Skip to content

feat: Milestone 6 — mechanism layer v1#11

Merged
shaypal5 merged 2 commits into
mainfrom
feat/milestone-6-mechanism-layer
Apr 28, 2026
Merged

feat: Milestone 6 — mechanism layer v1#11
shaypal5 merged 2 commits into
mainfrom
feat/milestone-6-mechanism-layer

Conversation

@shaypal5

Copy link
Copy Markdown
Contributor

Summary

  • mechanisms/base.pyMechanism ABC (sample(context, rng)), MechanismContext (latents + stage + t + extra), MechanismSummary (serialisable), MechanismAssignment (named instances for sim engine)
  • mechanisms/static.pyCategoricalDraw, BoundedNumericDraw, MixtureDraw
  • mechanisms/influence.pyAdditiveInfluence, LogisticInfluence, SaturatingInfluence, ThresholdInfluence, InteractionTerm
  • mechanisms/scores.pyLatentScore: logistic score from weighted latent combination; exposes .score() for deterministic use
  • mechanisms/hazards.pyConversionHazard: base_rate + scale * score, hard-capped at max_daily_rate
  • mechanisms/transitions.pyStageSequence: funnel stage registry + terminal detection; HazardTransition: dwell-aware daily advancement hazard
  • mechanisms/counts.pyPoissonIntensity (log-linear latent modulation), RecencyDecayIntensity (decay + floor)
  • mechanisms/categorical.pyCategoricalInfluence, CHANNEL_QUALITY_SCORES
  • mechanisms/measurement.pyNoisyProxy, NoisyCategorization, ProxyCompression
  • mechanisms/policies.pyassign_mechanisms(motif_family, rng): builds a fully wired MechanismAssignment with motif-tuned parameters for all 5 v1 motif families; mechanism_params_for_motif() for inspection

Test plan

  • 74 tests in tests/mechanisms/test_mechanisms.py
  • All mechanism types: output ranges, invalid-param validation, serialisation roundtrips
  • LatentScore: monotonicity, missing-key zero-contribution, empty-weights guard
  • ConversionHazard: probability bounds, monotone in fit, invalid-param guards
  • HazardTransition: min-dwell blocks at zero, invalid-param guards
  • StageSequence: next-stage chaining, terminal detection
  • PoissonIntensity/RecencyDecayIntensity: non-negative counts, decay monotonicity, floor
  • assign_mechanisms for all 5 motif families: callable, serialisable, summary roundtrip
  • Cross-motif ordering: fit_dominant > buying_committee_friction daily conversion probability
  • 437 total tests passing; ruff + mypy clean

🤖 Generated with Claude Code

Implements the full mechanism library in leadforge/mechanisms/:

base.py      — Mechanism ABC, MechanismContext, MechanismSummary,
               MechanismAssignment
static.py    — CategoricalDraw, BoundedNumericDraw, MixtureDraw
influence.py — AdditiveInfluence, LogisticInfluence, SaturatingInfluence,
               ThresholdInfluence, InteractionTerm
scores.py    — LatentScore (logistic from weighted latent combination)
hazards.py   — ConversionHazard (daily P(convert) = base + scale*score)
transitions.py — StageSequence (funnel order + terminal detection),
                 HazardTransition (dwell-aware daily advancement hazard)
counts.py    — PoissonIntensity (log-linear), RecencyDecayIntensity (decay+floor)
categorical.py — CategoricalInfluence, CHANNEL_QUALITY_SCORES
measurement.py — NoisyProxy, NoisyCategorization, ProxyCompression
policies.py  — assign_mechanisms(): motif-family-aware MechanismAssignment
               factory with tuned score weights for all 5 v1 motif families

74 tests covering all mechanism types, serialisation roundtrips, monotonicity
properties, edge-case validation, and cross-motif hazard ordering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 28, 2026 04:58
@shaypal5 shaypal5 added type: feature New capability layer: mechanisms mechanisms/ generators and transitions labels Apr 28, 2026
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces the Milestone 6 “mechanism layer v1” into leadforge/mechanisms/, providing a composable set of stochastic/deterministic mechanism primitives (scores, hazards, transitions, intensities, proxies) plus a motif-family-aware wiring policy, with a comprehensive new test suite.

Changes:

  • Added mechanism base contracts (Mechanism, MechanismContext, MechanismAssignment, MechanismSummary) and multiple mechanism families (static draws, influences, scores/hazards, transitions, counts, categorical lookup, measurement/proxy transforms).
  • Added assign_mechanisms() policy to construct a fully wired mechanism assignment per motif family, plus an inspection helper.
  • Added a large test module covering validation, ranges, serialization, determinism, and cross-motif ordering expectations.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
