Developer guide
PM Framework — Developer Guide (v1.0 → v7.10)
Technical reference for developers onboarding to the framework. Not the marketing narrative; the wiring.
Why this guide is here: the 2026-04-21 Google Gemini 2.5 Pro independent audit asked the framework to make its workings legible to external reviewers. v7.5 + v7.6 + v7.7 shipped the policy, mechanical, and validity-closure responses; this guide documents how the framework actually works, end to end, so an external operator (per Tier 3.3, GitHub issue #142) can replicate it on an unrelated product.
- Audience:
- Developers (not PMs, designers, HR, academic readers)
- Length:
- ~830 lines, 16 sections (incl. v7.8 §2.4 mechanism inventory + v7.8.1 gates in §10.1 + v7.9 §2.4.1 promoted sub-section)
- Last updated:
- 2026-06-21 at v7.10 — GATE_COVERAGE_ZERO observability + field-rename closure; T14 PLATFORMS_TESTED + F16 try-repo harness enforced (June 2026)
- Canonical source:
- docs/architecture/dev-guide-v1-to-v7-7.md (filename retained for ref-stability; content tracks v7.10)
Companion surfaces: Feature Lifecycle Event Catalog (the event/log/gate catalog with mermaid flow diagrams — 12 sections, paired with this guide), v7.9 case study (Advisory → Enforced Promotion: single-flag flip ships 3 gates after 14d calibration), v7.7 case study (Validity Closure synthesis), and Gemini audit on /trust (verbatim audit + appended response).
PM Framework — Developer Guide (v1.0 → v7.10)
Audience: developers landing in this codebase who need to understand how the PM framework actually works — not the marketing narrative, not the case-study story arc, but the wiring. If you are about to add a new feature, extend a check code, fix a CI workflow, or bump the framework version, start here.
Current version: v7.10 (shipped 2026-06-10 — GATE_COVERAGE_ZERO observability + measurement-layer field-rename closure; 0 new product-facing gates). Current canonical state (reconciled 2026-06-21): 115 features · 28 instrumented gates (17 write-time + 9 cycle-time + 2 W9 hooks), 25 firing · 0 integrity findings — see
docs/FRAMEWORK-FACTS.md. The detailed snapshot in §2.0 below is v7.9.1 (the last full-snapshot revision); v7.10 layered gate-self-observability on top of it. Predecessor v7.9.1 (single-day build window 2026-06-04 — 8 ships, 14 PRs, 0 new enforcement gates per Phase E exit discipline). The v7.9 Phase E validation soak exited cleanly on 2026-06-04. v7.9.1 ships observability surfaces + reusable substrates: F16 try-repo harness (a 3rd gate-test layer), F17last_fired_atindex, F2 Phase 0 reality-check, Dev-env Track B lint/coverage CI (CI workflows 8 → 14), observed-patterns W1–W28 → W1–W32. Post-window (2026-06-07) additions: t14platforms_testedfield +PLATFORMS_TESTEDgate (shipped advisory 2026-06-07; promoted to enforced 2026-06-21 via FT2 PR #781 after the clean 14-day B15 window),tracking-drift-check, contract-fixture sampling, and the prereg lock-introducing-commit permit fix. Enforcement total: 38 mechanical gates + 4 advisories (the v7.9 baseline was 37 + 5; PLATFORMS_TESTED moved from the advisory bucket to enforced on 2026-06-21). Shipped via FT2 PR #417 (v7.9) → v7.9.1 PRs #607–#628. For prior versions, see §12 timeline. For the full v7.9.1 outcome, see §2.0. Filename note: the source file staysdev-guide-v1-to-v7-7.md(this page mirrors it) for ref-stability across 16+ cross-references in FT2 + fitme-story. Content tracks the latest framework version (v7.10). Companion docs:docs/architecture/feature-lifecycle-event-catalog.md(event/log/gate catalog with mermaid flow diagrams),docs/skills/architecture.md(skill-by-skill anatomy),docs/skills/evolution.md(full version-by-version history),CLAUDE.md(project rules, fastest reference). Reading order: §0 is a 90-second tour. §1 is audience and reading hints. §1.5 is the glossary. §§ 2–3 give you the mental model. §§ 4–8 are the schemas and contracts you'll edit against. §§ 9–11 are the integrity layer (where failures get caught). § 12 is the compressed timeline. §§ 13–15 are operational walkthroughs.
Table of Contents
- §0. Overview — 90-second tour
- §1. Audience and how to read
- §1.5 Glossary
- §2. Big picture (current state — v7.9.1, Phase E exited)
- §3. Where the code lives
- §4. The skill ecosystem (hub + 11 spokes)
- §5.
state.json— the canonical per-feature contract - §6. Phase lifecycle (9 phases × 4 work types)
- §7. Dispatch model — how skills get invoked
- §8. Cache architecture (L1 per-skill, L2 shared, L3 project)
- §9. Measurement protocol (CU formula, cache_hits, timing)
- §10. Integrity layer — write-time + per-PR + cycle-time + weekly
- §11. Pre-commit hooks and GitHub Actions
- §12. Compressed evolution timeline (v1.0 → v7.9.1)
- §13. Operational walkthrough — adding a new feature
- §14. Operational walkthrough — extending an integrity check code
- §15. Operational walkthrough — bumping the framework version
- §16. References
0. Overview — 90-second tour
What this framework does. Every feature passes through a 9-phase lifecycle (Research → PRD → Tasks → UX → Implement → Test → Review → Merge → Docs) and is gated by automated checks at four cadences. Drift between code and documentation is caught fast.
The 4 enforcement layers (§2.2):
| Layer | Cadence | Where it lives |
|---|---|---|
| 1. Write-time | every git commit (~3-5s) | .githooks/pre-commit |
| 2. Per-PR | every push to a PR (~1-3min) | .github/workflows/pr-integrity-check.yml |
| 3. 72h cycle | cron, every 3 days at 04:00 UTC | .github/workflows/integrity-cycle.yml |
| 4. Weekly | cron, Mondays 05:00 UTC | .github/workflows/framework-status-weekly.yml |
The 1 file you touch most. .claude/features/<name>/state.json — your feature's lifecycle contract. Schema is enforced at write-time.
The 1 command you run most. /pm-workflow <feature-name> — creates state.json, drives phase transitions, dispatches the right skill per phase, gates each transition.
Where to next.
- New to the framework? → §1 (audience) → §1.5 (glossary) → §2 (big picture) → §3 (where the code lives)
- Writing a feature? → §13 walkthrough
- Adding a check code? → §14 walkthrough
- Bumping the framework version? → §15 walkthrough (and: don't forget to bump THIS doc — see §15's "what NOT to skip" callout)
1. Audience and how to read
This guide is for developers. If you are a PM looking for product workflow, read docs/skills/pm-workflow.md. If you are reading the project as evidence of an AI workflow approach, start with docs/case-studies/ (start at 01-onboarding-pilot.mdx on the fitme-story showcase).
The framework is not a single library you import. It is a set of conventions implemented across:
- Markdown documents that describe each skill (
.claude/skills/<name>/SKILL.md) and shared state (.claude/shared/*.json). - Python scripts that enforce or measure invariants (
scripts/*.py). - GitHub Actions workflows that run the scripts on schedules and on every PR (
.github/workflows/*.yml). - A pre-commit hook that runs the same scripts locally before any commit lands (
.githooks/pre-commit). - Per-feature state files that track each in-flight feature's lifecycle (
.claude/features/<name>/state.json).
There is no compiled binary. The framework is the union of the conventions above, the scripts that enforce them, and the agents (Claude Code, Claude Desktop, Codex, etc.) that follow them.
1.5 Glossary
Cross-cutting terms used throughout this guide and in commit messages, PR descriptions, and case studies. If a term is unfamiliar in §§ 2–15, look it up here first.
| Term | Definition |
|---|---|
| Mechanism A–F | The six v7.8 bridge mechanisms (§2.4). A = coverage-asserting gates (gate-coverage.jsonl). B = schema field-rename detection + dual-read. C = PostToolUse:Read attribution (auto-captures cache hits). D = pre-commit hook header self-audit. E = custom git merge driver for append-only ledgers. F = membrane status advisory (make membrane-status). |
| T1 / T2 / T3 | Data quality tiers for every quantitative claim in a PRD, case study, or meta-analysis. T1 = Instrumented (live metric). T2 = Declared (PRD target / pre-registered). T3 = Narrative (estimate). |
| Class A / B / C | Gate categorization. Class A = mechanically enforced. Class B = mechanically unclosable (requires judgment, external operator, or physical device — see §2.3, currently 4 gaps). Class C = advisory en route to enforced after a calibration window. |
| Advisory vs enforced | An advisory gate emits a finding but does NOT block a commit. An enforced gate blocks. Most v7.8 mechanisms ship advisory, then promote to enforced after ≥7 days of Mechanism A telemetry shows zero false positives. v7.9 promoted 3 advisories to enforced via a single-flag flip (§2.0). |
| Write-time / Per-PR / Cycle-time / Weekly | The 4 enforcement layers (§2.2). Write-time = pre-commit (every commit). Per-PR = GitHub Actions on every push. Cycle-time = 72h cron. Weekly = Mondays 05:00 UTC, observational. |
| CU (Composite Units) | The v6.0 measurement protocol's normalized "size of work" score. CU formula v2 has 4 continuous factors: complexity, blast_radius, novelty, verification_difficulty. See §9.1. |
| Gate vs check code | A gate is the mechanism (a script that runs at a given cadence). A check code is the finding type the gate emits (e.g., SCHEMA_DRIFT, PHASE_LIE). One gate emits multiple check codes. |
| Skill / spoke / hub | The framework runs as 12 skills. pm-workflow is the hub (always loaded). The other 11 are spokes (loaded on demand based on the active phase per skill-routing.json). See §4. |
| Phase E | A post-promotion validation soak (typically 14 days) where no new gates ship and the operator watches gate-coverage.jsonl for unexpected failure rows. v7.9 Phase E ran 2026-05-21 → 2026-06-04 and exited cleanly; the v7.9.1 build window opened at exit (§2.0). |
| state.json | Per-feature canonical contract at .claude/features/<name>/state.json. The single source of truth for that feature's lifecycle. See §5. |
/pm-workflow | The agent command that creates state.json, drives phase transitions, dispatches the right skill per phase. The 1 command you run most. |
| Observed Patterns Catalog | .claude/integrity/observed-patterns.md (v7.8.5). The canonical manifest of gate-firing patterns — 23 gate patterns + W1–W32 workflow patterns (W29–W32 added at v7.9.1). When a gate fires, consult it FIRST (§10.5). make observed-patterns. |
make preflight | The unified pre-work aggregator (v7.8.6). make preflight WORK_TYPE=<type> runs every pre-work check (ssh-agent, PR-cache freshness, branch isolation, integrity findings, drift-vs-anchor, doc-debt, adoption, W20 freshness) into preflight-cache.json. Mandatory Phase 0.0 step (§10.6). |
state_owner | Required top-level state.json enum ({ft2, fitme-story}, v7.8.3) declaring which repo holds the canonical state file. Enforced by the STATE_OWNER_* gates. |
platforms_tested | state.json object {ios, web, backend, ai} of booleans (T14, 2026-06-07) recording which platforms a feature's tests exercised. PLATFORMS_TESTED gate fires at current_phase=complete when none is set; framework-meta features exempt. Enforced as of 2026-06-21 (PR #781). See §5.1. |
| F16 / F17 / F2 | Three v7.9.1 substrates. F16 = try-repo harness (3rd gate-test layer — spawns a throwaway repo + runs the real pre-commit). F17 = gate-last-fired.json derived per-gate index. F2 = Phase 0 reality-check sub-step (make phase-0-reality-check) catching post-squash-merge state drift. |
| snapshot-phase / integrity-diff | make snapshot-phase (v7.8.3) writes a per-phase off-SSD backup; make integrity-diff (v7.8.6) diffs current platform state vs the 2026-05-14 baseline anchor. |
2. Big picture (current state — v7.9.1, Phase E exited)
2.0 Current version snapshot (v7.9.1, 2026-06-04)
v7.9.1 — single-day build window (2026-06-04). Opened at v7.9 Phase E exit and closed the same day: 8 ships across 14 PRs with 0 new enforcement gates (Phase E exit discipline forbids new gates for the first 14 days post-promotion). Every ship is an observability surface, doc update, reusable substrate, or warn-only CI workflow:
- F16 try-repo harness (PRs #607–#612) — a 3rd gate-test layer: spawns a throwaway git repo and runs the real
.githooks/pre-commitagainst canonical positive/negative fixtures, catching integration-surface bugs the in-process dispatch tests can't see. - F17
last_fired_atindex (#617) —gate-last-fired.json, a derived per-gate index of Mechanism A telemetry (AWS-Config-Rules pattern) so the planned v7.10GATE_COVERAGE_ZEROmeta-check runs O(1) per gate. - F2 Phase 0 reality-check (#618) —
make phase-0-reality-checkcross-checks pending tasks vs the last 30 days of git/PR/log evidence, surfacing post-squash-merge state drift before Phase 0 schedules stale work. - Dev-env Track B + batch (#619, #626, #627) — SwiftLint + ruff + markdownlint + coverage + gitleaks + pip-audit + SBOM + commitlint + shellcheck wired warn-only into CI (workflows 8 → 14).
- F-LAUNCHD-DRIFT-EXTENSION (#621–#624) — cron-context phantom-finding suppression + plist path-resolution health checks.
- Observed-patterns W29–W32 (#620) + F-PHASE-E-ADOPTION-FREEZE-DISCIPLINE (#625) + F-DEPLOYED-URL-PROBE FT2 substrate (#628).
Post-window additions (2026-06-07): t14 platforms_tested field + PLATFORMS_TESTED gate (FT2 #662 / #665 — shipped advisory, promoted to enforced 2026-06-21 via FT2 #781); tracking-drift-check (#659); the prereg lock-introducing-commit permit fix (#660); contract-fixture sampling consumer adoption (fitme-story #209). Shipped advisory/observability; PLATFORMS_TESTED later promoted to enforced (2026-06-21, cadence B15).
Predecessor — v7.9 promotion (2026-05-21): the enforcement-flip release. A single-line edit at scripts/check-state-schema.py:138 flipped BRANCH_ISOLATION_ADVISORY_MODE from True to False, promoting 3 v7.8.1 advisory gates simultaneously to enforced.
Gates promoted (3 advisory → 3 enforced):
| Gate | 14d telemetry | Skip reasons (all legit) |
|---|---|---|
BRANCH_ISOLATION_VIOLATION Mode B (infra commit-level) | 18 firings, 0 zero-candidate | not_infra_commit_level × 13 |
BRANCH_ISOLATION_VIOLATION Mode C (per-state.json) | 13 firings, 0 zero-candidate | separate emission key |
FEATURE_CLOSURE_COMPLETENESS (write-time) | 13 firings, 0 zero-candidate | not_complete_transition × 11, no_phase_change × 1 |
All four §2.2 promotion criteria (coverage ≥ 7d, no false positives, no silent skips, reversibility < 5 min) were met. Phase E validation soak runs 2026-05-21 → 2026-06-04.
Gates that stay advisory by design (NOT promoted at v7.9):
| Gate | Why |
|---|---|
BRANCH_ISOLATION_HISTORICAL cycle-time | T17 forward-only audit — historical features predating the gate cannot retroactively pass |
BRANCH_ISOLATION_LAUNCHD_DRIFT cycle-time | T18 macOS-only — environment-specific |
FEATURE_CLOSURE_COMPLETENESS cycle-time mirror | T19 --no-verify bypass catcher — fires when the write-time gate is bypassed |
Reversibility: single-line revert + commit + merge to main = < 5 min.
Full lineage: v7.9 case study | v7.9 entrypoint | FT2-FH-003 honesty ledger entry.
2.1 What the framework does, in one sentence
It enforces that every feature passes through a defined lifecycle (Research → PRD → Tasks → UX → Implement → Test → Review → Merge → Docs), records its state and timing in a machine-readable file, and is gated by automated checks at write-time, per-PR, and on a 72h schedule so that drift between code and documentation is caught fast.
2.2 The four enforcement layers (v7.9 — 3 advisories promoted to enforced 2026-05-21)
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 1 — WRITE-TIME (pre-commit hooks, ~3-5s) │
│ Fires on every `git commit`. Blocks the commit if it fails. │
│ Scripts: scripts/check-state-schema.py + check-case-study-preflight │
│ Check codes: SCHEMA_DRIFT, PR_NUMBER_UNRESOLVED, │
│ PHASE_TRANSITION_NO_LOG, PHASE_TRANSITION_NO_TIMING, │
│ BROKEN_PR_CITATION (write-time), │
│ CASE_STUDY_MISSING_TIER_TAGS │
└─────────────────────────────────────────────────────────────────────┘
│ ▲
│ commit lands │ also runs as
▼ │ rear-guard
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 2 — PER-PR (GitHub Actions, ~1-3min per push) │
│ Workflow: .github/workflows/pr-integrity-check.yml │
│ Compares PR HEAD findings vs origin/main baseline (worktree). │
│ Status check: pm-framework/pr-integrity → required for merge. │
└─────────────────────────────────────────────────────────────────────┘
│ PR merges to main
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 3 — 72h CYCLE (GitHub Actions cron, every 3 days at 04:00Z) │
│ Workflow: .github/workflows/integrity-cycle.yml │
│ Script: scripts/integrity-check.py (13 cycle-time + 1 advisory) │
│ Snapshots ledger to .claude/integrity/snapshots/. │
│ Opens issue on regression vs prior snapshot. │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 4 — WEEKLY (GitHub Actions cron, Mondays 05:00Z) │
│ Workflow: .github/workflows/framework-status-weekly.yml │
│ Snapshots measurement-adoption-history.json + documentation-debt. │
│ Opens issue on adoption regression. OBSERVATIONAL (does not block).│
└─────────────────────────────────────────────────────────────────────┘
2.3 The 4 mechanically unclosable Class B gaps (v7.8 closed Gap 1 in advisory; v7.9 promoted it to enforced)
The four layers above catch what a deterministic script can catch. Five gaps remained Class B (agent-attention, judgment, or external-dependency) at v7.7. v7.8 closed Gap 1 (cache_hits[] writer-path) in advisory mode via Mechanism C — capture is automatic, but writer-path adoption was not yet enforced. v7.9 (2026-05-21) promoted Gap 1 to enforced via CACHE_HITS_AUTO_INSTRUMENTATION_DRIFT (cycle-time gate, advisory → enforced once 14-day Mechanism A telemetry showed 0 zero-candidate firings). Same release also promoted 2 v7.8.1 branch-isolation advisories — BRANCH_ISOLATION_VIOLATION Mode B (infra commit-level) + Mode C (per-state.json mutation) + FEATURE_CLOSURE_COMPLETENESS (write-time). The list is documented in docs/case-studies/meta-analysis/unclosable-gaps.md:
cache_hits[]writer-path adoption — ✅ CLOSED at v7.9 (was issue #140, agent-must-remember-to-log-hits, the original Class B gap). Closed via the v7.8 advisoryPostToolUse:Readhook (Mechanism C) → promoted to enforced at v7.9 viaCACHE_HITS_AUTO_INSTRUMENTATION_DRIFT. Pre-Mechanism-C features (created_at < 2026-05-02) remain exempt fromCACHE_HITS_EMPTY_POST_V6.cu_v2factor correctness — magnitudes are judgment-based.- T1/T2/T3 tag correctness — preflight checks presence, not whether the tag is right.
- Tier 2.1 real-provider auth — physical device required.
- Tier 3.3 external replication — external operator required.
If you are a developer reading this guide, your code rarely needs to reason about Class B gaps directly — they exist as documented exceptions to the "everything is mechanical" framing. But if you are adding a check code, ask: "is what I'm checking deterministic, or am I trying to mechanize a judgment?" The latter belongs in the Class B inventory, not in check-state-schema.py.
2.4 The v7.8 bridge mechanisms (A–F)
v7.8 (shipped 2026-05-04 across 9 PRs: #173 + #185–#189 + #193–#195) added six cooperating mechanisms that close silent-pass and inter-agent context-handoff gaps without yet promoting them to Class A. All ship advisory; v7.9 (measurement window opens 2026-05-11) promotes the proven ones to enforced.
| Mech | Name | What it does | Where the data lands |
|---|---|---|---|
| A | Coverage-asserting gates | Every write-time gate emits {candidates, checked, skipped, skip_reasons} per run; GATE_COVERAGE_ZERO advisory fires when a gate stays at checked=0 for 7+ days | .claude/logs/gate-coverage.jsonl |
| B | Schema field-rename detection + dual-read | created ∪ created_at dual-read for migration window; canonical framework_version field on all features; agent_manifest + _meta.deprecation_warnings schema bridges populated but un-validated until v7.9 | scripts/migrate-state-v7-8-bridge.py |
| C | PostToolUse:Read attribution | Auto-captures Read events with active-feature tag; advisory CACHE_HITS_AUTO_INSTRUMENTATION_INACTIVE fires when session ledger has Reads but state.json::cache_hits[] is empty | .claude/logs/_session-<id>.events.jsonl + .claude/active-feature lockfile |
| D | Pre-commit hook header self-audit | Validates the hook header matches the implementation (catches drift between docstring and code) | make pre-commit-self-test → scripts/pre-commit-self-test.py |
| E | Custom git merge driver | Auto-resolves merge conflicts on append-only ledgers (measurement-adoption-history.json, documentation-debt.json) via union-dedup-by-key | scripts/merge-driver-dedup.py; registered by make install-hooks; .gitattributes opts in |
| F | Membrane status advisory | Single readout: active feature + recent gate firings + dispatch-blocker state — closes inter-agent context-handoff gap | make membrane-status → scripts/membrane-status.py; surfaced via SessionStart hook |
Full design: docs/superpowers/specs/2026-05-02-framework-v7-8-and-v7-9-bridge-design.md. Live append-only journal: docs/case-studies/framework-v7-8-bridge-case-study.md.
The v7.8 design principle: every new mechanism ships with a coverage ledger (Mechanism A) so we can measure its effective coverage before promoting to enforced. v7.7's CACHE_HITS_EMPTY_POST_V6 shipped at 0/46 effective coverage for 4 days because the gate read created_at while 43/46 features used the legacy created key — a silent-pass that Mechanism A would have caught immediately. v7.8's lesson is that we don't trust a gate until its coverage ledger says it's actually firing.
3. Where the code lives
FitTracker2/
├── .claude/
│ ├── features/<feature-name>/state.json ← per-feature state (1 per feature)
│ ├── logs/<feature-name>.log.json ← per-feature contemporaneous log
│ ├── shared/ ← shared cross-feature state
│ │ ├── framework-manifest.json ← framework version + capabilities
│ │ ├── feature-registry.json ← list of all features
│ │ ├── change-log.json ← cross-feature change events
│ │ ├── measurement-adoption.json ← v6.0 adoption ledger (current)
│ │ ├── measurement-adoption-history.json ← v6.0 adoption (append-only)
│ │ ├── documentation-debt.json ← Tier 3.2 debt ledger
│ │ ├── case-study-monitoring.json ← case-study health
│ │ ├── skill-routing.json ← skill phase routing config
│ │ └── … (~24 shared state files total)
│ ├── skills/<skill-name>/SKILL.md ← agent-facing skill prompt (12 skills since 2026-05-14; was 11 through v7.8.4)
│ ├── integrations/<service>/ ← per-service adapters (ga4, sentry…)
│ ├── cache/ ← learning cache (L1 + L2 _shared/ + L3 _project/)
│ └── integrity/
│ ├── README.md ← integrity layer canonical entry
│ ├── observed-patterns.md ← gate-firing pattern catalog (v7.8.5; make observed-patterns)
│ └── snapshots/ ← 72h cycle snapshots (committed)
├── scripts/
│ ├── check-state-schema.py ← write-time + cycle (state.json + branch-isolation + state_owner gates)
│ ├── check-case-study-preflight.py ← write-time (case studies)
│ ├── integrity-check.py ← cycle-time check codes + advisories
│ ├── ensure-pr-cache-fresh.py ← PR_CACHE_STALE auto-refresh (v7.8.4)
│ ├── observe-cache-hit.py ← Mechanism C PostToolUse:Read capture (v7.8)
│ ├── check-branch-drift.py ← W9 branch-drift PostToolUse:Bash alert (v7.8.5)
│ ├── check-ssh-agent.sh ← W1 ssh-agent SessionStart preflight (v7.8.6)
│ ├── membrane-status.py ← Mechanism F membrane readout
│ ├── preflight.py ← unified pre-work aggregator (v7.8.6)
│ ├── cross-layer-freshness.py ← W20 freshness scan (v7.8.6)
│ ├── daily-integrity-checkpoint.py ← daily launchd cron job
│ ├── integrity-diff.py ← diff vs baseline anchor (v7.8.6)
│ ├── snapshot-phase-completion.sh ← per-phase off-SSD backup (v7.8.3)
│ ├── measurement-adoption-report.py ← Tier 1.1 ledger generator
│ ├── append-feature-log.py ← contemporaneous log writer
│ ├── documentation-debt-report.py ← Tier 3.2 ledger generator
│ ├── runtime-smoke-gate.py ← Tier 2.1 smoke runner
│ └── test-v7-5-pipeline.sh ← mechanical-enforcement regression test
├── .githooks/pre-commit ← orchestrates write-time checks
├── .github/workflows/
│ ├── ci.yml ← Xcode build + test
│ ├── integrity-cycle.yml ← 72h cycle (cron 0 4 */3 * *)
│ ├── pr-integrity-check.yml ← per-PR (v7.6 Phase 2a)
│ └── framework-status-weekly.yml ← weekly cron (v7.6 Phase 2c)
├── docs/
│ ├── architecture/
│ │ └── dev-guide-v1-to-v7-7.md ← THIS FILE
│ ├── skills/
│ │ ├── architecture.md ← skill-by-skill anatomy
│ │ ├── evolution.md ← full version-by-version history
│ │ └── pm-workflow.md ← user-facing PM workflow doc
│ ├── case-studies/ ← all shipped case studies
│ │ ├── data-integrity-framework-v7.5-case-study.md
│ │ ├── mechanical-enforcement-v7-6-case-study.md
│ │ └── meta-analysis/unclosable-gaps.md
│ ├── process/ ← process docs (Tier groundwork)
│ ├── product/ ← PRDs, metrics, backlog
│ └── design-system/ ← UX foundations + component memory
├── trust/
│ └── audits/2026-04-21-gemini/ ← independent audit + remediation
└── CLAUDE.md ← project rules (fastest reference)
Companion repo (separate git): /Volumes/DevSSD/fitme-story — Next.js showcase site. Trust page (/trust/audits/2026-04-21-gemini) and case-studies index live there. The fitme-story repo cross-links to the main repo's case studies via raw GitHub URLs.
4. The skill ecosystem (hub + 11 spokes)
The framework runs as 12 skills (since 2026-05-14; was 11 through v7.8.4) following a hub-and-spoke pattern:
- Hub:
pm-workflow— owns the lifecycle, dispatches work to spokes, gates phase transitions. - Spokes (11):
brainstorm-pm(added 2026-05-14, P1.0b — Phase 0 default new-feature entry point),research,ux,design,dev,qa,analytics,cx,marketing,release,ops— each owns a phase or cross-cutting responsibility.
Each skill has:
- An agent-facing prompt at
.claude/skills/<name>/SKILL.md. The agent reads this when the skill is loaded. - A markdown doc at
docs/skills/<name>.mdfor human reference. - A routing config entry in
.claude/shared/skill-routing.jsondeclaring which phases load this skill on demand (v5.0 skill-on-demand optimization).
4.1 Skill loading model (v5.0+)
Before v5.0, all 11 skills (the v2.0–v7.8.4 baseline) loaded into context on every session. After v5.0:
- The
pm-workflowhub always loads. - Spokes load on demand based on
phase_skillsinskill-routing.json. - Each spoke has a
compressed_viewfield in its cache entry (~200 words) loaded by default; full expansion happens when the agent calls the skill. - Net savings: ~54K tokens per session vs. v4.x.
4.2 Adding a new skill
- Create
.claude/skills/<name>/SKILL.mdwith the agent-facing prompt. - Create
docs/skills/<name>.mdfor human reference. - Add an entry to
.claude/shared/skill-routing.json:{ "phase_skills": { "<phase>": ["<existing-skills>", "<name>"] }, "compressed_views": { "<name>": "≤200-word summary of what the skill does" } } - Bump
framework-manifest.json.structure.spoke_skills(currently 10).
5. state.json — the canonical per-feature contract
Every feature has a .claude/features/<name>/state.json file. This file is the single source of truth for that feature's lifecycle state. The integrity layer reads it; the dashboard reads it; the case study links to it.
5.1 Required top-level fields
| Field | Type | Notes |
|---|---|---|
name | string | Feature slug, must match directory name |
work_type | enum | "feature", "enhancement", "fix", "chore", "framework", "refactor" |
current_phase | enum | One of: research, prd, tasks, ux_or_integration, implement, test, review, merge, docs, complete. DO NOT use phase — that key is rejected by SCHEMA_DRIFT (canonical is current_phase). |
created | ISO 8601 timestamp | Used by measurement-adoption-report.py to bucket pre/post-v6.0 features |
phases | object | One key per phase entered, with started_at (ISO 8601). Phase M adds ended_at when leaving for phase N>M. |
tasks | array | Task list for Phase 3 (tasks phase) onward |
complexity | object | v6.0 protocol: cu_version, factors_applied[], view_count, etc. (see § 9.1) |
timing | object | v6.0 protocol: session_start, total_wall_time_minutes, per-phase started_at/ended_at |
cache_hits | array | v6.0 protocol: each entry is {timestamp, level, key, type, skill, event_type, phase} |
state_owner | enum | {ft2, fitme-story} (v7.8.3) — which repo holds the canonical state file. Enforced by STATE_OWNER_*. |
platforms_tested | object | {ios, web, backend, ai} booleans (T14, 2026-06-07) — which platforms the feature's tests exercised. PLATFORMS_TESTED gate at current_phase=complete; framework-meta features exempt. Companion platforms_tested_provenance string records origin. Enforced as of 2026-06-21 (PR #781). |
5.2 Phase-specific sub-fields
Each entered phase typically also has:
phases.<phase>.completed_at— when the phase finished (set on transition out)phases.<phase>.gate_passed— boolean if a hard gate (e.g., review approval) was requiredphases.merge.pr_number— set during the merge phase; verified by thePR_NUMBER_UNRESOLVEDcheck
5.3 Schema enforcement
scripts/check-state-schema.py reads each staged state.json (or, with --all, every state.json in the repo) and emits findings:
SCHEMA_DRIFT— legacyphasekey presentNO_PHASE— neithercurrent_phasenorphasepresentINVALID_JSON— file does not parsePHASE_TRANSITION_NO_LOG(v7.6) — phase changed but no log entry within last 15 minPHASE_TRANSITION_NO_TIMING(v7.6) — phase changed but notiming.phases.<new>.started_atand/or old-phaseended_atupdate
The --staged flag scopes the check to staged files (used by the pre-commit hook). The FORCE_TRANSITION_CHECKS=1 env var unscopes for testing.
6. Phase lifecycle (9 phases × 4 work types)
The PM framework defines a 9-phase pipeline for full features. Smaller work types skip subsets of phases.
| Phase | Skill driver | Output | Required for |
|---|---|---|---|
1. research | research | docs/product/research/<name>.md | Feature |
2. prd | pm-workflow | docs/product/prd/<name>.md | Feature, Enhancement |
3. tasks | pm-workflow | state.json.tasks[] | Feature, Enhancement |
4. ux_or_integration | ux + design | docs/design-system/<name>-spec.md | Feature (UI), or skipped + recorded as work_type:fix etc. |
5. implement | dev | code | All work types |
6. test | qa | XCTest + CI green | All except chore |
7. review | reviewer + qa | Approved PR | Feature, Enhancement |
8. merge | release | Commit on main + pr_number set | All |
9. docs | pm-workflow + cx | Case study + state.json closed | Feature, Enhancement |
6.1 Work types
Defined in CLAUDE.md (Work Item Types section):
- Feature — full 9-phase. New capabilities. Weight 1.0 in CU formula.
- Enhancement — 4-phase (Tasks → Implement → Test → Merge). Improvements to shipped features. Weight 0.8.
- Fix — 2-phase (Implement → Test). Bug fixes. Weight 0.5.
- Chore — 1-phase (Implement). Docs, config. Weight 0.3.
- Refactor (v2) — like Feature but v1 exists as reference. Weight 0.9.
- Framework — internal infrastructure (e.g., this dev guide, v7.6 itself). No fixed weight; choose nearest analog.
6.2 The "v2/" subdirectory rule
When refactoring a UI screen, the v2 file lives at <parent>/v2/<ScreenName>.swift. Same Swift type name; v1 stays in repo as historical artifact (removed from build target via project.pbxproj). Full rule: CLAUDE.md → "## UI Refactoring & V2 Rule".
7. Dispatch model — how skills get invoked
The agent (Claude Code, Codex, etc.) interacts with the framework primarily via slash commands that invoke skills:
/pm-workflow <feature-name> ← hub: starts/resumes a feature
/dev ← spoke: implementation work
/qa ← spoke: test work
/design / /ux ← spoke: design + UX
/analytics / /cx / /research ← spoke: cross-cutting
/marketing / /release / /ops ← spoke: support
When the user types a slash command, the runtime looks up the corresponding SKILL.md and loads its content into the agent's context. The agent then follows the skill's instructions.
7.1 Routing logic (v5.2 Dispatch Intelligence)
scripts/dispatch-intelligence.py and .claude/shared/dispatch-intelligence.json define a 3-stage dispatch pipeline:
- Tool budget check — does the requested skill fit within the per-session tool budget?
- Hardware affinity (v7.0 HADF) — does the current device profile favor a particular skill variant?
- Skill execution — invoke the skill with appropriate cache pre-load.
For most local Claude Code sessions, the dispatch pipeline is invisible — it just makes routing decisions before the agent picks up the work.
7.2 Concurrent dispatch hygiene
Per CLAUDE.md "## Concurrent Dispatch Hygiene": parallel subagent dispatch is currently blocked at the framework layer (F6–F9 framework bugs). Default to serial. Re-validation gate after upstream patches: docs/superpowers/plans/f6-f9-reproducer/proof-of-fix-tests.md.
8. Cache architecture (L1 per-skill, L2 shared, L3 project)
The framework treats agent reasoning as a cache hierarchy:
| Level | Scope | Location | Lifetime |
|---|---|---|---|
| L1 | Per-skill | .claude/cache/<skill>/ | Session-scoped; skill-internal |
| L2 | Cross-skill (shared) | .claude/cache/_shared/ | Session-scoped; multiple skills can read |
| L3 | Project-wide | .claude/cache/_project/ | Persistent across sessions |
8.1 Cache hits — the writer path
When an agent reuses a piece of prior knowledge (a skill output, a doc snippet, a prior plan, a memory entry) instead of re-deriving it, that's a cache hit. The agent logs it via:
python3 scripts/append-feature-log.py \
--feature <feature-name> \
--event-type code_change \
--summary "<what changed>" \
--artifact "<file>" \
--cache-hit L2 \
--cache-key "<a stable key>" \
--cache-hit-type {adapted,exact,miss} \
--cache-skill "<source skill or pattern reused>"The script writes the entry to .claude/logs/<feature>.log.json AND appends to state.json.cache_hits[]. The dual-write is intentional: logs are flat-file event streams, state.json is the canonical roll-up.
8.2 What the framework can and cannot mechanize
- Mechanizable: the writer path (CLI accepts the flags, schema validates the entry, count rolls up to
measurement-adoption.json). - Not mechanizable: the recognition that something is a cache hit. This is Class B Gap 1. The framework provides the infrastructure; the agent must remember to use it.
9. Measurement protocol (CU formula, cache_hits, timing)
Shipped at v6.0 (2026-04-16). Hardened across v7.5 → v7.6. Canonical doc: docs/case-studies/normalization-framework.md.
9.1 The CU formula (v6.0)
CU = Tasks × Work_Type_Weight × (1 + sum(Complexity_Factors))
Work-type weights:
| Type | Weight |
|---|---|
| Feature | 1.0 |
| Enhancement | 0.8 |
| Fix | 0.5 |
| Chore | 0.3 |
| Refactor (v2) | 0.9 |
| Framework | (choose nearest analog; commonly 0.9) |
Complexity factors (additive):
| Factor | Value | Source |
|---|---|---|
| Has UI (1 view) | +0.15 | state.json.complexity.view_count |
| Has UI (2-3 views) | +0.30 | same |
| Has UI (4+ views) | +0.45 | same |
| Design Iteration (text) | +0.10 per round | state.json.complexity.design_iteration_details[] |
| Design Iteration (layout) | +0.15 per round | same |
| Design Iteration (interaction) | +0.20 per round | same |
| Design Iteration (full redesign) | +0.25 per round | same |
| New Model/Service (1-2 types) | +0.1 | state.json.complexity.new_types_count |
| New Model/Service (3-5) | +0.2 | same |
| New Model/Service (6+) | +0.3 | same |
| Auth/External (binary) | +0.5 | binary flag |
| Runtime Testing (binary) | +0.4 | binary flag |
| Cross-Feature (binary) | +0.2 | binary flag |
| Architectural Novelty (binary) | +0.2 | state.json.complexity.is_first_of_kind |
The agent declares factors in state.json.complexity.factors_applied[] with a reason string per factor. The script does not auto-derive magnitudes — that's Class B Gap 2.
9.2 Velocity reporting
After phase completion, state.json.timing.total_wall_time_minutes should be set. Velocity = total_wall_time_minutes / CU. The v6.0 protocol requires three baseline comparisons:
- vs Historical (Onboarding v2 = 15.2 min/CU)
- vs Rolling (mean of last 5 features)
- vs Same-Type (mean of last 3 same work_type)
scripts/measurement-adoption-report.py reports per-feature adoption status across 4 dimensions: timing_wall_time, per_phase_timing, cache_hits, cu_v2. A feature is "fully adopted" only when all 4 dimensions are populated.
9.3 Tier tags (T1/T2/T3)
Every quantitative claim in a case study, PRD, or meta-analysis should carry a tier tag:
- T1 (Instrumented) — pulled from a JSON file or deterministic command output.
- T2 (Declared) — declared by the author from a non-instrumented source (e.g., human-counted from
git log). - T3 (Narrative) — narrative inference; should be avoided in v7.6+ case studies.
Forward-only: case studies dated >= 2026-04-21 get file-level tag-presence enforcement at write-time (CASE_STUDY_MISSING_TIER_TAGS). The preflight checks that at least one T1/T2/T3 tag exists in the scoped file. Tag exhaustiveness and correctness are Class B Gap 3 — code review still checks whether each metric has the right tag.
10. Integrity layer — write-time + per-PR + cycle-time + weekly
10.1 Check codes (38 mechanical + 4 advisories — PLATFORMS_TESTED promoted advisory → enforced 2026-06-21, FT2 PR #781)
v7.9 promotion (2026-05-21): 3 v7.8.1 advisories promoted to enforced:
BRANCH_ISOLATION_VIOLATIONMode B (infra commit-level) + Mode C (per-state.json mutation) +FEATURE_CLOSURE_COMPLETENESS(write-time). Single-flag flip atscripts/check-state-schema.py:138(BRANCH_ISOLATION_ADVISORY_MODE = True → False). All 4 §2.2 promotion criteria met against 14-day Mechanism A telemetry (18 + 13 + 13 firings, 0 zero-candidate, 0 false positives). Phase E validation soak runs 2026-05-21 → 2026-06-04. Reversibility: single-line revert.When a gate fires, check the Observed Patterns Catalog (§10.5) FIRST — most fire-patterns are documented there with a signal-vs-noise rule and a silence path.
| Code | Layer | Script | What it checks |
|---|---|---|---|
SCHEMA_DRIFT | Write + cycle | check-state-schema.py | Legacy phase key present (canonical is current_phase) |
NO_PHASE | Write + cycle | check-state-schema.py | Neither current_phase nor phase present |
INVALID_JSON | Write + cycle | check-state-schema.py | File does not parse |
PR_NUMBER_UNRESOLVED | Write + cycle | check-state-schema.py + integrity-check.py | phases.merge.pr_number does not resolve in the cached gh pr list result (skipped gracefully when gh is unavailable) |
PHASE_TRANSITION_NO_LOG (v7.6) | Write | check-state-schema.py | Staged phase change without log entry within 15 min |
PHASE_TRANSITION_NO_TIMING (v7.6) | Write | check-state-schema.py | Staged phase change without timing.phases.<new>.started_at and old-phase ended_at fields |
PHASE_LIE | Cycle | integrity-check.py | current_phase=complete but state.json contradicts |
TASK_LIE | Cycle | integrity-check.py | Tasks marked complete that contradict commits |
NO_CS_LINK | Cycle | integrity-check.py | Shipped feature has no case-study link |
V2_FILE_MISSING | Cycle | integrity-check.py | v2/ subdirectory missing for refactored screen |
PARTIAL_SHIP_TERMINAL | Cycle | integrity-check.py | Marked shipped but only some sub-tasks done |
NO_STATE | Cycle | integrity-check.py | Feature in registry has no state.json |
BROKEN_PR_CITATION (v7.6 write-time, v7.5 cycle) | Write + cycle | check-case-study-preflight.py (write) + integrity-check.py (cycle) | PR # in case study does not resolve |
CASE_STUDY_MISSING_TIER_TAGS (v7.6) | Write + cycle | check-case-study-preflight.py (write) + integrity-check.py (cycle) | Scoped case study has no T1/T2/T3 tag at all (forward-only ≥ 2026-04-21); presence only, not exhaustiveness |
CACHE_HITS_AUTO_INSTRUMENTATION_DRIFT (v7.7 as CACHE_HITS_EMPTY_POST_V6; renamed v7.8.3, enforced) | Write | check-state-schema.py | Post-v6 feature reaches current_phase=complete with empty cache_hits[]. Pairs with scripts/log-cache-hit.py wrapper that auto-discovers the active feature and dual-writes state.json + events log. Closes #140 (the v6 writer-path adoption gap). Pre-Mechanism-C features (created_at before 2026-05-02) are auto-exempt. |
CU_V2_INVALID (v7.7) | Write + cycle | check-state-schema.py + integrity-check.py | cu_v2 schema invalid: missing factor (complexity/blast_radius/novelty/verification_difficulty), out-of-range value, total mismatch with sum(factors), or invalid tier_class. Pre-v6 features without cu_v2 are exempt. Validates STRUCTURE only — magnitude correctness stays a documented Class B gap. |
STATE_NO_CASE_STUDY_LINK (v7.7) | Write | check-state-schema.py | current_phase=complete without case_study link OR parent_case_study link OR case_study_type exempt tag (no_case_study_required / pre_pm_workflow_backfill / roundup). Mirrors the cycle-time NO_CS_LINK at write-time. |
CASE_STUDY_MISSING_FIELDS (v7.7) | Write | check-case-study-preflight.py | Forward-only ≥ 2026-04-28: case study missing one or more of work_type, success_metrics, kill_criteria, dispatch_pattern in frontmatter. |
TIER_TAG_LIKELY_INCORRECT (v7.7 advisory) | Cycle (advisory) | validate-tier-tags.py + integrity-check.py | Heuristic regex extracts T1-tagged quantitative claims and cross-references against ledger numbers. Advisory severity — does not gate. Kill criterion 2 fired at baseline (FP rate 100% n=1; root cause: regex pattern designed for **T1**: prefix style, live corpus uses | value | T1 | table-column format). Ships advisory permanent. v7.8 redesign documented in docs/case-studies/meta-analysis/tier-tag-checker-baseline.md. |
SCHEMA_DRIFT_LEGACY_CREATED (2026-05-01 honesty-fixes patch, PR #169) | Write | check-state-schema.py | Legacy created key on state.json (canonical: created_at). Closes the silent-pass that left v7.7 CACHE_HITS_EMPTY_POST_V6 at 0/46 effective coverage when 43/46 features used the legacy field name. |
FRAMEWORK_VERSION_FORMAT (2026-05-01 honesty-fixes patch, PR #169) | Write | check-state-schema.py | When framework_version is set, must match (pre-)?v<major>.<minor>. Presence-required deferred to v7.9 backfill. |
CACHE_HITS_AUTO_INSTRUMENTATION_INACTIVE (v7.8 advisory, Mechanism C) | Cycle (advisory) | integrity-check.py | Session ledger (.claude/logs/_session-<id>.events.jsonl) attributes Read events to a feature, but state.json::cache_hits[] is empty/absent. Mechanism C captures session events; state.json::cache_hits requires manual scripts/log-cache-hit.py until v7.9 promotes observe-cache-hit.py to dual-write. Advisory only in v7.8; v7.9 promotes to enforced. |
GATE_COVERAGE_ZERO (v7.8 advisory, Mechanism A; v7.9-enforced) | Cycle (advisory) | integrity-check.py (planned) | Write-time gate that fired with checked=0 (every candidate skipped) for 7+ days. Catches the failure mode where a gate's predicate is too restrictive and silently passes everything. Coverage data lands in .claude/logs/gate-coverage.jsonl per Mechanism A. Advisory in v7.8 (need 7+ days of stats to calibrate); v7.9 promotes to enforced once the threshold is empirically grounded. |
BRANCH_ISOLATION_VIOLATION Mode B (v7.8.1 advisory → enforced v7.9, 2026-05-21) | Write | check-state-schema.py | Infra-path commit (.githooks/*, .github/workflows/*, scripts/*, .claude/skills/*, .claude/shared/*, CLAUDE.md, docs/architecture/*, Makefile, OR work_subtype: framework_feature / work_type: chore) on a non-feature branch. Per-feature isolation_opt_out does NOT bypass Mode B (Q3 infra override). Auto-isolation dispatches scripts/create-isolated-worktree.py. |
BRANCH_ISOLATION_VIOLATION Mode C (v7.8.1 advisory → enforced v7.9) | Write | check-state-schema.py (BRANCH_ISOLATION_VIOLATION_MODE_C) | state.json::current_phase mutation from a non-feature branch. Per-feature isolation_opt_out: true + reason bypasses Mode C only. |
ISOLATION_OPT_OUT_REASON_MISSING (v7.8.1, enforced at ship) | Write | check-state-schema.py | isolation_opt_out: true with empty/missing isolation_opt_out_reason. |
FEATURE_CLOSURE_COMPLETENESS (v7.8.1 advisory → enforced v7.9; cycle mirror stays advisory) | Write + cycle | check-state-schema.py (write) + integrity-check.py (cycle mirror) | current_phase=complete transition: validates 7 required case-study frontmatter fields + Q7 (kill_criteria_resolution when kill_criteria set) + Q6 bidirectional PR-list parity (state.json ↔ case study). Cycle mirror catches --no-verify bypasses. Override: pr_citation_exempt / case_study_type exemption. |
STATE_OWNER_MISSING / STATE_OWNER_INVALID / STATE_OWNER_LOCATION_MISMATCH (v7.8.3) | Write | check-state-schema.py | Cross-repo state ownership: state_owner ∈ {ft2, fitme-story} required + valid enum + file location must match the value (reverse-sync mirrors with state_owner_sync_origin ending -reverse exempt from LOCATION_MISMATCH). |
BRANCH_ISOLATION_HISTORICAL (v7.8.1 cycle advisory — stays advisory by design) | Cycle (advisory) | integrity-check.py | T17 forward-only audit — feature files first appear on main with no feature/*/chore/* branch attribution (squash-merge + branch-cleanup artifact; see Observed Patterns #1). |
BRANCH_ISOLATION_LAUNCHD_DRIFT (v7.8.1 cycle advisory — macOS-only, stays advisory) | Cycle (advisory) | integrity-check.py | T18 — launchd plist anchored to a stale repo path (the 2026-04-30 HADF Phase 2 trigger incident). |
PR_CACHE_STALE (v7.8.4 operability) | Pre-check | ensure-pr-cache-fresh.py | .cache/gh-pr-cache.json empty/missing/older-than-24h → auto-refresh runs before make integrity-check + inside integrity-cycle.yml. Refresh failure logs but does NOT abort. Closes the 33-finding empty-cache false-positive incident (2026-05-12; see Observed Patterns #12 + W11). |
PLATFORMS_TESTED (T14, 2026-06-07, enforced 2026-06-21, PR #781) | Write | check-state-schema.py | current_phase=complete transition with no platform set in platforms_tested {ios,web,backend,ai}. Own PLATFORMS_TESTED_ADVISORY_MODE flag + isolated coverage key kept the advisory→enforced flip independent of FEATURE_CLOSURE_COMPLETENESS; promoted to enforced on 2026-06-21 (cadence B15) after a clean 14-day window. Framework-meta features (work_type=chore/work_subtype=framework_feature) exempt. Also validates field shape any phase. |
TRACKING_DRIFT_OPEN_BUT_SHIPPED (2026-06-07, advisory) | On-demand | tracking-drift-check.py (make tracking-drift-check) | Planning rows that claim OPEN ([ ] / un-struck RICE row) while the feature state.json is complete or the row's own title carries a ship marker. Advisory only. |
PR_NUMBER_UNRESOLVED window (raised 500 → 2000, 2026-06-07) | Write | check-state-schema.py _load_pr_cache | gh pr list --limit 2000 (was 500): a commit touching an OLD complete feature re-validates its merge pr_number, so the window must span full PR history (same W34 truncation class as PR #631). |
10.2 The 72h cycle
Defined in .github/workflows/integrity-cycle.yml. Cron: 0 4 */3 * * (every 3 days at 04:00 UTC). Steps:
- Checkout repo with
fetch-depth: 0. - Run
integrity-check.py --snapshot <new> --compare-to <prev> --snapshot-trigger scheduled_cycle. - Commit the new snapshot to
.claude/integrity/snapshots/. - If a regression is detected, open a
regression-labeled issue.
10.3 The per-PR layer
Defined in .github/workflows/pr-integrity-check.yml (v7.6 Phase 2a). Steps:
- Checkout PR HEAD.
- Run schema check + integrity check + measurement-adoption against PR HEAD.
- Capture
origin/mainbaseline viagit worktree add /tmp/main-tree origin/main. - Compute
delta = pr_findings - main_findings. - Set
pm-framework/pr-integritycommit status tofailureif any required command exits non-zero or ifdelta > 0. - Sticky comment with marker
<!-- pm-framework-pr-integrity-bot -->updates in place and reports command exit codes. try-repo-harnessjob (v7.9.1, F16): spawns throwaway git repos and runs the real.githooks/pre-commitagainst canonical per-gate fixtures (15/16 write-time gates + the gate-coverage contract test). ~15s; catches integration-surface bugs the in-process dispatch tests can't see.
10.4 The weekly cycle
Defined in .github/workflows/framework-status-weekly.yml (v7.6 Phase 2c). Cron: 0 5 * * 1 (Mondays 05:00 UTC, 1h after the 72h cycle to avoid runner queue contention). Steps:
- Snapshot measurement-adoption history with
--snapshot-trigger weekly_status. - Compare current vs prior history snapshot.
- Open issue if
fully_adoptedorany_adopteddecreased. - Observational only — never blocks merges.
10.5 Observed Patterns Catalog (v7.8.5)
When a gate fires, the finding alone does not tell you whether it is a real problem or an expected artifact (a squash-merge leaving no branch attribution, an empty PR cache, a heuristic over-trigger, etc.). The Observed Patterns Catalog at .claude/integrity/observed-patterns.md is the canonical manifest of every recognized fire-pattern. Each entry carries a trigger, a why-expected classification (by-design / cleanup-artifact / silent-pass-then-fixed / heuristic-FP / schema-drift), a distinguishing-real-signal rule, and a silence path.
- Coverage (current): 23 gate-firing patterns (Section 1,
#1–#23) + 32 workflow/operational patterns (Section 2,W1–W32; W29–W32 added at v7.9.1). - CLI:
make observed-patterns. - Preflight-loaded by
/pm-workflowand referenced by all spoke skills. - Operator obligation (mandatory): when any framework gate or advisory fires, the FIRST step is to consult this catalog. Apply the documented remediation if the pattern matches; investigate only if novel; and append a new entry to the catalog before the feature that surfaced the novel pattern is closed. The catalog is append-only-by-default.
The catalog is the human-facing companion to the Mechanism A coverage ledger (§2.4): Mechanism A tells you a gate fired; the catalog tells you what the firing means.
10.6 Real-time + daily observability surfaces (v7.8.5 → v7.8.6)
Beyond the four scheduled enforcement layers, the framework runs several lightweight read/warn surfaces:
| Surface | Cadence | What it does | Producer |
|---|---|---|---|
| W9 branch-drift alert | PostToolUse:Bash hook (every Bash call) | Warns when the git branch changed unexpectedly between tool calls (concurrent-session git checkout collision). Disable: CLAUDE_W9_DISABLE_DRIFT_CHECK=1 | scripts/check-branch-drift.py |
| W1 ssh-agent preflight | SessionStart hook | Loud stderr warning when ssh-add -l shows no identities (prevents the silent sign-hang). Disable: CLAUDE_W1_DISABLE_SSH_CHECK=1 | scripts/check-ssh-agent.sh |
| Mechanism C cache-hit capture | PostToolUse:Read hook | Auto-captures Read events into the session ledger (existence-guarded so it no-ops in cross-repo cwd, per v7.8.2) | scripts/observe-cache-hit.py |
| Membrane status (Mechanism F) | make membrane-status + SessionStart | Active feature + recent gate firings + dispatch-blocker state in one readout | scripts/membrane-status.py |
| Daily integrity checkpoint | launchd cron (daily) | Appends an integrity snapshot to the checkpoint ledger + surfaces stale [gone] branches (W10), orphan worktrees, idle-PR babysit. SessionStart surfaces the regression flag | scripts/daily-integrity-checkpoint.py → make daily-checkpoint |
| Preflight aggregator | make preflight WORK_TYPE=… [FEATURE=…] | Mandatory Phase 0.0 step: aggregates W1 ssh-agent, PR-cache freshness, branch isolation, integrity findings, drift-vs-anchor, doc-debt, adoption baseline + auto-chains make freshness-check (W20) into .claude/shared/preflight-cache.json | scripts/preflight.py + scripts/cross-layer-freshness.py |
| Integrity diff vs anchor | make integrity-diff | Compares current platform state vs the 2026-05-14 pre-v7.9 baseline anchor; EXIT_ON_REGRESSION=1 for CI | scripts/integrity-diff.py |
11. Pre-commit hooks and GitHub Actions
11.1 Installing the pre-commit hook
make install-hooks # symlinks .githooks/pre-commit to .git/hooks/pre-commit11.2 What the hook runs
python3 scripts/check-state-schema.py --staged || exit 1
python3 scripts/check-case-study-preflight.py --staged || exit 1Both scripts exit non-zero on findings. Emergency bypass: git commit --no-verify. The cycle layer still catches the issue 0–72h later, so bypass is not silent.
11.3 GitHub Actions inventory
| Workflow | Trigger | Purpose |
|---|---|---|
ci.yml | push, PR | Xcode build + XCTest + tokens-check + ui-audit |
ci-docs-skip.yml | PR (docs-only paths) | Skips the iOS build for docs-only PRs (10-15min → instant) |
integrity-cycle.yml | cron 0 4 */3 * * + workflow_dispatch | 72h state.json + case-study audit; snapshots ledger; regression issue |
pr-integrity-check.yml | pull_request (opened, sync, reopen) | Per-PR delta vs main; sets pm-framework/pr-integrity status |
framework-status-weekly.yml | cron 0 5 * * 1 (Mon 05:00Z) + workflow_dispatch | Weekly measurement-adoption + documentation-debt snapshot + Mechanism A gate-coverage zero-drift scan (v7.8.6) + per-dimension adoption trend nudge; regression issue |
dependency-audit-weekly.yml (v7.8.6) | cron 0 6 * * 1 (Mon 06:00Z) | npm audit --omit=dev across root + website + dashboard + Swift pin count; issue on HIGH/CRITICAL |
audit-prompts-weekly.yml | cron 0 6 * * 1 (Mon 06:00Z) | Rebuilds the external-audit prompt substrate bundle |
audit-bundle-on-tag.yml | tag push | Builds a deterministic audit bundle on release tags |
ucc-audit-log-sync.yml | cron 17 5 * * * (daily) | Syncs the UCC passkey-auth audit log (Redis → ledger) |
weekly-backup.yml | cron 0 2 * * 0 (Sun 02:00Z) | Weekly off-repo backup snapshot |
figma-code-connect-publish.yml | push to main (*.figma.{swift,tsx} / config) | Publishes Code Connect mappings |
lint.yml (v7.9.1) | push, PR | SwiftLint + ruff + markdownlint — warn-only (continue-on-error) |
coverage.yml (v7.9.1) | push, PR | iOS Slather + Python pytest-cov coverage telemetry — warn-only |
gitleaks.yml (v7.9.1) | push, PR | Secret scanning |
pip-audit.yml (v7.9.1) | push, PR | ai-engine Python dependency audit |
sbom.yml (v7.9.1) | release tags | SBOM generation (syft) |
commitlint.yml (v7.9.1) | PR | Conventional-commits lint |
shellcheck.yml (v7.9.1) | push, PR | Shell-script lint |
v7.9.1 grew the CI workflow count from 8 → 14 baseline (the 7 dev-env additions above; all warn-only per Phase E exit discipline).
pr-integrity-check.ymlalso gained the F16try-repo-harnessjob (§10.3).
Local (launchd) cron — not a GitHub Action:
| Job | Cadence | Purpose |
|---|---|---|
com.fittracker.daily-integrity-checkpoint.plist | daily | Runs scripts/daily-integrity-checkpoint.py (§10.6) — daily integrity snapshot + stale-branch / orphan-worktree / idle-PR surfaces. Install via make install-daily-cron. macOS-specific. |
11.4 Security note for workflow files
All dynamic values used inside run: blocks MUST be routed through the env: block, never via ${{ }} interpolation directly into shell. This prevents the GitHub Actions injection vector (see github.blog reference). The pre-commit hook for workflow files (security_reminder_hook.py) blocks writes that violate this. Both v7.6 workflows (pr-integrity-check.yml, framework-status-weekly.yml) follow this pattern.
12. Compressed evolution timeline (v1.0 → v7.9.1)
Full per-version detail: docs/skills/evolution.md. This section is the compressed dev-only summary — what each version changed structurally.
| Version | Date | Structural change | Why it matters to a dev today |
|---|---|---|---|
| v1.0 | 2026-03-16 | Single-track serial pipeline (Research → ... → Docs). All work types ran the full 9 phases. | The legacy structure; replaced in v2.0. Files predating v2.0 may show signs of "every change passed through PRD." |
| v2.0 | 2026-03-25 | Work-type tiering (Feature / Enhancement / Fix / Chore). Reduced phase counts per type. | Why a fix PR doesn't have a PRD — it's not laziness, it's the work-type contract. |
| v3.0 | 2026-04-09 | External integrations (GA4, Sentry, App Store Connect, Firecrawl, Axe), screen audits, multi-screen v2. | The .claude/integrations/ directory dates from here. |
| v4.0 | 2026-04-10 | Reactive data mesh + learning cache. L1/L2/L3 cache levels introduced. | The _shared/ and _project/ cache directories. |
| v4.1 | 2026-04-10 | Skill internal lifecycle (each skill has init, do, report, learn stages internally). | Why every SKILL.md has the same outline. |
| v4.2 | 2026-04-10 | Self-healing hub with integrity verification. First seed cache (5 L1 + 5 L2/L3). | The cache verification logic in scripts/cache-integrity.py. |
| v4.3 | 2026-04-11 | Operations Control Room + case-study monitoring. case-study-monitoring.json. | The dashboard route on fitme-story (/) is built on this data. |
| v4.4 | 2026-04-13 | Eval-driven development. Skill learn stage now runs evals against historical sessions. | .claude/cache/_shared/skill-evals/ directory. |
| v5.0 | 2026-04-14 | SoC-on-software part 1: skill-on-demand loading + cache compression. 54K tokens saved per session. | Why only pm-workflow is in context until you call a spoke. |
| v5.1 | 2026-04-14 | SoC-on-software part 2: 8 SoC items (batch dispatch, result forwarding, model tiering, speculative preload, systolic chains, complexity gate, etc.). | The performance gains came from these — see docs/skills/architecture.md §3 for inspiration analogs (Apple ANE, TPU, ARM big.LITTLE). |
| v5.2 | 2026-04-16 | Dispatch Intelligence (3-stage dispatch pipeline) + Parallel Write Safety (3-tier mirror extraction). | The .claude/shared/dispatch-intelligence.json config + the parallel-write guards in spoke skills. |
| v6.0 | 2026-04-16 | Framework Measurement Protocol. CU formula v2 (continuous factors), L1/L2/L3 cache hit tracking, eval coverage gates, monitoring auto-sync, 79K tokens measured, rolling baselines, serial/parallel velocity decomposition. | This is when state.json.timing and state.json.cache_hits schemas became canonical. Most of v7.5/v7.6's "retroactive backfill" was about catching pre-v6.0 features up to this schema. |
| v7.0 | 2026-04-16 | HADF (Hardware-Aware Dispatch). 5-layer architecture, 17 chip profiles, 7 cloud signatures, hardware_context block in dispatch-intelligence.json, zero-regression gate (0.4/0.7), composite optimizer. | If you see hardware_context in dispatch logs, this is why. Layer 4 (chip-affinity-map) is empty by design — it activates when a workload meets thresholds. |
| v7.1 | 2026-04-21 | 72h Integrity Cycle. First framework capability whose trigger is wall-clock elapsed (cron). 7 failure-mode detectors. | The integrity-cycle.yml workflow + .claude/integrity/snapshots/ ledger. |
| v7.5 | 2026-04-24 | Data Integrity Framework (8 cooperating defenses). Pre-commit schema gates, PR-resolution check, runtime smoke gates, contemporaneous logging, T1/T2/T3 data quality tiers, documentation-debt + measurement-adoption ledgers, 3 new Auditor Agent check codes. Triggered by Gemini 2.5 Pro audit. | 7 of Gemini's 9 Tier 1/2/3 items shipped fully or effectively, 2 partial/pilot, 1 deferred to v7.6. The pre-commit hook and the make targets (integrity-check, measurement-adoption, documentation-debt, runtime-smoke) date from here. |
| v7.6 | 2026-04-25 | Mechanical Enforcement. 4 new write-time check codes (PHASE_TRANSITION_NO_LOG, PHASE_TRANSITION_NO_TIMING, BROKEN_PR_CITATION write-time, CASE_STUDY_MISSING_TIER_TAGS). Per-PR review bot with pm-framework/pr-integrity status check. Weekly framework-status cron. Append-only adoption history. 5 explicit Class B gaps documented in unclosable-gaps.md. | The point where mechanical enforcement reached steady-state. The Class B inventory crystallized here. |
| v7.7 | 2026-04-27 | Validity Closure. 5 new check codes (4 gating + 1 advisory): CACHE_HITS_EMPTY_POST_V6 (write — closes #140 writer-path), CU_V2_INVALID (write+cycle — schema validator), STATE_NO_CASE_STUDY_LINK (write — mirrors cycle-time NO_CS_LINK), CASE_STUDY_MISSING_FIELDS (write — forward-only ≥ 2026-04-28), TIER_TAG_LIKELY_INCORRECT (cycle advisory permanent — kill-2 fired at baseline). Cycle-time codes 12 → 13. Linkage 95.5% → 100% (gated). Doc-debt fields 4–61% → 95.7–100% (gated forward). Framework-health dashboard live at fitme-story /control-room/framework. Reduces unclosable Class B gaps from 5 to 4. | The first version to gate the full closure-time chain (linkage + case-study fields + cu_v2 schema). The 2026-05-01 honesty-fixes patch (PR #169) revealed v7.7's CACHE_HITS_EMPTY_POST_V6 had 0/46 effective coverage because the gate read created_at while 43/46 features used legacy created — surfaced the silent-pass class of failure that v7.8 set out to close. |
| v7.8 | 2026-05-04 | Bridge to v7.9 — silent-pass prevention + inter-agent awareness. Six cooperating mechanisms (A–F): coverage-asserting gates (Mech A → gate-coverage.jsonl), schema field-rename detection + dual-read (Mech B → migrate-state-v7-8-bridge.py), PostToolUse:Read attribution (Mech C → _session-<id>.events.jsonl + .claude/active-feature lockfile; closes Gap 1 in advisory), pre-commit hook header self-audit (Mech D → pre-commit-self-test.py), custom git merge driver for append-only ledgers (Mech E → merge-driver-dedup.py), membrane status advisory (Mech F → membrane-status.py). 2 new write-time gates (SCHEMA_DRIFT_LEGACY_CREATED, FRAMEWORK_VERSION_FORMAT). 2 new cycle-time advisories (CACHE_HITS_AUTO_INSTRUMENTATION_INACTIVE, GATE_COVERAGE_ZERO). Schema bridges (agent_manifest, _meta.deprecation_warnings, path-reducers.json, agent-leases.json) ship populated but un-validated. Shipped via 9 PRs: #173 + #185–#189 + #193–#195. | The bridge release. Writing code on v7.8: expect the v7.7 write-time gates plus 2 new gates (SCHEMA_DRIFT_LEGACY_CREATED, FRAMEWORK_VERSION_FORMAT). On every Read tool call, PostToolUse:Read hook captures the event into the session ledger via scripts/observe-cache-hit.py (Mechanism C). On every commit, every write-time gate emits coverage telemetry into .claude/logs/gate-coverage.jsonl (Mechanism A). |
| v7.8.1 | 2026-05-07 | Branch Isolation + Feature-Closure Completeness. 3 new write-time gates — BRANCH_ISOLATION_VIOLATION (Mode B infra / Mode C per-state.json), FEATURE_CLOSURE_COMPLETENESS (7 frontmatter fields + Q6 PR-parity + Q7 kill-resolution), ISOLATION_OPT_OUT_REASON_MISSING (enforced at ship) — plus 3 cycle-time advisories (BRANCH_ISOLATION_HISTORICAL, BRANCH_ISOLATION_LAUNCHD_DRIFT, FEATURE_CLOSURE_COMPLETENESS mirror). All advisory pending the 14-day Mechanism A window. Companions: create-isolated-worktree.py, make verify-isolation, make feature-completeness-audit. Shipped via PR #244 + #245. | The gates you'll most often see fire on infra/chore commits. If you commit to scripts/* or .claude/shared/* off a non-feature branch, Mode B fires — isolate first. |
| v7.8.2 | 2026-05-08 | Cross-Repo Telemetry Asymmetry — documented disposition (no new gates). Hook fix: PostToolUse:Read command gets a Bash existence guard so it no-ops in fitme-story cwd. Closes v7.9 candidates F7 + F8 by documented exemption (annual re-eval). Shipped via PR #258. | Why the Mechanism C hook silently no-ops when cwd is the website repo — by design, not a bug. |
| v7.8.3 | 2026-05-11 | Cross-Repo State Sync. Top-level state_owner enum ({ft2, fitme-story}) on every state.json + 3 gates (STATE_OWNER_MISSING/INVALID/LOCATION_MISMATCH). Promotes V2 (CACHE_HITS_AUTO_INSTRUMENTATION_DRIFT, renamed from CACHE_HITS_EMPTY_POST_V6) + V9 (merge driver extends to per-feature log) to enforced. New make snapshot-phase + scripts/snapshot-phase-completion.sh for per-phase off-SSD backups. Unified cross-repo PR-cite cache (refresh-pr-cache.py). Shipped via PR #298/#299 (+ fitme-story #86). | state_owner is now a required field — /pm-workflow writes it; the gate blocks if absent/mismatched. |
| v7.8.4 | 2026-05-12 | Pre-v7.9 telemetry calibration + doc-debt cleanup. One operability gate: PR_CACHE_STALE auto-refresh (ensure-pr-cache-fresh.py) closing the 33-finding empty-cache false-positive. TIER_TAG_LIKELY_INCORRECT heuristic narrowed (3 fixes). New case-study-t1-references.json ledger. Baseline driven to 0 findings + 0 advisory. Shipped on chore/framework-v7-8-4-calibration-patch. | Why a stale/empty PR cache no longer produces a wall of phantom BROKEN_PR_CITATION findings. |
| v7.8.5 | 2026-05-13 | Observability layer (docs + a hook, no new gates). Observed Patterns Catalog (.claude/integrity/observed-patterns.md, make observed-patterns) — canonical manifest of gate-firing patterns; check it FIRST when a gate fires. W9 branch-drift real-time alert (PostToolUse:Bash → check-branch-drift.py). Shipped via PR #327/#328 + #341. | The catalog is the doc you consult when a gate fires; W9 warns you if a concurrent session flipped your branch (§10.5 + §10.6). |
| v7.8.6 | 2026-05-15 | Cadence batch — read/diff/warn surfaces closing the 96h drift window. make integrity-diff (vs 2026-05-14 anchor), unified make preflight (mandatory Phase 0.0 aggregator → preflight-cache.json), weekly gate-coverage zero-drift scan + per-dimension adoption trend nudge (extends framework-status-weekly.yml), W1 ssh-agent SessionStart preflight, dependency-audit-weekly.yml, daily stale-branch / orphan-worktree / idle-PR surfaces. Shipped via PR #363 + #365. | make preflight WORK_TYPE=<type> is the one command to run before any new work — it aggregates every pre-work check (§10.6). |
| v7.9 | 2026-05-21 | Promotion release. Single-flag flip at scripts/check-state-schema.py:138 (BRANCH_ISOLATION_ADVISORY_MODE = True → False) promotes 3 v7.8.1 advisory gates simultaneously: BRANCH_ISOLATION_VIOLATION Mode B (infra commit-level), Mode C (per-state.json mutation), and FEATURE_CLOSURE_COMPLETENESS (write-time). All 4 promotion criteria met against 14-day Mechanism A telemetry (18 + 13 + 13 firings, 0 zero-candidate, 0 false positives). First real-world Mode C gate fire caught + resolved same-session (captured in honesty ledger FT2-FH-003). Phase E validation soak runs 2026-05-21 → 2026-06-04. Reversibility: single-line revert in under 5 min. Shipped via FT2 PR #417 (ea53ff4) + close-out PR #419. | The enforcement baseline (still current for gates). Writing code today: expect the v7.8 baseline plus the 3 promoted gates enforced — infra paths (.githooks/*, .github/workflows/*, scripts/*, .claude/skills/*, .claude/shared/*, CLAUDE.md, docs/architecture/*, Makefile) trigger BRANCH_ISOLATION_VIOLATION on chore branches unless an isolated worktree pattern is used. state.json::current_phase=complete transitions trigger FEATURE_CLOSURE_COMPLETENESS validation of 7 frontmatter fields + bidirectional PR-list parity. Same release shipped GitHub Security Tier S (PR #435): required_signatures=true on main, CODEOWNERS, Dependabot for GH Actions SHA-pin upgrades, pre-commit secret-regex + file-size guard, make doctor security checks. Plus YubiKey FIDO2 hardware-signing cut-over end-to-end. |
| v7.9.1 | 2026-06-04 | Single-day build window — 8 ships / 14 PRs / 0 new enforcement gates (Phase E exit discipline). Observability + substrates only: F16 try-repo harness (3rd gate-test layer — throwaway repo + real pre-commit; PRs #607–#612), F17 gate-last-fired.json derived index (#617), F2 make phase-0-reality-check (#618), Dev-env Track B + batch (SwiftLint/ruff/markdownlint/coverage/gitleaks/pip-audit/SBOM/commitlint/shellcheck warn-only; CI workflows 8 → 14; #619/#626/#627), F-LAUNCHD-DRIFT-EXTENSION (#621–#624), observed-patterns W29–W32 (#620), F-PHASE-E-ADOPTION-FREEZE-DISCIPLINE (#625), F-DEPLOYED-URL-PROBE substrate (#628). Post-window (2026-06-07): t14 platforms_tested field + advisory PLATFORMS_TESTED gate (#662/#665 — promoted to enforced 2026-06-21 via FT2 #781, cadence B15), tracking-drift-check (#659), prereg lock-introducing-commit permit (#660), contract-fixture sampling (fitme-story #209). | The current state. What's new for a dev: a 3rd test layer (try-repo) runs on every PR; platforms_tested is a new state.json field whose gate shipped advisory at complete and was promoted to enforced 2026-06-21; 7 new warn-only CI workflows; make phase-0-reality-check + make tracking-drift-check are available. As of 2026-06-21, PLATFORMS_TESTED now blocks a complete transition with no platform set, in addition to the v7.9 gate set. |
12.1 Version-bump policy
A major-version bump (e.g., v7.6 → v7.7) requires:
- A new structural capability — not just code changes within an existing capability.
- A propagated update across surfaces — manifest, CLAUDE.md, evolution doc, case study, and trust-page integration where relevant.
- A measurement that the change is real — pipeline test, integrity check, or instrumented data.
Minor bumps (e.g., v7.5 hardening commits) extend an existing capability without introducing a new layer.
13. Operational walkthrough — adding a new feature
You are adding a new feature called widget-customization. Here's the full sequence.
13.0 Preflight (Phase 0.0, mandatory since v7.8.6)
Before any work, run the unified preflight aggregator:
make preflight WORK_TYPE=feature FEATURE=widget-customizationThis runs every pre-work check (W1 ssh-agent, PR-cache freshness, branch isolation, integrity findings, drift-vs-anchor, doc-debt, adoption baseline) and auto-chains make freshness-check (W20 — confirms your mental model isn't stale vs origin/main). Results land in .claude/shared/preflight-cache.json, which every spoke skill reads. If preflight surfaces a blocker (e.g., you're on main and about to touch infra paths, which trips branch-isolation), resolve it before starting.
13.1 Bootstrap
/pm-workflow widget-customizationThe hub creates .claude/features/widget-customization/state.json with:
{
"name": "widget-customization",
"work_type": "feature",
"current_phase": "research",
"created": "<now ISO>",
"phases": {"research": {"started_at": "<now>"}},
"tasks": [],
"complexity": {"cu_version": 2, "view_count": 0, "factors_applied": []},
"timing": {"session_start": "<now>", "phases": {"research": {"started_at": "<now>"}}},
"cache_hits": []
}It also creates .claude/logs/widget-customization.log.json with a phase_started event.
13.2 Phase progression
For each phase transition (e.g., research → prd):
- Run the phase-specific work (research → write
docs/product/research/widget-customization.md). - Update state.json: set
phases.research.completed_at, setcurrent_phase = "prd", addphases.prd.started_at. - Append a
phase_transitionlog event viaappend-feature-log.py. - Commit. The pre-commit hook will:
- Verify
current_phase(notphase) —SCHEMA_DRIFT. - Verify the log entry exists within 15 min —
PHASE_TRANSITION_NO_LOG. - Verify
phases.prd.started_atis set —PHASE_TRANSITION_NO_TIMING.
- Verify
13.3 During implementation
Log cache hits as you go:
python3 scripts/append-feature-log.py \
--feature widget-customization \
--event-type code_change \
--summary "<what>" \
--artifact "<file>" \
--cache-hit L2 \
--cache-key "<stable key>" \
--cache-hit-type adapted \
--cache-skill "<source>"Update state.json.complexity.factors_applied[] as factors become known (e.g., when you add a new view, set view_count; if you discover a new model is needed, set new_types_count).
13.4 Merge phase
- PR opens. The per-PR bot fires automatically.
- If the bot fails the
pm-framework/pr-integritystatus check, fix the new findings before requesting review. - After merge, set
state.json.phases.merge.pr_numberto the merged PR number. The pre-commit verifies it against a cachedgh pr listresult whenghis available (PR_NUMBER_UNRESOLVED).
13.5 Docs phase + close
- Write
docs/case-studies/widget-customization-case-study.md. - The pre-commit will scan it for:
- PR citations (
PR #Norpull/N) —BROKEN_PR_CITATION. - Missing file-level T1/T2/T3 tag in scoped post-2026-04-21 case studies —
CASE_STUDY_MISSING_TIER_TAGS.
- PR citations (
- Set
current_phase = "complete". Setphases.docs.completed_at. Settiming.total_wall_time_minutes(sum of per-phase elapsed). - Add the case study to
feature-registry.jsonand to fitme-storycontent/04-case-studies/<NN>-<slug>.mdxif it's showcase-worthy.
14. Operational walkthrough — extending an integrity check code
You want to add a new check code, e.g., MISSING_METRIC_BASELINE (a feature in complete phase whose PRD has no baseline number set). Here's the sequence.
14.1 Decide the layer
- Should it block at write-time? (Cheap and immediate; agent corrects mid-session.)
- Should it run only on the cycle? (More expensive to surface, but catches cross-session drift.)
- Should it run per-PR? (Catches before merge; status-check enforced.)
Most checks should be cycle-time first; promote to write-time once the false-positive rate is < 1%.
14.2 Add the cycle-time check
- Open
scripts/integrity-check.py. - Add a new function:
def check_missing_metric_baseline(state: dict, name: str) -> list[Finding]: if state.get("current_phase") != "complete": return [] prd_path = REPO_ROOT / "docs" / "product" / "prd" / f"{name}.md" if not prd_path.exists(): return [] prd = prd_path.read_text() if not re.search(r"baseline:\s*\d", prd, re.IGNORECASE): return [Finding("MISSING_METRIC_BASELINE", name, f"PRD has no baseline number")] return [] - Call it from the main loop alongside other check fns.
- Add a row to the check-code table in CLAUDE.md "Data Integrity Framework" section.
14.3 Add a synthetic-violation test
Open scripts/test-v7-5-pipeline.sh. Add a new assertion:
# Test N: MISSING_METRIC_BASELINE fires on PRD without baseline
echo "test N: MISSING_METRIC_BASELINE fires"
mkdir -p docs/product/prd
echo "# fake PRD without baseline" > docs/product/prd/widget-customization.md
out=$(python3 scripts/integrity-check.py --findings-only)
if echo "$out" | grep -q "MISSING_METRIC_BASELINE"; then
echo " ✓ fired"
else
echo " ✗ did not fire"; exit 1
fi
rm docs/product/prd/widget-customization.md14.4 Promote to write-time later
Once the cycle-time check is stable, copy the check function into scripts/check-state-schema.py's validate_file() (with enforce_transition semantics if appropriate), add the --staged invocation to .githooks/pre-commit, and add a write-time test assertion.
15. Operational walkthrough — bumping the framework version
You shipped a structural capability that meets §12.1 criteria. The checklist below is the full propagation sequence. Run it top-to-bottom; if you skip a step, the framework will drift between surfaces and the next operator (often you, two weeks later) will hit a confusing inconsistency.
15.1 The checklist (10 steps)
- Bump the manifest. Edit
.claude/shared/framework-manifest.json: bumpframework_version(e.g.,7.6 → 7.7); updatedescription; add new capability flags tocapabilities; add a new top-level blockv<X>_<name>mirroring thev7_6_mechanical_enforcementshape. - Update
CLAUDE.md. Update the "## Data Integrity Framework" header. Add new check codes to the Write-time gates list. Add new defenses to the appropriate block. Update "## Known Mechanical Limits" if Class B gaps changed. - Update
docs/skills/evolution.md. Update the> **Status:** v<X>line. Add a new dated note. Add a new row to the version table at the bottom. - Update the FT2 canonical dev guide. Bump the title
(v1.0 → v<X>)indocs/architecture/dev-guide-v1-to-v7-7.md. Bump the "Current version" callout at the top. Add a new row to the §12 timeline table. If the change introduced new gates, update the §10.1 check-code table AND the §2.2 layer diagram. If you promoted advisories to enforced, add an §2.0 snapshot block. - Update THIS page. Mirror the same changes into
fitme-story/content/framework/dev-guide.md(the Next.js render source). The FT2 → fitme-story sync script handlessrc/data/docs/docs/architecture/dev-guide-v1-to-v7-7.mdautomatically, but THIS file is independent. - Write the case study. Create
docs/case-studies/<slug>-v<X>-case-study.md. Followmechanical-enforcement-v7-6-case-study.mdas the format reference. T1/T2/T3 tier tags are required forward of 2026-04-21 — the pre-commit hook will block the commit otherwise. - Update memory + mirrors. Update repo-root
project_*.mdmirror files where relevant. Add a memory entry under~/.claude/projects/.../memory/project_<slug>.md. UpdateMEMORY.mdindex. - Cross-repo. If user-visible, add a new MDX case study slot in
fitme-story/content/04-case-studies/. If it relates to the trust page, append a section to the appropriate trust subroute. - Commit + push. Pre-commit hooks catch tier-tag gaps in the case study and phase-transition discipline failures. Fix and re-commit if any fire.
- Verify. Run
bash scripts/test-v7-5-pipeline.sh— all assertions should pass. If you added a new check code (per §14), the count line in the script header updates.
15.2 What NOT to skip — the dev-guide drift trap
The most common failure mode is finishing steps 1–3 (manifest, CLAUDE.md, evolution doc) and then forgetting steps 4 + 5 (the dev guide canonical + this page). The result: CLAUDE.md says "current version v7.9," framework-manifest.json says "framework_version": 7.9, and yet the FT2 canonical dev-guide still says "v1.0 → v7.8.6" in its title. Operators landing on it think the framework is days behind reality.
Concrete example. The v7.9 promotion (shipped 2026-05-21 via FT2 PR #417) bumped CLAUDE.md, the manifest, and THIS page. It missed the FT2 canonical dev-guide and its sync mirror. The drift was caught + fixed 3 days later in the same PR that introduced this callout.
Pre-flight check (do this before pushing the bump):
grep -nE '^# .* \(v1\.0 → ' \
/Volumes/DevSSD/FitTracker2/docs/architecture/dev-guide-v1-to-v7-7.md \
/Volumes/DevSSD/fitme-story/content/framework/dev-guide.mdBoth files should show the same v<X> in their H1. If they diverge, finish step 4 + 5 before pushing.
15.3 Version-bump criteria (when does a change qualify?)
A major bump (e.g., v7.6 → v7.7) requires:
- A new structural capability — not just code changes within an existing capability.
- A propagated update across surfaces — manifest, CLAUDE.md, evolution doc, case study, both dev guides, trust-page integration where relevant.
- A measurement that the change is real — pipeline test, integrity check, or instrumented data.
Minor bumps (e.g., v7.5 → v7.5.1) extend an existing capability without introducing a new layer.
16. References
Canonical docs
CLAUDE.md— project rules (always loaded; fastest reference)docs/architecture/feature-lifecycle-event-catalog.md— companion to this guide; the event/log/gate catalog (artifact stack, trigger stack, gate stack, phase-by-phase event matrix, mermaid flow diagrams, worked example)docs/skills/architecture.md— skill-by-skill anatomydocs/skills/evolution.md— full version-by-version historydocs/skills/pm-workflow.md— user-facing PM workflow.claude/integrity/README.md— integrity layer canonical entry.claude/integrity/observed-patterns.md— Observed Patterns Catalog (gate-firing pattern manifest; consult FIRST when a gate fires;make observed-patterns)
Case studies (most relevant for this guide)
docs/case-studies/data-integrity-framework-v7.5-case-study.md— v7.5 narrativedocs/case-studies/mechanical-enforcement-v7-6-case-study.md— v7.6 narrative + comprehensive CU + workload analysisdocs/case-studies/framework-v7-7-validity-closure-case-study.md— v7.7 narrativedocs/case-studies/framework-v7-8-bridge-case-study.md— v7.8 live append-only journal (silent-pass prevention + inter-agent awareness)docs/case-studies/meta-analysis/unclosable-gaps.md— 5 mechanically unclosable Class B gaps (Gap 1 closed in v7.8 advisory)docs/case-studies/normalization-framework.md— CU formula referencedocs/case-studies/data-quality-tiers.md— T1/T2/T3 convention
Audit artifacts
docs/case-studies/meta-analysis/independent-audit-2026-04-21-gemini.md— verbatim Gemini audittrust/audits/2026-04-21-gemini/remediation-plan-2026-04-23.md— remediation trackerdocs/master-plan/codex-ssd-audit-2026-04-19.md— Codex SSD audit (pre-v7.5 context)
Implementation plans + specs
docs/superpowers/plans/2026-04-25-v7-6-mechanical-enforcement-phases-2-4.md— v7.6 plan agent outputdocs/superpowers/specs/2026-04-27-framework-v7-7-validity-closure-design.md— v7.7 specdocs/superpowers/plans/2026-04-27-framework-v7-7-validity-closure.md— v7.7 plandocs/superpowers/specs/2026-05-02-framework-v7-8-and-v7-9-bridge-design.md— v7.8 + v7.9 bridge design
Scripts (alphabetical)
scripts/append-feature-log.py— contemporaneous log writerscripts/check-branch-drift.py— W9 branch-drift PostToolUse:Bash alert (v7.8.5)scripts/check-case-study-preflight.py— write-time case study checksscripts/check-ssh-agent.sh— W1 ssh-agent SessionStart preflight (v7.8.6)scripts/check-state-schema.py— write-time + cycle state.json checks (incl. branch-isolation + state_owner gates)scripts/create-isolated-worktree.py— branch-isolation auto-isolation (v7.8.1)scripts/cross-layer-freshness.py— W20 cross-layer freshness scan (v7.8.6)scripts/daily-integrity-checkpoint.py— daily launchd checkpointscripts/documentation-debt-report.py— Tier 3.2 ledgerscripts/ensure-pr-cache-fresh.py— PR_CACHE_STALE auto-refresh (v7.8.4)scripts/integrity-check.py— cycle-time integrity checkscripts/integrity-diff.py— diff vs baseline anchor (v7.8.6)scripts/measurement-adoption-report.py— Tier 1.1 ledger + historyscripts/membrane-status.py— Mechanism F membrane readoutscripts/merge-driver-dedup.py— Mechanism E append-only-ledger merge driverscripts/observe-cache-hit.py— Mechanism C PostToolUse:Read capture (v7.8)scripts/preflight.py— unified pre-work aggregator (v7.8.6)scripts/runtime-smoke-gate.py— Tier 2.1 smoke runnerscripts/snapshot-phase-completion.sh— per-phase off-SSD backup (v7.8.3)scripts/test-v7-5-pipeline.sh— mechanical-enforcement regression testscripts/weekly-trend-scan.py— weekly gate-coverage + adoption trend scan (v7.8.6)
Workflows (full inventory in §11.3)
.github/workflows/ci.yml— Xcode build + test + tokens-check + ui-audit.github/workflows/ci-docs-skip.yml— skips iOS build for docs-only PRs.github/workflows/integrity-cycle.yml— 72h cycle (v7.1 → v7.5), cron0 4 */3 * *.github/workflows/pr-integrity-check.yml— per-PR (v7.6 Phase 2a).github/workflows/framework-status-weekly.yml— weekly cron0 5 * * 1(v7.6 + v7.8.6 trend scans).github/workflows/dependency-audit-weekly.yml— weekly npm audit, cron0 6 * * 1(v7.8.6).github/workflows/audit-prompts-weekly.yml— external-audit prompt substrate, cron0 6 * * 1.github/workflows/audit-bundle-on-tag.yml— deterministic audit bundle on tag push.github/workflows/ucc-audit-log-sync.yml— UCC audit-log sync, cron17 5 * * *.github/workflows/weekly-backup.yml— weekly off-repo backup, cron0 2 * * 0.github/workflows/figma-code-connect-publish.yml— Code Connect publish- Local launchd:
com.fittracker.daily-integrity-checkpoint.plist— daily checkpoint (make install-daily-cron)
External reference
- GitHub Actions injection guide — security pattern referenced in workflow files
This guide is updated whenever the framework's structural shape changes. If you find an inaccuracy or a stale reference, file a PR — the pre-commit hook will tell you immediately if the doc is out of sync with the code.
This page is a vendored mirror of docs/architecture/dev-guide-v1-to-v7-7.md on the FitTracker2 repository. The canonical source updates whenever the framework's structural shape changes; this page is regenerated on the next site deploy. If a code-vs-doc drift appears, the GitHub source is authoritative.