Skip to content
fitme·story

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), F17 last_fired_at index, 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: t14 platforms_tested field + PLATFORMS_TESTED gate (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 stays dev-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

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):

LayerCadenceWhere it lives
1. Write-timeevery git commit (~3-5s).githooks/pre-commit
2. Per-PRevery push to a PR (~1-3min).github/workflows/pr-integrity-check.yml
3. 72h cyclecron, every 3 days at 04:00 UTC.github/workflows/integrity-cycle.yml
4. Weeklycron, 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.

TermDefinition
Mechanism A–FThe 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 / T3Data 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 / CGate 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 enforcedAn 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 / WeeklyThe 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 codeA 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 / hubThe 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 EA 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.jsonPer-feature canonical contract at .claude/features/<name>/state.json. The single source of truth for that feature's lifecycle. See §5.
/pm-workflowThe 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 preflightThe 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_ownerRequired 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_testedstate.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 / F2Three 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-diffmake 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-commit against canonical positive/negative fixtures, catching integration-surface bugs the in-process dispatch tests can't see.
  • F17 last_fired_at index (#617) — gate-last-fired.json, a derived per-gate index of Mechanism A telemetry (AWS-Config-Rules pattern) so the planned v7.10 GATE_COVERAGE_ZERO meta-check runs O(1) per gate.
  • F2 Phase 0 reality-check (#618) — make phase-0-reality-check cross-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):

Gate14d telemetrySkip reasons (all legit)
BRANCH_ISOLATION_VIOLATION Mode B (infra commit-level)18 firings, 0 zero-candidatenot_infra_commit_level × 13
BRANCH_ISOLATION_VIOLATION Mode C (per-state.json)13 firings, 0 zero-candidateseparate emission key
FEATURE_CLOSURE_COMPLETENESS (write-time)13 firings, 0 zero-candidatenot_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):

GateWhy
BRANCH_ISOLATION_HISTORICAL cycle-timeT17 forward-only audit — historical features predating the gate cannot retroactively pass
BRANCH_ISOLATION_LAUNCHD_DRIFT cycle-timeT18 macOS-only — environment-specific
FEATURE_CLOSURE_COMPLETENESS cycle-time mirrorT19 --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:

  1. 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 advisory PostToolUse:Read hook (Mechanism C) → promoted to enforced at v7.9 via CACHE_HITS_AUTO_INSTRUMENTATION_DRIFT. Pre-Mechanism-C features (created_at < 2026-05-02) remain exempt from CACHE_HITS_EMPTY_POST_V6.
  2. cu_v2 factor correctness — magnitudes are judgment-based.
  3. T1/T2/T3 tag correctness — preflight checks presence, not whether the tag is right.
  4. Tier 2.1 real-provider auth — physical device required.
  5. 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.

MechNameWhat it doesWhere the data lands
ACoverage-asserting gatesEvery 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
BSchema field-rename detection + dual-readcreatedcreated_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.9scripts/migrate-state-v7-8-bridge.py
CPostToolUse:Read attributionAuto-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
DPre-commit hook header self-auditValidates the hook header matches the implementation (catches drift between docstring and code)make pre-commit-self-testscripts/pre-commit-self-test.py
ECustom git merge driverAuto-resolves merge conflicts on append-only ledgers (measurement-adoption-history.json, documentation-debt.json) via union-dedup-by-keyscripts/merge-driver-dedup.py; registered by make install-hooks; .gitattributes opts in
FMembrane status advisorySingle readout: active feature + recent gate firings + dispatch-blocker state — closes inter-agent context-handoff gapmake membrane-statusscripts/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>.md for human reference.
  • A routing config entry in .claude/shared/skill-routing.json declaring 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-workflow hub always loads.
  • Spokes load on demand based on phase_skills in skill-routing.json.
  • Each spoke has a compressed_view field 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

  1. Create .claude/skills/<name>/SKILL.md with the agent-facing prompt.
  2. Create docs/skills/<name>.md for human reference.
  3. 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"
      }
    }
  4. 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