leadforge/mechanisms/base.py Defines the core mechanism interface, shared context carrier, and serializable assignment/summary containers.
leadforge/mechanisms/static.py Implements static distribution draws (categorical, bounded Gaussian, mixture).
leadforge/mechanisms/influence.py Implements latent-to-latent influence transforms (additive/logistic/saturating/threshold/interaction).
leadforge/mechanisms/scores.py Implements LatentScore for deterministic logistic scoring over latent weights.
leadforge/mechanisms/hazards.py Implements ConversionHazard as a daily boolean event driven by latent score.
leadforge/mechanisms/transitions.py Implements stage sequencing and a dwell-aware advancement hazard.
leadforge/mechanisms/counts.py Implements Poisson-like count/intensity mechanisms used for event generation.
leadforge/mechanisms/categorical.py Adds categorical lookup-based influence and default channel quality scores.
leadforge/mechanisms/measurement.py Implements noisy proxy observation and compression to categorical tiers.
leadforge/mechanisms/policies.py Wires motif-specific parameter tables into a complete MechanismAssignment.
tests/mechanisms/test_mechanisms.py Adds broad test coverage for parameter guards, output bounds, serialization, determinism, and policy wiring.
tests/mechanisms/init.py Adds the test package marker for mechanisms tests.
.agent-plan.md Updates the milestone tracking/status to reflect M6 completion and M7 focus.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread leadforge/mechanisms/static.py
Comment thread leadforge/mechanisms/measurement.py Outdated
Comment thread leadforge/mechanisms/scores.py Outdated
Comment thread leadforge/mechanisms/influence.py Outdated
@github-actions

This comment has been minimized.

- MixtureDraw: guard against negative mix_weights (COPILOT-1)
- ProxyCompression: strict adjacent-pair increase + (0,1) range checks (COPILOT-2)
- LatentScore.score: numerically stable two-branch sigmoid (COPILOT-3)
- influence._sigmoid: numerically stable two-branch sigmoid (COPILOT-4)
- Tests: overflow, duplicate/boundary threshold, negative weight cases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

pr-agent-context report:

This run includes unresolved review comments on PR #11.

For each unresolved review comment, recommend one of: resolve as irrelevant, accept and implement
the recommended solution, open a separate issue and resolve as out-of-scope for this PR, accept and
implement a different solution, or resolve as already treated by the code.

After I reply with my decision per item, implement the accepted actions, resolve the corresponding
PR comments, and push all of these changes in a single commit.

# Copilot Comments

## COPILOT-1
Location: leadforge/mechanisms/static.py:125
URL: https://github.com/leadforge-dev/leadforge/pull/11#discussion_r3151683664
Root author: copilot-pull-request-reviewer

Comment:
    `MixtureDraw` normalizes `mix_weights` but does not reject negative weights. Passing a negative value will later raise from `random.choices` at sample-time; validate `mix_weights` are all non-negative (and ideally mirror `CategoricalDraw`'s checks) so failures are early and consistent.

## COPILOT-2
Location: leadforge/mechanisms/measurement.py
URL: https://github.com/leadforge-dev/leadforge/pull/11#discussion_r3151683683
Status: outdated
Root author: copilot-pull-request-reviewer

Comment:
    `ProxyCompression` claims thresholds must be *strictly* increasing, but the check `thresholds != sorted(thresholds)` allows duplicates (e.g. `[0.5, 0.5]`) and does not enforce thresholds are within (0, 1) as documented. Tighten validation to require `0 < t < 1` and `thresholds[i] < thresholds[i+1]` for all adjacent pairs.

## COPILOT-3
Location: leadforge/mechanisms/scores.py
URL: https://github.com/leadforge-dev/leadforge/pull/11#discussion_r3151683693
Status: outdated
Root author: copilot-pull-request-reviewer

Comment:
    `LatentScore.score()` uses `1 / (1 + exp(-linear))`, which can raise `OverflowError` for sufficiently negative `linear`. Consider a numerically-stable sigmoid implementation (branch on sign or use `math.exp` in a stable form) so extreme weights/biases don't crash scoring.

## COPILOT-4
Location: leadforge/mechanisms/influence.py
URL: https://github.com/leadforge-dev/leadforge/pull/11#discussion_r3151683705
Status: outdated
Root author: copilot-pull-request-reviewer

Comment:
    `_sigmoid()` uses `1 / (1 + exp(-x))`, which can overflow for large negative `x` and crash callers. Switching to a numerically-stable sigmoid implementation avoids runtime errors for extreme parameterizations.

Run metadata:

Tool ref: v4
Tool version: 4.0.20
Trigger: commit pushed
Workflow run: 25037201298 attempt 1
Comment timestamp: 2026-04-28T06:17:55.101241+00:00
PR head commit: 5bdc40da2f5e3f77a06bbc1fc6981232f70d1357

@shaypal5 shaypal5 merged commit b92ad96 into main Apr 28, 2026
5 checks passed
@shaypal5 shaypal5 deleted the feat/milestone-6-mechanism-layer branch April 28, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

layer: mechanisms mechanisms/ generators and transitions type: feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants