@massa-ai/cursor-plugin 1.21.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.cursor-plugin/plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/skills/massa-ai/SKILL.md +9 -0
  4. package/skills/massa-ai/references/evidence-gate.md +1 -1
  5. package/skills/massa-ai/references/figma-pre-analysis.md +69 -0
  6. package/skills/massa-ai/references/hook-enforcement.md +2 -2
  7. package/skills/massa-ai/references/implementation-delivery.md +17 -3
  8. package/skills/massa-ai/references/lessons.md +9 -10
  9. package/skills/massa-ai/references/mcp-tools.md +1 -1
  10. package/skills/massa-ai/references/mobile-context.md +19 -0
  11. package/skills/massa-ai/references/mobile-diagnosis.md +1 -1
  12. package/skills/massa-ai/references/project-context.md +1 -1
  13. package/skills/massa-ai/references/spec-driven/artifact-store.md +7 -8
  14. package/skills/massa-ai/references/spec-driven/design.md +1 -1
  15. package/skills/massa-ai/references/spec-driven/execute.md +5 -5
  16. package/skills/massa-ai/references/spec-driven/specify.md +6 -6
  17. package/skills/massa-ai/references/spec-driven/sub-agents.md +1 -1
  18. package/skills/massa-ai/references/spec-driven/tasks.md +2 -2
  19. package/skills/massa-ai/references/spec-driven/validate.md +3 -3
  20. package/skills/massa-ai/scripts/check_commit.ts +231 -0
  21. package/skills/massa-ai/scripts/check_specs_delivered.ts +209 -0
  22. package/skills/massa-ai/scripts/lessons.ts +907 -0
  23. package/skills/massa-ai/scripts/validate_spec.ts +413 -0
  24. package/skills/massa-ai/scripts/validate_state.ts +276 -0
  25. package/skills/massa-ai/scripts/validate_tasks.ts +498 -0
  26. package/skills/massa-ai/workflows/architecture/architecture-fix.md +1 -1
  27. package/skills/massa-ai/workflows/bugs/bugs-fix.md +1 -1
  28. package/skills/massa-ai/workflows/code-quality/code-quality-fix.md +1 -1
  29. package/skills/massa-ai/workflows/debug.md +1 -1
  30. package/skills/massa-ai/workflows/design.md +1 -1
  31. package/skills/massa-ai/workflows/feature.md +2 -2
  32. package/skills/massa-ai/workflows/general.md +2 -2
  33. package/skills/massa-ai/workflows/implementation/implementation-fix.md +1 -1
  34. package/skills/massa-ai/workflows/maestro/maestro-fix.md +1 -1
  35. package/skills/massa-ai/workflows/mobile-figma/mobile-figma-audit.md +1 -0
  36. package/skills/massa-ai/workflows/mobile-figma/mobile-figma-fix.md +2 -1
  37. package/skills/massa-ai/workflows/refactor.md +1 -1
  38. package/skills/massa-ai/workflows/requirements/requirements-fix.md +1 -1
  39. package/skills/massa-ai/workflows/security/security-fix.md +1 -1
  40. package/skills/massa-ai/workflows/spec-driven.md +6 -6
  41. package/skills/massa-ai/workflows/tests/tests-fix.md +1 -1
  42. package/skills/massa-ai/scripts/check_commit.py +0 -128
  43. package/skills/massa-ai/scripts/check_specs_delivered.py +0 -137
  44. package/skills/massa-ai/scripts/lessons.py +0 -630
  45. package/skills/massa-ai/scripts/validate_spec.py +0 -272
  46. package/skills/massa-ai/scripts/validate_state.py +0 -183
  47. package/skills/massa-ai/scripts/validate_tasks.py +0 -302
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "massa-ai",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "description": "massa-ai — semantic code search, memory, and context compression for Cursor"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/cursor-plugin",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "description": "massa-ai plugin for Cursor — semantic code search, memory, and context compression",
5
5
  "files": [
6
6
  "agents",
@@ -60,6 +60,14 @@ Before reading any massa-ai file:
60
60
  - Persist only durable, useful knowledge. Do not fabricate memories to satisfy
61
61
  process. Use `memory_update` to correct stale memories and `memory_delete`
62
62
  to remove obsolete ones.
63
+ - Expand every word abbreviation on first use in user-facing output — e.g.
64
+ "PR (Pull Request)", "AC (Acceptance Criteria)", "KMP (Kotlin Multiplatform)"
65
+ — including workflow-specific shorthands and finding-ID families.
66
+ - Use one uniform vocabulary for separating batches of work in every workflow:
67
+ a **Task** is the atomic unit; a **Phase** is an ordered group of Tasks.
68
+ Report a phase's size as `1 Phase = X Tasks` and a plan's total as
69
+ `Y Phases = Z Tasks`. Do not substitute synonyms such as batch, wave, stage,
70
+ or chunk for these units in agent prose.
63
71
  - Emit concise user-facing status updates at meaningful workflow boundaries
64
72
  when the Conversation Feedback Policy is active.
65
73
  - Verify, don't assume: every factual claim that drives a decision is
@@ -275,6 +283,7 @@ Load only when a selected workflow asks for them:
275
283
  - `references/debug-diagnosis-loop.md`
276
284
  - `references/mobile-context.md`
277
285
  - `references/mobile-diagnosis.md`
286
+ - `references/figma-pre-analysis.md`
278
287
  - `references/mobile-figma-matcher/`
279
288
  - `references/lessons.md`
280
289
  - `references/naming-standards.md`
@@ -38,7 +38,7 @@ Use this compact shape when closing docs or skill work:
38
38
  ✅ [Verified] Skill validation and stale-reference scans passed.
39
39
  🏁 [Finished] Updated massa-ai references. Memory outcome: durable decision stored. Remaining risk: none found.
40
40
 
41
- Evidence: `rtk python3 skills/skill-architect/scripts/validate_skill.py skills/massa-ai --format json` passed; stale-reference and local-link scans passed.
41
+ Evidence: `bun run scripts/generate-skill-artifacts.ts --check` passed; stale-reference and local-link scans passed.
42
42
  Changed artifacts: `skills/massa-ai/SKILL.md`, `workflows/spec-driven.md`, `references/spec-driven/`, and `references/memory-policy.md`.
43
43
  Memory outcome: wrote decision memory `dec_...`; no failed memory writes.
44
44
  Residual risk: none found.
@@ -0,0 +1,69 @@
1
+ # Figma Pre-Analysis And Sequential Retrieval
2
+
3
+ Load this reference whenever a workflow receives one or more Figma links, node
4
+ IDs, or a readable desktop selection as a design source — the Figma audit/fix
5
+ family (`mobile-figma-audit`, `mobile-figma-fix`), `design`, and the
6
+ design-source gates of implementation workflows (`feature`, `spec-driven`).
7
+ This reference owns the orchestration protocol only; Figma Evidence Packet
8
+ field contracts stay in `references/mobile-figma-matcher/core.md`.
9
+
10
+ The protocol is the single normative copy. Workflows point here; they do not
11
+ restate it.
12
+
13
+ ## Why Two Stages
14
+
15
+ Full Figma extraction on unscoped links overloads one context with mixed
16
+ screens, buries feature boundaries, and makes evidence non-attributable. A
17
+ cheap pre-analysis pass first maps what the links contain, so each retrieval
18
+ pass reads one coherent slice.
19
+
20
+ ## Stage 1 — Pre-Analysis (always first, exactly one subagent)
21
+
22
+ Dispatch one read-only subagent (investigator-class; Figma MCP — Model Context
23
+ Protocol — access, no repository mutation) over the user-provided Figma links.
24
+ Its job is understanding, **not** extraction:
25
+
26
+ - Summarize composition: pages, screens, frames, component sets, shared tokens.
27
+ - Summarize product context: what the screens are for, the features they serve,
28
+ and the user flows connecting them.
29
+ - It does not build Figma Evidence Packet fields, does not resolve variables or
30
+ exact geometry, and does not compare against source code.
31
+
32
+ Its output is a compact packet:
33
+
34
+ 1. **Context summary** — screens/features/flows in prose, sized for the main
35
+ agent's context budget.
36
+ 2. **Partition proposal** — how many retrieval subagents should read which
37
+ links/nodes/screen groups, partitioned by:
38
+ - **Size:** each slice must fit one subagent's context comfortably.
39
+ - **Coupling:** screens sharing tokens, components, or a design system
40
+ section stay in one slice.
41
+ - **Feature flow:** one user flow per slice when possible, so evidence
42
+ stays attributable to a feature.
43
+ A single small screen legitimately yields a one-slice proposal.
44
+
45
+ The main agent reviews the proposal, adjusts slice boundaries if project
46
+ knowledge contradicts them, and records the final partition before Stage 2.
47
+
48
+ ## Stage 2 — Sequential Retrieval (N subagents, one at a time)
49
+
50
+ The main agent orchestrates the retrieval subagents **strictly sequentially —
51
+ never in parallel**. For each slice, in the recorded order:
52
+
53
+ 1. Dispatch one read-only retrieval subagent scoped to that slice's
54
+ links/nodes, carrying the Stage 1 context summary and the slice's purpose.
55
+ 2. Wait for completion; fold its output into the workflow's Figma Evidence
56
+ Packet (or Screenshot Context Packet rows) before dispatching the next.
57
+ 3. Let each completed slice inform the next dispatch prompt — resolved shared
58
+ tokens, discovered variants, and naming conventions carry forward.
59
+
60
+ Sequential dispatch is a hard rule, not a tuning choice: it respects Figma MCP
61
+ session/rate limits, and it is what lets slice N+1 reuse what slice N learned.
62
+ Retrieval subagents never spawn further subagents.
63
+
64
+ ## Fallback
65
+
66
+ If subagent spawning is unavailable (forbidden, plugin missing, unknown agent
67
+ type), run both stages inline in the main agent in the same order — pre-analysis
68
+ summary first, then per-slice retrieval — and record the skipped delegation
69
+ with its reason. Do not skip Stage 1 because delegation is unavailable.
@@ -44,7 +44,7 @@ Every hook exits 0 on bad stdin or non-critical error. Blocking hooks are
44
44
  | Hook | Event | Enforces |
45
45
  |---|---|---|
46
46
  | `stop_evidence_gate.py` | Stop | `references/evidence-gate.md` |
47
- | `continuous_learning_evaluate.py` | Stop | `references/lessons.md`, `scripts/lessons.py` |
47
+ | `continuous_learning_evaluate.py` | Stop | `references/lessons.md`, `scripts/lessons.ts` |
48
48
  | `precompact_save_state.py` | PreCompact | `workflows/long-session.md`, `references/context-firewall.md` |
49
49
  | `suggest_compact.py` | PreToolUse(Edit\|Write) | `references/context-firewall.md` (compaction boundary) |
50
50
  | `gateguard_fact_force.py` | PreToolUse(Edit) | `references/context-firewall.md` (investigate-before-edit) |
@@ -100,7 +100,7 @@ absent, it falls back to the flat evidence matrix (graceful degradation).
100
100
 
101
101
  The continuous-learning loop writes two stores, not one:
102
102
 
103
- - `lessons.py add` / `import` — deterministic grounded file store
103
+ - `lessons.ts add` / `import` — deterministic grounded file store
104
104
  (`.specs/lessons.json`); refuses ungrounded lessons; promotion/quarantine.
105
105
  - `remember` — durable memory, best-effort via REST (`MASSA_AI_API_URL`),
106
106
  file-only fallback when REST is unavailable.
@@ -22,8 +22,8 @@ human chose to merge it".
22
22
  | 1 | Isolate | `git fetch origin <base> && git worktree add -b <type>/<slug> <path> origin/<base>` | Branch name taken → suffix `-2`. Worktree path taken → reuse it only if its branch matches |
23
23
  | 2 | Implement | one task → gate → `git commit` | Gate red → fix before committing. Never commit through a failing gate |
24
24
  | 3 | Push | `git push -u origin <type>/<slug>` | Rejected non-fast-forward → `git fetch` + rebase, never force-push a shared branch |
25
- | 3.5 | Deliver specs | `python3 skills/massa-ai/scripts/check_specs_delivered.py <feature> [--root .]` | Non-zero → commit the missing `.specs/` updates (a `docs(specs):`-type commit is normal), push, re-run. Defensive fallback — should not fire when the close-out task already committed `.specs/` before the first push |
26
- | 4 | Propose — precondition: Stage 3.5 (`check_specs_delivered.py`) green | `gh pr create --base <base> --title <t> --body <b>` | `gh` absent/unauthenticated → degraded path |
25
+ | 3.5 | Deliver specs | `bun skills/massa-ai/scripts/check_specs_delivered.ts <feature> [--root .]` | Non-zero → commit the missing `.specs/` updates (a `docs(specs):`-type commit is normal), push, re-run. Defensive fallback — should not fire when the close-out task already committed `.specs/` before the first push |
26
+ | 4 | Propose — precondition: Stage 3.5 (`check_specs_delivered.ts`) green | `gh pr create --base <base> --title <t> --body <b>` | `gh` absent/unauthenticated → degraded path |
27
27
  | 5 | Watch | `gh pr checks --watch` | No checks configured → say so; do not claim CI passed |
28
28
  | 6 | Repair | fix on the branch, commit, return to stage 5 | Capped at 3 iterations, then stop as `Blocked` |
29
29
  | 7 | **Ask** | report the PR URL and the green check list, then **stop** | — |
@@ -76,7 +76,7 @@ One explicit delivery authorization per feature, obtained before implementation
76
76
 
77
77
  ### Stage 3.5 — deliver specs before PR (defensive fallback)
78
78
 
79
- Between Push and Propose, all feature `.specs/` artifacts (`spec/context/design/tasks/validation` as applicable), `.specs/project/STATE.md`, `.specs/HANDOFF.md`, and `.specs/project/FEATURES.json` must be updated and committed on the branch. **Deterministic backing (run it, do not eyeball it):** `python3 skills/massa-ai/scripts/check_specs_delivered.py <feature> [--root .]` — a non-zero exit blocks Propose. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
79
+ Between Push and Propose, all feature `.specs/` artifacts (`spec/context/design/tasks/validation` as applicable), `.specs/project/STATE.md`, `.specs/HANDOFF.md`, and `.specs/project/FEATURES.json` must be updated and committed on the branch. **Deterministic backing (run it, do not eyeball it):** `bun skills/massa-ai/scripts/check_specs_delivered.ts <feature> [--root .]` — a non-zero exit blocks Propose. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
80
80
 
81
81
  **Nominal path: this stage should never fire.** The feature's own close-out task (the last task before delivery — see `workflows/spec-driven.md` step 7) commits `.specs/` updates **before** the first push, so stage 3.5's remediation is a defensive fallback for the rare case something slipped through, not the normal place `.specs/` gets committed. On failure: commit the missing `.specs/` updates (a `docs(specs):`-type commit is normal), push, re-run this stage. No commits may land between the close-out commit and PR creation.
82
82
 
@@ -90,6 +90,18 @@ title: `[SA-100] Phase 1: search facade split`. The per-task commit prefixes on
90
90
  the branch are owned by `workflows/commit.md`; this stage owns only the PR-level
91
91
  phase prefix. Non-phased work keeps the existing PR title behavior unchanged.
92
92
 
93
+ ### Stages 3–7 — the PR description stays current
94
+
95
+ The PR description is a living artifact, not a creation-time snapshot. After
96
+ **every push requested while the PR exists** — repair iterations, follow-up
97
+ tasks, review-requested changes — update the PR description with
98
+ `gh pr edit <number> --body <b>` so it reflects the branch's current commit
99
+ set, scope, and evidence **before** returning to Watch. The description must be
100
+ current before the merge decision is requested; a merge may never be proposed
101
+ over a description that describes an older state of the branch. When generated
102
+ or bundled files are regenerated alongside source edits, the description names
103
+ that blast radius explicitly so reviewers do not undercount the diff.
104
+
93
105
  ### Stage 7 — merge is never automatic
94
106
 
95
107
  Do not run `gh pr merge` without explicit user approval given in the current
@@ -126,6 +138,8 @@ silently did not run is worse than one that loudly failed.
126
138
  - Merging because CI passed. CI passing is the precondition for asking, not the
127
139
  approval itself.
128
140
  - Reporting "done" while the branch is unpushed.
141
+ - Proposing or performing a merge while the PR description still describes an
142
+ older commit set — update it after each requested push, before merging.
129
143
 
130
144
  ## Completion Evidence
131
145
 
@@ -4,9 +4,8 @@ Use this reference when loading confirmed project lessons during startup, or rec
4
4
 
5
5
  ## Artifacts
6
6
 
7
- - `.specs/lessons.json` — canonical machine-owned lesson state. Read it; do not hand-edit.
8
- - `.specs/LESSONS.md` — rendered playbook generated by the script. Read it; do not hand-edit.
9
- - `skills/massa-ai/scripts/lessons.py` — deterministic bookkeeping script.
7
+ - `.specs/lessons.json` — canonical machine-owned lesson state, the single lessons store. Read it; do not hand-edit.
8
+ - `skills/massa-ai/scripts/lessons.ts` — deterministic bookkeeping script; `lessons list` is the on-demand view.
10
9
 
11
10
  ## Lesson Signal Table
12
11
 
@@ -23,7 +22,7 @@ Use this reference when loading confirmed project lessons during startup, or rec
23
22
  After a workflow's verification step finds a concrete reusable signal, record it:
24
23
 
25
24
  ```bash
26
- python3 skills/massa-ai/scripts/lessons.py --root . add \
25
+ bun skills/massa-ai/scripts/lessons.ts --root . add \
27
26
  --feature "<feature-slug>" \
28
27
  --signal "<ac_gap|surviving_mutant|spec_precision_gap|spec_deviation|gate_fail>" \
29
28
  --source "<validation.md source, AC id, file:line, mutant id, or SPEC_DEVIATION ref>" \
@@ -51,7 +50,7 @@ Run this self-check after verification: if a failed acceptance criterion, surviv
51
50
  During startup of any applicable workflow, load confirmed lessons when `.specs/lessons.json` exists:
52
51
 
53
52
  ```bash
54
- python3 skills/massa-ai/scripts/lessons.py --root . list --status confirmed [--scope <relevant>]
53
+ bun skills/massa-ai/scripts/lessons.ts --root . list --status confirmed [--scope <relevant>]
55
54
  ```
56
55
 
57
56
  - Use `--scope` or `--query` to keep the loaded set small.
@@ -69,7 +68,7 @@ python3 skills/massa-ai/scripts/lessons.py --root . list --status confirmed [--s
69
68
 
70
69
  ## No-Script Fallback
71
70
 
72
- If `lessons.py` is unavailable or cannot run, record `Lessons: skipped - script unavailable` in the validation report or evidence gate, keep the raw signal in the report, and do not hand-edit `lessons.json` or `LESSONS.md`. A future run with the script can import the validated signal.
71
+ If `lessons.ts` is unavailable or cannot run, record `Lessons: skipped - script unavailable` in the validation report or evidence gate, keep the raw signal in the report, and do not hand-edit `lessons.json`. A future run with the script can import the validated signal.
73
72
 
74
73
  ## Continuous-Learning Loop (hook-fed)
75
74
 
@@ -82,13 +81,13 @@ The lessons layer is a closed loop, not manual-only. Two runtime hooks
82
81
  2. **evaluate** — `continuous_learning_evaluate.py` (Stop) reads the active
83
82
  massa-ai context from `.specs/project/STATE.md` and the observations
84
83
  buffer. For each observation that already carries grounded fields
85
- (`signal`, `text`, `source`, `feature`), it calls `lessons.py add` with the
84
+ (`signal`, `text`, `source`, `feature`), it calls `lessons.ts add` with the
86
85
  `--project`/`--session`/`--workflow`/`--entity` context. Ungrounded
87
86
  observations are left in the buffer for agent input and logged as skipped.
88
87
 
89
88
  ### massa-ai Dual-Write
90
89
 
91
- `lessons.py add` and `import` best-effort write massa-ai memory so the file store
90
+ `lessons.ts add` and `import` best-effort write massa-ai memory so the file store
92
91
  and durable memory stay consistent:
93
92
 
94
93
  - **type** is always `pattern` (lessons are procedural knowledge). `procedural`
@@ -105,8 +104,8 @@ and durable memory stay consistent:
105
104
  ### Round-Trip
106
105
 
107
106
  ```bash
108
- python3 skills/massa-ai/scripts/lessons.py --root . export --out lessons.export.json
109
- python3 skills/massa-ai/scripts/lessons.py --root . import --in lessons.export.json
107
+ bun skills/massa-ai/scripts/lessons.ts --root . export --out lessons.export.json
108
+ bun skills/massa-ai/scripts/lessons.ts --root . import --in lessons.export.json
110
109
  ```
111
110
 
112
111
  `export`/`import` round-trip the file store; `import` re-emits massa-ai memory
@@ -285,7 +285,7 @@ delay. Preferred shell pattern:
285
285
  MASSA_AI_API_URL="${MASSA_AI_API_URL:-http://localhost:3333}"
286
286
  for i in $(seq 1 40); do
287
287
  result=$(rtk curl -s "$MASSA_AI_API_URL/api/v1/project/index/status/JOB_ID")
288
- status=$(printf '%s' "$result" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['status'])")
288
+ status=$(printf '%s' "$result" | bun -e "console.log(JSON.parse(await Bun.stdin.text()).data.status)")
289
289
  printf '[%s] status=%s\n' "$i" "$status"
290
290
  [ "$status" = "completed" ] || [ "$status" = "failed" ] && break
291
291
  sleep 15
@@ -76,6 +76,25 @@ For design, mobile Figma audit, or mobile Figma fix, load `references/mobile-fig
76
76
 
77
77
  Never rely on model self-evaluation. If device access, signing, credentials, provisioning, or hardware is unavailable, state the missing dependency and use the strongest available artifact or static proof.
78
78
 
79
+ ## Compose Screen Previews
80
+
81
+ In every implementation workflow, when the target surface is Android Jetpack
82
+ Compose or KMP (Kotlin Multiplatform) Compose Multiplatform, every created or
83
+ updated screen-level composable ships with `@Preview` composables in the same
84
+ change:
85
+
86
+ - Cover the representative states the change touches (default content, loading,
87
+ error, and empty where they exist), using preview parameter providers when
88
+ the project already uses them.
89
+ - Follow the project's existing preview conventions (naming, placement,
90
+ multipreview annotations, theme wrappers) rather than inventing new ones.
91
+ - Previews are validation assets: never delete or weaken an existing preview to
92
+ make a change compile, and treat a screen edit that leaves its previews stale
93
+ as incomplete work.
94
+ - On KMP, place previews in the source set where the project renders them
95
+ (commonMain multiplatform previews or per-platform preview hosts), matching
96
+ established project layout.
97
+
79
98
  ## Tests Lens