FieldTypeNotes
namestringFeature slug, must match directory name
work_typeenum"feature", "enhancement", "fix", "chore", "framework", "refactor"
current_phaseenumOne 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).
createdISO 8601 timestampUsed by measurement-adoption-report.py to bucket pre/post-v6.0 features
phasesobjectOne key per phase entered, with started_at (ISO 8601). Phase M adds ended_at when leaving for phase N>M.
tasksarrayTask list for Phase 3 (tasks phase) onward
complexityobjectv6.0 protocol: cu_version, factors_applied[], view_count, etc. (see § 9.1)
timingobjectv6.0 protocol: session_start, total_wall_time_minutes, per-phase started_at/ended_at
cache_hitsarrayv6.0 protocol: each entry is {timestamp, level, key, type, skill, event_type, phase}
state_ownerenum{ft2, fitme-story} (v7.8.3) — which repo holds the canonical state file. Enforced by STATE_OWNER_*.
platforms_testedobject{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 required
  • phases.merge.pr_number — set during the merge phase; verified by the PR_NUMBER_UNRESOLVED check

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 — legacy phase key present
  • NO_PHASE — neither current_phase nor phase present
  • INVALID_JSON — file does not parse
  • PHASE_TRANSITION_NO_LOG (v7.6) — phase changed but no log entry within last 15 min
  • PHASE_TRANSITION_NO_TIMING (v7.6) — phase changed but no timing.phases.<new>.started_at and/or old-phase ended_at update

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.

PhaseSkill driverOutputRequired for
1. researchresearchdocs/product/research/<name>.mdFeature
2. prdpm-workflowdocs/product/prd/<name>.mdFeature, Enhancement
3. taskspm-workflowstate.json.tasks[]Feature, Enhancement
4. ux_or_integrationux + designdocs/design-system/<name>-spec.mdFeature (UI), or skipped + recorded as work_type:fix etc.
5. implementdevcodeAll work types
6. testqaXCTest + CI greenAll except chore
7. reviewreviewer + qaApproved PRFeature, Enhancement
8. mergereleaseCommit on main + pr_number setAll
9. docspm-workflow + cxCase study + state.json closedFeature, 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:

  1. Tool budget check — does the requested skill fit within the per-session tool budget?
  2. Hardware affinity (v7.0 HADF) — does the current device profile favor a particular skill variant?
  3. 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:

LevelScopeLocationLifetime
L1Per-skill.claude/cache/<skill>/Session-scoped; skill-internal
L2Cross-skill (shared).claude/cache/_shared/Session-scoped; multiple skills can read
L3Project-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:

TypeWeight
Feature1.0
Enhancement0.8
Fix0.5
Chore0.3
Refactor (v2)0.9
Framework(choose nearest analog; commonly 0.9)

Complexity factors (additive):

FactorValueSource
Has UI (1 view)+0.15state.json.complexity.view_count
Has UI (2-3 views)+0.30same
Has UI (4+ views)+0.45same
Design Iteration (text)+0.10 per roundstate.json.complexity.design_iteration_details[]
Design Iteration (layout)+0.15 per roundsame
Design Iteration (interaction)+0.20 per roundsame
Design Iteration (full redesign)+0.25 per roundsame
New Model/Service (1-2 types)+0.1state.json.complexity.new_types_count
New Model/Service (3-5)+0.2same
New Model/Service (6+)+0.3same
Auth/External (binary)+0.5binary flag
Runtime Testing (binary)+0.4binary flag
Cross-Feature (binary)+0.2binary flag
Architectural Novelty (binary)+0.2state.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_VIOLATION Mode B (infra commit-level) + Mode C (per-state.json mutation) + FEATURE_CLOSURE_COMPLETENESS (write-time). Single-flag flip at scripts/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.

CodeLayerScriptWhat it checks
SCHEMA_DRIFTWrite + cyclecheck-state-schema.pyLegacy phase key present (canonical is current_phase)
NO_PHASEWrite + cyclecheck-state-schema.pyNeither current_phase nor phase present
INVALID_JSONWrite + cyclecheck-state-schema.pyFile does not parse
PR_NUMBER_UNRESOLVEDWrite + cyclecheck-state-schema.py + integrity-check.pyphases.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)Writecheck-state-schema.pyStaged phase change without log entry within 15 min
PHASE_TRANSITION_NO_TIMING (v7.6)Writecheck-state-schema.pyStaged phase change without timing.phases.<new>.started_at and old-phase ended_at fields
PHASE_LIECycleintegrity-check.pycurrent_phase=complete but state.json contradicts
TASK_LIECycleintegrity-check.pyTasks marked complete that contradict commits
NO_CS_LINKCycleintegrity-check.pyShipped feature has no case-study link
V2_FILE_MISSINGCycleintegrity-check.pyv2/ subdirectory missing for refactored screen
PARTIAL_SHIP_TERMINALCycleintegrity-check.pyMarked shipped but only some sub-tasks done
NO_STATECycleintegrity-check.pyFeature in registry has no state.json
BROKEN_PR_CITATION (v7.6 write-time, v7.5 cycle)Write + cyclecheck-case-study-preflight.py (write) + integrity-check.py (cycle)PR # in case study does not resolve
CASE_STUDY_MISSING_TIER_TAGS (v7.6)Write + cyclecheck-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)Writecheck-state-schema.pyPost-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 + cyclecheck-state-schema.py + integrity-check.pycu_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)Writecheck-state-schema.pycurrent_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)Writecheck-case-study-preflight.pyForward-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.pyHeuristic 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)Writecheck-state-schema.pyLegacy 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)Writecheck-state-schema.pyWhen 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.pySession 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)Writecheck-state-schema.pyInfra-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)Writecheck-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)Writecheck-state-schema.pyisolation_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 + cyclecheck-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)Writecheck-state-schema.pyCross-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.pyT17 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.pyT18 — 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-checkensure-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)Writecheck-state-schema.pycurrent_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-demandtracking-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)Writecheck-state-schema.py _load_pr_cachegh 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:

  1. Checkout repo with fetch-depth: 0.
  2. Run integrity-check.py --snapshot <new> --compare-to <prev> --snapshot-trigger scheduled_cycle.
  3. Commit the new snapshot to .claude/integrity/snapshots/.
  4. 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:

  1. Checkout PR HEAD.
  2. Run schema check + integrity check + measurement-adoption against PR HEAD.
  3. Capture origin/main baseline via git worktree add /tmp/main-tree origin/main.
  4. Compute delta = pr_findings - main_findings.
  5. Set pm-framework/pr-integrity commit status to failure if any required command exits non-zero or if delta > 0.
  6. Sticky comment with marker <!-- pm-framework-pr-integrity-bot --> updates in place and reports command exit codes.
  7. try-repo-harness job (v7.9.1, F16): spawns throwaway git repos and runs the real .githooks/pre-commit against 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:

  1. Snapshot measurement-adoption history with --snapshot-trigger weekly_status.
  2. Compare current vs prior history snapshot.
  3. Open issue if fully_adopted or any_adopted decreased.
  4. 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, W1W32; W29–W32 added at v7.9.1).
  • CLI: make observed-patterns.
  • Preflight-loaded by /pm-workflow and 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:

SurfaceCadenceWhat it doesProducer
W9 branch-drift alertPostToolUse: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=1scripts/check-branch-drift.py
W1 ssh-agent preflightSessionStart hookLoud stderr warning when ssh-add -l shows no identities (prevents the silent sign-hang). Disable: CLAUDE_W1_DISABLE_SSH_CHECK=1scripts/check-ssh-agent.sh
Mechanism C cache-hit capturePostToolUse:Read hookAuto-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 + SessionStartActive feature + recent gate firings + dispatch-blocker state in one readoutscripts/membrane-status.py
Daily integrity checkpointlaunchd cron (daily)Appends an integrity snapshot to the checkpoint ledger + surfaces stale [gone] branches (W10), orphan worktrees, idle-PR babysit. SessionStart surfaces the regression flagscripts/daily-integrity-checkpoint.pymake daily-checkpoint
Preflight aggregatormake 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.jsonscripts/preflight.py + scripts/cross-layer-freshness.py
Integrity diff vs anchormake integrity-diffCompares current platform state vs the 2026-05-14 pre-v7.9 baseline anchor; EXIT_ON_REGRESSION=1 for CIscripts/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-commit

11.2 What the hook runs

python3 scripts/check-state-schema.py --staged || exit 1
python3 scripts/check-case-study-preflight.py --staged || exit 1

Both 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

WorkflowTriggerPurpose
ci.ymlpush, PRXcode build + XCTest + tokens-check + ui-audit
ci-docs-skip.ymlPR (docs-only paths)Skips the iOS build for docs-only PRs (10-15min → instant)
integrity-cycle.ymlcron 0 4 */3 * * + workflow_dispatch72h state.json + case-study audit; snapshots ledger; regression issue
pr-integrity-check.ymlpull_request (opened, sync, reopen)Per-PR delta vs main; sets pm-framework/pr-integrity status
framework-status-weekly.ymlcron 0 5 * * 1 (Mon 05:00Z) + workflow_dispatchWeekly 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.ymlcron 0 6 * * 1 (Mon 06:00Z)Rebuilds the external-audit prompt substrate bundle
audit-bundle-on-tag.ymltag pushBuilds a deterministic audit bundle on release tags
ucc-audit-log-sync.ymlcron 17 5 * * * (daily)Syncs the UCC passkey-auth audit log (Redis → ledger)
weekly-backup.ymlcron 0 2 * * 0 (Sun 02:00Z)Weekly off-repo backup snapshot
figma-code-connect-publish.ymlpush to main (*.figma.{swift,tsx} / config)Publishes Code Connect mappings
lint.yml (v7.9.1)push, PRSwiftLint + ruff + markdownlint — warn-only (continue-on-error)
coverage.yml (v7.9.1)push, PRiOS Slather + Python pytest-cov coverage telemetry — warn-only
gitleaks.yml (v7.9.1)push, PRSecret scanning
pip-audit.yml (v7.9.1)push, PRai-engine Python dependency audit
sbom.yml (v7.9.1)release tagsSBOM generation (syft)
commitlint.yml (v7.9.1)PRConventional-commits lint
shellcheck.yml (v7.9.1)push, PRShell-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.yml also gained the F16 try-repo-harness job (§10.3).

Local (launchd) cron — not a GitHub Action:

JobCadencePurpose
com.fittracker.daily-integrity-checkpoint.plistdailyRuns 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.

VersionDateStructural changeWhy it matters to a dev today
v1.02026-03-16Single-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.02026-03-25Work-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.02026-04-09External integrations (GA4, Sentry, App Store Connect, Firecrawl, Axe), screen audits, multi-screen v2.The .claude/integrations/ directory dates from here.
v4.02026-04-10Reactive data mesh + learning cache. L1/L2/L3 cache levels introduced.The _shared/ and _project/ cache directories.
v4.12026-04-10Skill internal lifecycle (each skill has init, do, report, learn stages internally).Why every SKILL.md has the same outline.
v4.22026-04-10Self-healing hub with integrity verification. First seed cache (5 L1 + 5 L2/L3).The cache verification logic in scripts/cache-integrity.py.
v4.32026-04-11Operations Control Room + case-study monitoring. case-study-monitoring.json.The dashboard route on fitme-story (/) is built on this data.
v4.42026-04-13Eval-driven development. Skill learn stage now runs evals against historical sessions..claude/cache/_shared/skill-evals/ directory.
v5.02026-04-14SoC-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.12026-04-14SoC-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.22026-04-16Dispatch 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.02026-04-16Framework 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.02026-04-16HADF (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.12026-04-2172h 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.52026-04-24Data 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.62026-04-25Mechanical 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.72026-04-27Validity 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.82026-05-04Bridge 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.12026-05-07Branch 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.22026-05-08Cross-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.32026-05-11Cross-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.42026-05-12Pre-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.52026-05-13Observability 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:Bashcheck-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.62026-05-15Cadence 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.92026-05-21Promotion 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:

  1. A new structural capability — not just code changes within an existing capability.
  2. A propagated update across surfaces — manifest, CLAUDE.md, evolution doc, case study, and trust-page integration where relevant.
  3. 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-customization

This 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-customization

The 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):

  1. Run the phase-specific work (research → write docs/product/research/widget-customization.md).
  2. Update state.json: set phases.research.completed_at, set current_phase = "prd", add phases.prd.started_at.
  3. Append a phase_transition log event via append-feature-log.py.
  4. Commit. The pre-commit hook will:
    • Verify current_phase (not phase) — SCHEMA_DRIFT.
    • Verify the log entry exists within 15 min — PHASE_TRANSITION_NO_LOG.
    • Verify phases.prd.started_at is set — PHASE_TRANSITION_NO_TIMING.

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

  1. PR opens. The per-PR bot fires automatically.
  2. If the bot fails the pm-framework/pr-integrity status check, fix the new findings before requesting review.
  3. After merge, set state.json.phases.merge.pr_number to the merged PR number. The pre-commit verifies it against a cached gh pr list result when gh is available (PR_NUMBER_UNRESOLVED).

13.5 Docs phase + close

  1. Write docs/case-studies/widget-customization-case-study.md.
  2. The pre-commit will scan it for:
    • PR citations (PR #N or pull/N) — BROKEN_PR_CITATION.
    • Missing file-level T1/T2/T3 tag in scoped post-2026-04-21 case studies — CASE_STUDY_MISSING_TIER_TAGS.
  3. Set current_phase = "complete". Set phases.docs.completed_at. Set timing.total_wall_time_minutes (sum of per-phase elapsed).
  4. Add the case study to feature-registry.json and to fitme-story content/04-case-studies/<NN>-<slug>.mdx if 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

  1. Open scripts/integrity-check.py.
  2. 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 []
  3. Call it from the main loop alongside other check fns.
  4. 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.md

14.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)

  1. Bump the manifest. Edit .claude/shared/framework-manifest.json: bump framework_version (e.g., 7.6 → 7.7); update description; add new capability flags to capabilities; add a new top-level block v<X>_<name> mirroring the v7_6_mechanical_enforcement shape.
  2. 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.
  3. 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.
  4. Update the FT2 canonical dev guide. Bump the title (v1.0 → v<X>) in docs/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.
  5. 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 handles src/data/docs/docs/architecture/dev-guide-v1-to-v7-7.md automatically, but THIS file is independent.
  6. Write the case study. Create docs/case-studies/<slug>-v<X>-case-study.md. Follow mechanical-enforcement-v7-6-case-study.md as the format reference. T1/T2/T3 tier tags are required forward of 2026-04-21 — the pre-commit hook will block the commit otherwise.
  7. Update memory + mirrors. Update repo-root project_*.md mirror files where relevant. Add a memory entry under ~/.claude/projects/.../memory/project_<slug>.md. Update MEMORY.md index.
  8. 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.
  9. 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.
  10. 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.md

Both 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:

  1. A new structural capability — not just code changes within an existing capability.
  2. A propagated update across surfaces — manifest, CLAUDE.md, evolution doc, case study, both dev guides, trust-page integration where relevant.
  3. 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

Case studies (most relevant for this guide)

Audit artifacts

Implementation plans + specs

Scripts (alphabetical)

Workflows (full inventory in §11.3)

External reference


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.