80
99
 
81
100
  When auditing or executing test work, check mobile-specific coverage for:
@@ -4,7 +4,7 @@ Use this reference when `workflows/debug.md` handles broken behavior involving K
4
4
 
5
5
  This extends `references/debug-diagnosis-loop.md`. Do not use it instead of the general debug loop.
6
6
 
7
- For non-debug mobile feature, refactor, tests, or security work, keep the intent-specific workflow and load `references/mobile-context.md` instead. Use `references/mobile-context.md` from Debug only when shared mobile vocabulary or non-bug parity/security/test framing is needed.
7
+ For non-debug mobile feature, refactor, tests, or security work, keep the intent-specific workflow and load `references/mobile-context.md` instead. Use `references/mobile-context.md` from Debug only when shared mobile vocabulary or non-bug parity/security/test framing is needed — and always when a fix creates or updates a Compose screen, because its Compose Screen Previews rule (`@Preview` coverage) applies to debug-path edits too.
8
8
 
9
9
  ## Mobile Intake
10
10
 
@@ -23,7 +23,7 @@ continue only when the next decision still needs more.
23
23
  | 2 — Host config | `.claude/` (`settings.json`, `settings.local.json`, `commands/`, `agents/`, `skills/`, `hooks/`), `.cursor/` (`rules/`, `mcp.json`), `.github/copilot-instructions.md`, `.opencode/`, `.codex/` | Permissions, hooks, host-specific tooling, MCP registrations |
24
24
  | 3 — Product docs | `README.md`, `CONTRIBUTING.md`, `docs/`, `ARCHITECTURE.md` | Install/run/build surface, contribution protocol, architecture |
25
25
  | 4 — Delivery config | `.github/workflows/`, `CHANGELOG.md`, `package.json` / `Cargo.toml` / `build.gradle*` / `pyproject.toml`, `.tool-versions`, `mise.toml`, `Makefile` | CI gates, release rules, runtime and toolchain pins, task commands |
26
- | 5 — Live state | `.specs/project/STATE.md`, `.specs/project/FEATURES.json`, `.specs/HANDOFF.md`, `.specs/LESSONS.md` | In-flight work, decisions already made, confirmed lessons |
26
+ | 5 — Live state | `.specs/project/STATE.md`, `.specs/project/FEATURES.json`, `.specs/HANDOFF.md`, `.specs/lessons.json` (single store; `lessons list` is the on-demand view) | In-flight work, decisions already made, confirmed lessons |
27
27
 
28
28
  Tier 1 and Tier 3 (`README.md`) are mandatory in every workflow. Tiers 2, 4, and
29
29
  5 are read when the task touches host tooling, a gate/release surface, or
@@ -27,8 +27,7 @@ Use these logical paths:
27
27
  - `.specs/features/<slug>/validation.md` — feature validation report
28
28
  - `.specs/quick/NNN-slug/TASK.md` — quick-mode task (one-line intent + acceptance)
29
29
  - `.specs/quick/NNN-slug/SUMMARY.md` — quick-mode result (files changed + gate evidence)
30
- - `.specs/lessons.json` — machine-owned lesson state (managed by `lessons.py`)
31
- - `.specs/LESSONS.md` — rendered lesson playbook (read-only, generated by `lessons.py`)
30
+ - `.specs/lessons.json` — the single lessons store, machine-owned (managed by `lessons.ts`); `lessons list` is the on-demand view
32
31
 
33
32
  ## Quick Artifacts
34
33
 
@@ -61,21 +60,21 @@ Quick tasks are also listed in the STATE.md Quick Tasks table (see `references/s
61
60
 
62
61
  Load only what you need. Prefer metadata-only inspection before loading full content.
63
62
 
64
- - **Feature registry status:** `cat .specs/project/FEATURES.json | python3 -c "import json,sys; d=json.load(sys.stdin); print('active:', d.get('active_feature')); [print(f['id'], f['status']) for f in d.get('features',[])]"`
63
+ - **Feature registry status:** `bun -e "const d=await Bun.file('.specs/project/FEATURES.json').json(); console.log('active:', d.active_feature); for (const f of d.features??[]) console.log(f.id, f.status);"`
65
64
  - **Full feature registry:** `cat .specs/project/FEATURES.json`
66
65
  - **Project state:** `cat .specs/project/STATE.md`
67
66
  - **Handoff:** `cat .specs/HANDOFF.md`
68
67
  - **Feature spec:** `cat .specs/features/<slug>/spec.md`
69
- - **Confirmed lessons:** `python3 skills/massa-ai/scripts/lessons.py --root . list --status confirmed [--scope <relevant>]`
68
+ - **Confirmed lessons:** `bun skills/massa-ai/scripts/lessons.ts --root . list --status confirmed [--scope <relevant>]`
70
69
 
71
70
  ## Writing Artifacts
72
71
 
73
- Write artifacts directly to `.specs/` files. Use a here-doc or `printf` for Markdown, or `python3 -c` for JSON mutations.
72
+ Write artifacts directly to `.specs/` files. Use a here-doc or `printf` for Markdown, or `bun -e` for JSON mutations.
74
73
 
75
74
  - **Update state:** `printf '...' > .specs/project/STATE.md`
76
75
  - **Update handoff:** `printf '...' > .specs/HANDOFF.md`
77
76
  - **Write feature artifact:** `printf '...' > .specs/features/<slug>/design.md`
78
- - **Update feature registry:** use `python3 -c` to read-modify-write `FEATURES.json`
77
+ - **Update feature registry:** use `bun -e` to read-modify-write `FEATURES.json`
79
78
 
80
79
  Feature activate/complete flows update `.specs/project/FEATURES.json`, `.specs/project/STATE.md`, and `.specs/HANDOFF.md` through file writes.
81
80
 
@@ -83,7 +82,7 @@ Feature activate/complete flows update `.specs/project/FEATURES.json`, `.specs/p
83
82
 
84
83
  - Feature artifacts under `.specs/features/<slug>/` are versioned by design (one file per slug).
85
84
  - `.specs/project/FEATURES.json` and `.specs/project/STATE.md` are append-only versioned by their git history.
86
- - `lessons.json` versioning is managed automatically by `lessons.py`.
85
+ - `lessons.json` versioning is managed automatically by `lessons.ts`.
87
86
  - When content must be superseded (e.g., a decision), update the existing file and rely on git history for the prior version.
88
87
 
89
88
  ## Debug Exports
@@ -94,5 +93,5 @@ Exports under `.specs-exports/` are optional, untracked review aids. Use `cp -r
94
93
 
95
94
  - `.specs/` directory missing or not writable: block spec-driven state mutation; do not fall back to memory or chat.
96
95
  - Required artifact missing: create it on first write or block unless it is an approved initial creation.
97
- - `lessons.py` unavailable: skip lessons loading/recording, record skipped reason in validation report.
96
+ - `lessons.ts` unavailable: skip lessons loading/recording, record skipped reason in validation report.
98
97
  .specs/ files
@@ -35,7 +35,7 @@ Read `.specs/features/<slug>/spec.md` before designing. If `.specs/features/<slu
35
35
 
36
36
  Silently ignoring an active decision is not an option — it creates invisible inconsistency across features.
37
37
 
38
- **Also load confirmed lessons** relevant to this feature: `python3 skills/massa-ai/scripts/lessons.py list --status confirmed` (filter with `--scope`/`--query`). These are past verification failures distilled into guidance — apply them while designing. Load only `confirmed`. Skip silently if no store or no code tool. See [lessons.md](lessons.md).
38
+ **Also load confirmed lessons** relevant to this feature: `bun skills/massa-ai/scripts/lessons.ts list --status confirmed` (filter with `--scope`/`--query`). These are past verification failures distilled into guidance — apply them while designing. Load only `confirmed`. Skip silently if no store or no code tool. See [lessons.md](lessons.md).
39
39
 
40
40
  ### 1.5. Research (Optional but Recommended)
41
41
 
@@ -302,13 +302,13 @@ for reuse across multiple endpoints.
302
302
  - Never sneak in "while I'm here" changes.
303
303
  - If tests are part of the task, include them in the same commit.
304
304
 
305
- **Deterministic backing (run it, do not eyeball it):** `python3 skills/massa-ai/scripts/check_commit.py --message "<your message>"` before committing. A non-zero exit means fix the format first — this makes the format rule enforceable instead of memory-dependent. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
305
+ **Deterministic backing (run it, do not eyeball it):** `bun skills/massa-ai/scripts/check_commit.ts --message "<your message>"` before committing. A non-zero exit means fix the format first — this makes the format rule enforceable instead of memory-dependent. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
306
306
 
307
307
  **Optional git-level guard (git only, no agent dependency).** In a git repo the same check can run on every commit by wiring it as a `commit-msg` hook, so a malformed message is rejected regardless of who or what drives the commit:
308
308
 
309
309
  ```bash
310
310
  # from the repo root, one time:
311
- ln -sf skills/massa-ai/scripts/check_commit.py .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
311
+ ln -sf skills/massa-ai/scripts/check_commit.ts .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
312
312
  ```
313
313
 
314
314
  This is a plain git hook, not tied to any editor or assistant. Skip it if the project manages hooks its own way (for example a pre-commit framework); the manual check above still applies.
@@ -316,14 +316,14 @@ This is a plain git hook, not tied to any editor or assistant. Skip it if the pr
316
316
  **Distill a confirmed lesson** when a task produced a reusable signal (an unexpected failure mode, a confirmed pattern, a corrected assumption):
317
317
 
318
318
  ```
319
- python3 skills/massa-ai/scripts/lessons.py --root . add \
319
+ bun skills/massa-ai/scripts/lessons.ts --root . add \
320
320
  --feature <slug> --signal <S> --source <src> --text "<T>" --scope <O>
321
321
  ```
322
322
 
323
323
  `--source` is mandatory (grounding gate). Load applicable confirmed lessons before starting a task:
324
324
 
325
325
  ```
326
- python3 skills/massa-ai/scripts/lessons.py --root . list --status confirmed [--scope <relevant>]
326
+ bun skills/massa-ai/scripts/lessons.ts --root . list --status confirmed [--scope <relevant>]
327
327
  ```
328
328
 
329
329
  ### 8. Scope Guardrail / Scope Control
@@ -452,7 +452,7 @@ Then run `references/spec-driven/validate.md` as the final Execute gate. The ver
452
452
  **Status**: ✅ Complete | ❌ Blocked | ⚠️ Partial
453
453
  ```
454
454
 
455
- **After the LAST task:** dispatch the Verifier sub-agent (see step 9 and [sub-agents.md](sub-agents.md)) for independent feature-level validation, including the spec-anchored check and discrimination sensor. Validation always runs automatically — never prompted. Execute is not done until the Verifier reports PASS and the validation report is written, confirmed deterministically by `python3 skills/massa-ai/scripts/validate_state.py <feature> [--root .]` (exit non-zero = not done); see [validate.md](validate.md). If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
455
+ **After the LAST task:** dispatch the Verifier sub-agent (see step 9 and [sub-agents.md](sub-agents.md)) for independent feature-level validation, including the spec-anchored check and discrimination sensor. Validation always runs automatically — never prompted. Execute is not done until the Verifier reports PASS and the validation report is written, confirmed deterministically by `bun skills/massa-ai/scripts/validate_state.ts <feature> [--root .]` (exit non-zero = not done); see [validate.md](validate.md). If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
456
456
 
457
457
  ---
458
458
 
@@ -9,7 +9,7 @@ If the feature has ambiguous gray areas (multiple valid approaches for user-faci
9
9
  - First user request and any supplied requirement source.
10
10
  - Current repository source and docs needed to understand scope.
11
11
  - Existing `.specs/features/<slug>/` artifacts when resuming.
12
- - `.specs/LESSONS.md` only when lessons are enabled by existing lesson artifacts.
12
+ - `.specs/lessons.json` (via `lessons list`) only when lessons are enabled by existing lesson artifacts.
13
13
 
14
14
  ## Required Sections
15
15
 
@@ -65,7 +65,7 @@ The table is canonical; the prose is the applied sweep. **Large/Complex** work m
65
65
 
66
66
  ### 1. Clarify Requirements
67
67
 
68
- **Load confirmed lessons first:** Before clarifying, load the project's confirmed lessons so past verification failures shape this spec instead of repeating. Run `python3 skills/massa-ai/scripts/lessons.py --root . list --status confirmed` (optionally `--scope [area]` or `--query [term]` for the area this feature touches) and apply what comes back as guidance. Load only `confirmed` — never `candidate` or `quarantined`. If no store exists yet or no code tool is available, skip silently. See [lessons.md](../lessons.md).
68
+ **Load confirmed lessons first:** Before clarifying, load the project's confirmed lessons so past verification failures shape this spec instead of repeating. Run `bun skills/massa-ai/scripts/lessons.ts --root . list --status confirmed` (optionally `--scope [area]` or `--query [term]` for the area this feature touches) and apply what comes back as guidance. Load only `confirmed` — never `candidate` or `quarantined`. If no store exists yet or no code tool is available, skip silently. See [lessons.md](../lessons.md).
69
69
 
70
70
  **Lightweight context scan first (Knowledge Verification Chain Step 1):** Before asking questions, briefly scan existing code, patterns, and neighboring features relevant to this feature. Prefer massa-ai tooling first (`list_projects`, `search`, `project_map`, `optimized_context`) before `ast-grep`/`rg`/`grep`, honoring freshness and source-precedence (current source overrides stale index/memory). Use what you find to ground your clarifying questions in reality — not to constrain the spec to current implementation. Keep it lightweight (stay within the <40k token budget; reuse the chain, no new machinery). The spec captures WHAT is needed, not only what exists.
71
71
 
@@ -115,7 +115,7 @@ Write every acceptance criterion in **EARS** (Easy Approach to Requirements Synt
115
115
 
116
116
  **Why patterns beat one shape:** failure states, state transitions, and optional behavior become first-class criteria instead of footnotes squeezed into WHEN/THEN. The patterns map onto the implicit-requirement dimensions above: state-transition integrity to State-driven; failure and external-dependency failure to Unwanted-behavior; feature flags to Optional-feature.
117
117
 
118
- **Rules:** one requirement per criterion (never bundle two behaviors); use concrete values (a specific status code, a specific message, a bound) rather than "quickly" or "gracefully"; every criterion contains a SHALL and is measurable. `python3 skills/massa-ai/scripts/validate_spec.py` flags any criterion without a SHALL and any that matches no recognized pattern.
118
+ **Rules:** one requirement per criterion (never bundle two behaviors); use concrete values (a specific status code, a specific message, a bound) rather than "quickly" or "gracefully"; every criterion contains a SHALL and is measurable. `bun skills/massa-ai/scripts/validate_spec.ts` flags any criterion without a SHALL and any that matches no recognized pattern.
119
119
 
120
120
  ### 4. Requirement Closure Gate (before confirm)
121
121
 
@@ -135,7 +135,7 @@ Before Design, Tasks, or Execute — and before presenting the spec for confirma
135
135
 
136
136
  6. **Continue only when** the Open Questions table is empty or every row has an accepted assumption.
137
137
 
138
- 7. **Deterministic backing (run it, do not eyeball it):** `python3 skills/massa-ai/scripts/validate_spec.py <feature> [--root .]` checks that required sections exist, every AC is EARS-shaped (has a SHALL), no Assumptions row has an empty default or rationale, and requirement IDs are well-formed. A non-zero exit means fix before confirming — the script checks structure; the judgment calls (is the interpretation right, is the outcome precise) stay yours. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
138
+ 7. **Deterministic backing (run it, do not eyeball it):** `bun skills/massa-ai/scripts/validate_spec.ts <feature> [--root .]` checks that required sections exist, every AC is EARS-shaped (has a SHALL), no Assumptions row has an empty default or rationale, and requirement IDs are well-formed. A non-zero exit means fix before confirming — the script checks structure; the judgment calls (is the interpretation right, is the outcome precise) stay yours. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
139
139
 
140
140
  Fix inline. This gate is bounded to THIS feature's stated dimensions and actual behavior — never to "anything imaginable." The Out of Scope table and anti-scope-creep rules remain the counterweights: the gate clarifies existing requirements, it never invents new ones.
141
141
 
@@ -286,13 +286,13 @@ How we know the feature is successful:
286
286
  - **Edge cases matter** — What breaks? What's empty? What's huge?
287
287
  - **Out of Scope prevents creep** — If it's not here, it doesn't get built
288
288
  - **Closure gate before confirm** — Three checks: unambiguity + precision, open-questions/assumptions closure, declined gray areas logged; scope-tiered; bounded to stated dimensions; never invents requirements
289
- - **Confirm after the gate passes** — Present the spec for user confirmation only after the closure gate passes (no unresolved-and-unmarked items remain) and `validate_spec.py` exits clean; user approves spec before moving to the discuss phase
289
+ - **Confirm after the gate passes** — Present the spec for user confirmation only after the closure gate passes (no unresolved-and-unmarked items remain) and `validate_spec.ts` exits clean; user approves spec before moving to the discuss phase
290
290
 
291
291
  ---
292
292
 
293
293
  ## Done
294
294
 
295
- Specify is done when every requirement has an ID, acceptance criteria are testable EARS statements, edge cases are named, out-of-scope boundaries are explicit, implicit-requirement dimensions are resolved or marked `N/A because <reason>`, the Requirement Closure Gate is satisfied, and `validate_spec.py` exits clean (or the no-code-execution-tool fallback was applied).
295
+ Specify is done when every requirement has an ID, acceptance criteria are testable EARS statements, edge cases are named, out-of-scope boundaries are explicit, implicit-requirement dimensions are resolved or marked `N/A because <reason>`, the Requirement Closure Gate is satisfied, and `validate_spec.ts` exits clean (or the no-code-execution-tool fallback was applied).
296
296
 
297
297
  ## Massa-ai Integration
298
298
 
@@ -148,7 +148,7 @@ Delegated work returns through the compact summary contract above. Planning, tas
148
148
 
149
149
  ## Standalone Fallback
150
150
 
151
- When sub-agents are unavailable (a single agent executing the full feature), use the standalone fresh-eyes fallback: run `references/spec-driven/validate.md` as a standalone pass — clear implementation assumptions, re-read `spec.md` and the diff from scratch, apply evidence-or-zero, run the spec-anchored coverage check and discrimination sensor, and write `.specs/features/<slug>/validation.md`. **Deterministic backing (run it, do not eyeball it):** `python3 skills/massa-ai/scripts/validate_state.py <feature> [--root .]` confirms the report is a real PASS before the feature is marked done. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
151
+ When sub-agents are unavailable (a single agent executing the full feature), use the standalone fresh-eyes fallback: run `references/spec-driven/validate.md` as a standalone pass — clear implementation assumptions, re-read `spec.md` and the diff from scratch, apply evidence-or-zero, run the spec-anchored coverage check and discrimination sensor, and write `.specs/features/<slug>/validation.md`. **Deterministic backing (run it, do not eyeball it):** `bun skills/massa-ai/scripts/validate_state.ts <feature> [--root .]` confirms the report is a real PASS before the feature is marked done. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
152
152
 
153
153
  ---
154
154
 
@@ -157,7 +157,7 @@ This keeps phase boundaries meaningful while letting the packing hit its target
157
157
 
158
158
  Before showing tasks to the user, run ALL three pre-approval checks. These are NOT optional — they are gates. If any check fails, restructure the tasks and re-run until all pass.
159
159
 
160
- **Deterministic backing (run it, do not eyeball it):** `python3 skills/massa-ai/scripts/validate_tasks.py <feature> [--root .]` enforces the structural half of these checks so they cannot drift: it flags a `Where` that names multiple files (granularity smell, Check 1), a diagram edge with no matching `Depends on` within a phase and vice-versa (Check 2), a task missing its `Tests` or `Gate` field, a `Tests: none` to confirm against the matrix (Check 3), and any dependency pointing to a later phase. A non-zero exit means restructure before presenting. The script checks structure; the two tables below (the layer-to-test co-location judgment) are still yours. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
160
+ **Deterministic backing (run it, do not eyeball it):** `bun skills/massa-ai/scripts/validate_tasks.ts <feature> [--root .]` enforces the structural half of these checks so they cannot drift: it flags a `Where` that names multiple files (granularity smell, Check 1), a diagram edge with no matching `Depends on` within a phase and vice-versa (Check 2), a task missing its `Tests` or `Gate` field, a `Tests: none` to confirm against the matrix (Check 3), and any dependency pointing to a later phase. A non-zero exit means restructure before presenting. The script checks structure; the two tables below (the layer-to-test co-location judgment) are still yours. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
161
161
 
162
162
  **Check 1: Task Granularity** — verify each task is atomic (see Granularity Check section).
163
163
 
@@ -516,4 +516,4 @@ Before sampling tests manually, prefer massa-ai tooling to read the codebase:
516
516
 
517
517
  ## Done
518
518
 
519
- Tasks is done when every in-scope requirement maps to one or more executable tasks, dependencies are explicit, the Test Coverage Matrix and Gate Check Commands are present, project testing guideline scan and pre-approval checks are recorded, the three mandatory pre-approval tables (Granularity, Diagram-Definition Cross-Check, Test Co-location Validation) pass, `validate_tasks.py` exits clean (or the no-code-execution-tool fallback was applied), and each task has deterministic validation with artifact-store evidence recorded.
519
+ Tasks is done when every in-scope requirement maps to one or more executable tasks, dependencies are explicit, the Test Coverage Matrix and Gate Check Commands are present, project testing guideline scan and pre-approval checks are recorded, the three mandatory pre-approval tables (Granularity, Diagram-Definition Cross-Check, Test Co-location Validation) pass, `validate_tasks.ts` exits clean (or the no-code-execution-tool fallback was applied), and each task has deterministic validation with artifact-store evidence recorded.
@@ -204,14 +204,14 @@ After all checks complete, the Verifier MUST:
204
204
  1. **Write the persisted report** to `.specs/features/<slug>/validation.md` (see template below). This file is the evidence artifact — it survives the session and can be referenced by CI, reviewers, or future agents. Record in `.specs/project/STATE.md` (Decisions) that validation evidence is available at that path.
205
205
  2. **Return a compact summary in chat** to the orchestrator (see Compact Chat Summary section below). The orchestrator surfaces it to the user and routes any ranked gaps to fix tasks.
206
206
 
207
- **Deterministic backing (run it, do not eyeball it):** after writing the report, run `python3 skills/massa-ai/scripts/validate_state.py <feature> [--root .]`. It confirms the report is real — present, verdict filled to PASS, and backed by at least one `file:line` evidence citation — so a missing, hollow, placeholder, or FAIL report cannot slip through as done. A non-zero exit means the feature is NOT done: repair the report or route the FAIL gaps to fix tasks, then re-run. This is the closing gate of Execute and runs automatically, the same way the lessons layer runs at distillation — never a manual step. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
207
+ **Deterministic backing (run it, do not eyeball it):** after writing the report, run `bun skills/massa-ai/scripts/validate_state.ts <feature> [--root .]`. It confirms the report is real — present, verdict filled to PASS, and backed by at least one `file:line` evidence citation — so a missing, hollow, placeholder, or FAIL report cannot slip through as done. A non-zero exit means the feature is NOT done: repair the report or route the FAIL gaps to fix tasks, then re-run. This is the closing gate of Execute and runs automatically, the same way the lessons layer runs at distillation — never a manual step. If no code-execution tool is available, run the same checks by reading the artifact (graceful degradation preserved).
208
208
 
209
209
  ### 10. Distill Lessons (MANDATORY when validation.md has signal)
210
210
 
211
211
  This is the closing action of validation — not a separate phase. Immediately after the report is written, turn its grounded failures into reusable, project-local guidance by following [references/lessons.md](../lessons.md) and the stub at [references/spec-driven/lessons.md](lessons.md). In short: for each surviving mutant, spec-precision gap, failed/uncovered AC, or `// SPEC_DEVIATION`, record one terse general lesson via:
212
212
 
213
213
  ```bash
214
- python3 skills/massa-ai/scripts/lessons.py --root . add --feature <slug> --signal "<signal>" --source "<source>" --text "<lesson>" --scope "<scope>"
214
+ bun skills/massa-ai/scripts/lessons.ts --root . add --feature <slug> --signal "<signal>" --source "<source>" --text "<lesson>" --scope "<scope>"
215
215
  ```
216
216
 
217
217
  The script enforces grounding (mandatory `--source`) and owns all bookkeeping. A clean PASS with no signal → record nothing. Run the self-check: if there was signal but no lesson was recorded, say so in chat. See [references/lessons.md](../lessons.md) for the exact commands, phrasing rules, scope discipline, and the no-script fallback.
@@ -398,5 +398,5 @@ Update `.specs/features/<slug>/spec.md` requirement statuses and reflect verifie
398
398
  - **Max 3 diagnostic iterations** — Prevents infinite investigation loops
399
399
  - **Update traceability** — Every verified requirement updates spec.md status and the FEATURES.json registry
400
400
  - **Always write the report file** — `.specs/features/<slug>/validation.md` is the persisted evidence artifact
401
- - **Distill after writing** — turn grounded failures into lessons via `python3 skills/massa-ai/scripts/lessons.py` ([references/lessons.md](../lessons.md)); clean PASS → no lesson
401
+ - **Distill after writing** — turn grounded failures into lessons via `bun skills/massa-ai/scripts/lessons.ts` ([references/lessons.md](../lessons.md)); clean PASS → no lesson
402
402
  - **Independence first** — prefer a fresh read-only verifier; the author never verifies their own work when tooling allows