mutate4py 0.1.0__tar.gz

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 (146) hide show
  1. mutate4py-0.1.0/.agents/backlog.md +19 -0
  2. mutate4py-0.1.0/.agents/ledger-project.md +54 -0
  3. mutate4py-0.1.0/.agents/ledger-swarmforge.md +68 -0
  4. mutate4py-0.1.0/.agents/references/equivalent-mutants.md +21 -0
  5. mutate4py-0.1.0/.agents/roles/QA.md +16 -0
  6. mutate4py-0.1.0/.agents/roles/cleaner.md +10 -0
  7. mutate4py-0.1.0/.agents/roles/coder.md +10 -0
  8. mutate4py-0.1.0/.agents/roles/hardender.md +32 -0
  9. mutate4py-0.1.0/.agents/skills/agent-retro/SKILL.md +219 -0
  10. mutate4py-0.1.0/.agents/skills/agent-retro/scripts/extract.py +940 -0
  11. mutate4py-0.1.0/.agents/skills/domain-modeling/ADR-FORMAT.md +47 -0
  12. mutate4py-0.1.0/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  13. mutate4py-0.1.0/.agents/skills/domain-modeling/SKILL.md +74 -0
  14. mutate4py-0.1.0/.agents/skills/explain/SKILL.md +34 -0
  15. mutate4py-0.1.0/.agents/skills/grill-with-docs/SKILL.md +7 -0
  16. mutate4py-0.1.0/.agents/skills/grilling/SKILL.md +10 -0
  17. mutate4py-0.1.0/.agents/skills/recall/SKILL.md +123 -0
  18. mutate4py-0.1.0/.agents/skills/replay/SKILL.md +141 -0
  19. mutate4py-0.1.0/.agents/skills/review/SKILL.md +220 -0
  20. mutate4py-0.1.0/.agents/skills/review/references/review-rules.md +87 -0
  21. mutate4py-0.1.0/.agents/skills/search/SKILL.md +70 -0
  22. mutate4py-0.1.0/.agents/skills/session-crosslink/SKILL.md +141 -0
  23. mutate4py-0.1.0/.agents/skills/session-handoff/SKILL.md +137 -0
  24. mutate4py-0.1.0/.agents/skills/session-to-skill/SKILL.md +210 -0
  25. mutate4py-0.1.0/.agents/skills/setup-swarm/SKILL.md +150 -0
  26. mutate4py-0.1.0/.agents/skills/teach/SKILL.md +130 -0
  27. mutate4py-0.1.0/.agents/skills/using-entire/SKILL.md +149 -0
  28. mutate4py-0.1.0/.agents/skills/what-happened/SKILL.md +333 -0
  29. mutate4py-0.1.0/.claude/agents/entire-search.md +25 -0
  30. mutate4py-0.1.0/.claude/settings.json +85 -0
  31. mutate4py-0.1.0/.entire/.gitignore +5 -0
  32. mutate4py-0.1.0/.entire/settings.json +10 -0
  33. mutate4py-0.1.0/.github/workflows/ci.yml +53 -0
  34. mutate4py-0.1.0/.github/workflows/release.yml +29 -0
  35. mutate4py-0.1.0/.gitignore +25 -0
  36. mutate4py-0.1.0/AGENTS.md +38 -0
  37. mutate4py-0.1.0/CONTEXT.md +204 -0
  38. mutate4py-0.1.0/LICENSE +21 -0
  39. mutate4py-0.1.0/PKG-INFO +70 -0
  40. mutate4py-0.1.0/README.md +55 -0
  41. mutate4py-0.1.0/acceptance/__init__.py +0 -0
  42. mutate4py-0.1.0/acceptance/fixtures/empty_units.py +9 -0
  43. mutate4py-0.1.0/acceptance/fixtures/mixed_operators.py +10 -0
  44. mutate4py-0.1.0/acceptance/fixtures/module_level.py +4 -0
  45. mutate4py-0.1.0/acceptance/fixtures/plain.py +6 -0
  46. mutate4py-0.1.0/acceptance/fixtures/stale.py +11 -0
  47. mutate4py-0.1.0/acceptance/generate_acceptance.py +153 -0
  48. mutate4py-0.1.0/acceptance/run_acceptance.sh +142 -0
  49. mutate4py-0.1.0/acceptance/run_gherkin_mutation.sh +95 -0
  50. mutate4py-0.1.0/acceptance/runner_adapter.py +192 -0
  51. mutate4py-0.1.0/acceptance/steps/__init__.py +0 -0
  52. mutate4py-0.1.0/acceptance/steps/cli_surface_helpers.py +176 -0
  53. mutate4py-0.1.0/acceptance/steps/cli_surface_qa_steps.py +297 -0
  54. mutate4py-0.1.0/acceptance/steps/cli_surface_steps.py +194 -0
  55. mutate4py-0.1.0/acceptance/steps/coverage_helpers.py +187 -0
  56. mutate4py-0.1.0/acceptance/steps/coverage_qa_steps.py +266 -0
  57. mutate4py-0.1.0/acceptance/steps/coverage_steps.py +206 -0
  58. mutate4py-0.1.0/acceptance/steps/manifest_qa_steps.py +247 -0
  59. mutate4py-0.1.0/acceptance/steps/manifest_steps.py +455 -0
  60. mutate4py-0.1.0/acceptance/steps/parallel_workers_qa_steps.py +617 -0
  61. mutate4py-0.1.0/acceptance/steps/parallel_workers_steps.py +681 -0
  62. mutate4py-0.1.0/acceptance/steps/run_loop_helpers.py +86 -0
  63. mutate4py-0.1.0/acceptance/steps/run_loop_qa_steps.py +396 -0
  64. mutate4py-0.1.0/acceptance/steps/run_loop_steps.py +621 -0
  65. mutate4py-0.1.0/acceptance/steps/site_discovery_qa_steps.py +198 -0
  66. mutate4py-0.1.0/acceptance/steps/site_discovery_steps.py +241 -0
  67. mutate4py-0.1.0/acceptance/steps/step_lib.py +83 -0
  68. mutate4py-0.1.0/check.sh +99 -0
  69. mutate4py-0.1.0/docs/adr/0001-site-discovery-and-operators.md +102 -0
  70. mutate4py-0.1.0/docs/adr/0002-scan-counts-only-no-manifest-in-f1.md +63 -0
  71. mutate4py-0.1.0/docs/adr/0003-ci-skeleton-crap-and-mutation-gates-deferred.md +62 -0
  72. mutate4py-0.1.0/docs/adr/0004-manifest-faithful-port-of-mutate4go.md +72 -0
  73. mutate4py-0.1.0/docs/adr/0005-manifest-hash-is-ast-dump.md +47 -0
  74. mutate4py-0.1.0/docs/adr/0006-update-manifest-idempotent.md +57 -0
  75. mutate4py-0.1.0/docs/adr/0007-coverage-default-path-and-line-only-gate.md +49 -0
  76. mutate4py-0.1.0/docs/adr/0008-coverage-flags-pairwise-exclusive.md +39 -0
  77. mutate4py-0.1.0/docs/adr/0009-coverage-partition-surfaces-via-scan.md +48 -0
  78. mutate4py-0.1.0/docs/adr/0010-run-loop-composes-f3-coverage-and-baseline-gate.md +42 -0
  79. mutate4py-0.1.0/docs/adr/0011-timeout-printed-verbatim-folded-into-killed.md +45 -0
  80. mutate4py-0.1.0/docs/adr/0012-run-loop-serial-only-no-worker-token.md +64 -0
  81. mutate4py-0.1.0/docs/adr/0013-max-workers-restored-as-real-flag.md +62 -0
  82. mutate4py-0.1.0/docs/adr/0014-cli-validation-mirrors-upstream-parse-model.md +52 -0
  83. mutate4py-0.1.0/docs/adr/0015-parallel-workers-via-uv-clone-per-worker.md +118 -0
  84. mutate4py-0.1.0/docs/plan.md +258 -0
  85. mutate4py-0.1.0/docs/spec.md +383 -0
  86. mutate4py-0.1.0/features/ci.feature +92 -0
  87. mutate4py-0.1.0/features/cli-surface.feature +230 -0
  88. mutate4py-0.1.0/features/cli-surface_qa.feature +117 -0
  89. mutate4py-0.1.0/features/coverage.feature +169 -0
  90. mutate4py-0.1.0/features/coverage_qa.feature +145 -0
  91. mutate4py-0.1.0/features/manifest.feature +215 -0
  92. mutate4py-0.1.0/features/manifest_qa.feature +99 -0
  93. mutate4py-0.1.0/features/parallel-workers.feature +294 -0
  94. mutate4py-0.1.0/features/parallel-workers_qa.feature +154 -0
  95. mutate4py-0.1.0/features/run-loop.feature +247 -0
  96. mutate4py-0.1.0/features/run-loop_qa.feature +144 -0
  97. mutate4py-0.1.0/features/site-discovery.feature +157 -0
  98. mutate4py-0.1.0/features/site-discovery_qa.feature +97 -0
  99. mutate4py-0.1.0/features/test-selection.feature +55 -0
  100. mutate4py-0.1.0/perf.sh +89 -0
  101. mutate4py-0.1.0/pyproject.toml +58 -0
  102. mutate4py-0.1.0/src/mutate4py/__init__.py +3 -0
  103. mutate4py-0.1.0/src/mutate4py/__main__.py +431 -0
  104. mutate4py-0.1.0/src/mutate4py/_cmd.py +25 -0
  105. mutate4py-0.1.0/src/mutate4py/_coverage.py +123 -0
  106. mutate4py-0.1.0/src/mutate4py/_discovery.py +323 -0
  107. mutate4py-0.1.0/src/mutate4py/_ids.py +21 -0
  108. mutate4py-0.1.0/src/mutate4py/_manifest.py +172 -0
  109. mutate4py-0.1.0/src/mutate4py/_runner.py +629 -0
  110. mutate4py-0.1.0/src/mutate4py/_test_selection.py +113 -0
  111. mutate4py-0.1.0/src/mutate4py/_workers.py +241 -0
  112. mutate4py-0.1.0/swarm +127 -0
  113. mutate4py-0.1.0/swarmforge/constitution/articles/engineering.prompt +44 -0
  114. mutate4py-0.1.0/swarmforge/constitution/articles/handoffs.prompt +83 -0
  115. mutate4py-0.1.0/swarmforge/constitution/articles/local-engineering.prompt +11 -0
  116. mutate4py-0.1.0/swarmforge/constitution/articles/local-workflow.prompt +11 -0
  117. mutate4py-0.1.0/swarmforge/constitution/articles/project.prompt +15 -0
  118. mutate4py-0.1.0/swarmforge/constitution/articles/workflow.prompt +21 -0
  119. mutate4py-0.1.0/swarmforge/constitution.prompt +4 -0
  120. mutate4py-0.1.0/swarmforge/roles/QA.prompt +27 -0
  121. mutate4py-0.1.0/swarmforge/roles/architect.prompt +41 -0
  122. mutate4py-0.1.0/swarmforge/roles/cleaner.prompt +35 -0
  123. mutate4py-0.1.0/swarmforge/roles/coder.prompt +31 -0
  124. mutate4py-0.1.0/swarmforge/roles/curator.prompt +82 -0
  125. mutate4py-0.1.0/swarmforge/roles/hardender.prompt +32 -0
  126. mutate4py-0.1.0/swarmforge/roles/integrator.prompt +42 -0
  127. mutate4py-0.1.0/swarmforge/roles/specifier.prompt +42 -0
  128. mutate4py-0.1.0/swarmforge/roles/ux-engineer.prompt +30 -0
  129. mutate4py-0.1.0/swarmforge/skills/agent-retro/SKILL.md +219 -0
  130. mutate4py-0.1.0/swarmforge/skills/agent-retro/scripts/extract.py +940 -0
  131. mutate4py-0.1.0/swarmforge/skills/setup-swarm/SKILL.md +150 -0
  132. mutate4py-0.1.0/swarmforge/swarmforge.conf +20 -0
  133. mutate4py-0.1.0/swarmforge/templates/feature.feature +82 -0
  134. mutate4py-0.1.0/tests/__init__.py +0 -0
  135. mutate4py-0.1.0/tests/test_cli_surface_helpers.py +351 -0
  136. mutate4py-0.1.0/tests/test_cmd.py +41 -0
  137. mutate4py-0.1.0/tests/test_coverage.py +373 -0
  138. mutate4py-0.1.0/tests/test_coverage_helpers.py +304 -0
  139. mutate4py-0.1.0/tests/test_discovery.py +433 -0
  140. mutate4py-0.1.0/tests/test_main.py +1642 -0
  141. mutate4py-0.1.0/tests/test_manifest.py +625 -0
  142. mutate4py-0.1.0/tests/test_properties.py +370 -0
  143. mutate4py-0.1.0/tests/test_runner.py +1179 -0
  144. mutate4py-0.1.0/tests/test_test_selection.py +350 -0
  145. mutate4py-0.1.0/tests/test_workers.py +348 -0
  146. mutate4py-0.1.0/uv.lock +731 -0
@@ -0,0 +1,19 @@
1
+ # Enforcement Gate Backlog
2
+
3
+ Dated proposals for mechanical enforcement gates, config changes, or CI guardrails.
4
+ Format: `<date> | <category> | <failure-class> | <affected> | <status> | <description>`
5
+
6
+ ---
7
+ 2026-06-28 | swarmforge-pattern | convention-gap | specifier | pending | Glossary canon is CONTEXT.md (## Glossary) per domain-modeling skill + sibling mutate4js, but F1-F4 specifier sessions wrote entries into an orphan docs/glossary.md (nothing linked it; the two drifted). Consolidated into CONTEXT.md and deleted docs/glossary.md in F5. specifier.prompt phase 3 says "glossary entries are part of the deliverable" without naming the file — add "write glossary terms to CONTEXT.md ## Glossary, never docs/glossary.md".
8
+ 2026-06-25 | project-config | tool-error | all-roles | pending | Disable GPG commit signing in all worktrees' .git/config to eliminate 1Password SSH agent failures (git config --local commit.gpgsign false per worktree, or a global swarm setup step)
9
+ 2026-06-25 | swarmforge-pattern | tool-error | architect,cleaner | pending | 1Password SSH agent unavailable in swarm sessions causes git fetch and commit signing failures; two roles required manual workaround (-c commit.gpgsign=false); setup-swarm should disable signing in each worktree
10
+ 2026-06-25 | swarmforge-pattern | tool-error | cleaner,QA,hardender | pending | External GitHub tool installs blocked by auto-mode classifier across 3 roles; engineering.prompt needs explicit fallback rule: "if external install is blocked, use locally installed binary and continue"
11
+ 2026-06-25 | swarmforge-pattern | tool-error | cleaner,QA,hardender | pending | extract.py returns zero non-null arc content on Claude Code 2.1.191+ across all roles (5 sessions: architect, cleaner, integrator, hardender, QA); investigate JSONL format change and update extract.py
12
+ 2026-06-26 | swarmforge-pattern | tool-error | specifier,coder,cleaner,architect,hardender,QA | pending | extract.py arc null-content now confirmed across 9+ sessions and 6 roles in CC 2.1.193; this is now critical-path for all agent-retro data analysis — ESCALATE
13
+ 2026-06-26 | swarmforge-pattern | convention-gap | specifier,specifier | pending | ir-dry-checker (specifier phase 6) is not installed; two specifier sessions in this pipeline hit it; either ship the tool or reword phase 6 to manual-prune
14
+ 2026-06-26 | swarmforge-pattern | convention-gap | specifier,architect | pending | role-level tool API discovery gap: both specifier (grill-with-docs invocation failure) and architect (fc.hexaString/fc.float missing) were blocked by undocumented API surfaces; add "run --help or grep available API before using any unfamiliar tool/library function" to constitution
15
+ 2026-06-26 | swarmforge-pattern | convention-gap | cleaner,QA,integrator | pending | pre-handoff lint+format verification gap: cleaner and QA do not run ruff check+format before handing off; integrator absorbs 2+ fix-push-watch cycles per pipeline run; add mandatory pre-handoff lint+format step to engineering verification
16
+ 2026-06-26 | swarmforge-pattern | missing-artifact | coder,QA,cleaner | pending | drywall DRY check blocked by auto-mode sandbox across 3 roles attempting binary download; pre-install drywall in worktree setup or grant explicit permission in project settings.json
17
+ 2026-06-26 | swarmforge-pattern | missing-artifact | QA,cleaner | pending | merge_and_process <role> <commit> appears in handoff PAYLOADs for non-hardender roles but no such script exists; both QA and cleaner had to infer the merge intent manually; either ship the script for all roles or update handoff spec to document the convention
18
+ 2026-06-28 | swarmforge-pattern | tool-error | hardender | pending | uv re-provisioning per Gherkin mutation makes acceptance mutation slow (~10s/mutation); consider pre-provisioning worker trees once in a shared acceptance fixture or mocking _provision_worker in acceptance scenarios to avoid per-mutation cost
19
+ 2026-06-28 | swarmforge-pattern | convention-gap | integrator | pending | gh pr create blocked by auto-mode classifier even when integrator role prompt explicitly owns "Open the PR"; consider pre-authorizing integrator's gh pr create in project settings.json allowlist
@@ -0,0 +1,54 @@
1
+ # Ledger — Project Knowledge
2
+
3
+ Permanent, append-only. Contains only `promoted` and `rejected→first-occurrence` items.
4
+ Format: `<date> | <session-id> | <role> | <failure-class> | <verdict> | <one-line summary>`
5
+
6
+ ---
7
+ 2026-06-25 | 9bc9e159 | architect | convention-gap | promoted→AGENTS.md | Correct role name spelling: hardender (two d's); worktree dir names are authoritative
8
+ 2026-06-25 | 9bc9e159 | architect | tool-error | rejected→first-occurrence | extract.py null-arc: all arc entries return null content on Claude Code 2.1.191
9
+ 2026-06-25 | 00466112 | cleaner | missing-artifact | promoted→AGENTS.md | drywall at /Users/gabadi/.local/bin/drywall (not in PyPI); crap4py from local sibling
10
+ 2026-06-25 | 58d11592 | integrator | tool-error | rejected→first-occurrence | extract.py null-arc: integrator session confirms pattern (same failure class)
11
+ 2026-06-25 | e4b18370 | curator | tool-error | rejected→first-occurrence | agent-retro: use grep -A50 "## Actions" instead of cat to read retros (full dump = 4-6x larger)
12
+ 2026-06-25 | ba459785 | hardender | convention-gap | promoted→.agents/roles/hardender.md | mutate4py is the mutation tool — use mutmut on this project's own test suite, not itself
13
+ 2026-06-25 | ba459785 | hardender | missing-artifact | promoted→AGENTS.md | crap4py installed from local sibling ~/workspace/addi/crap4py (not PyPI or GitHub URL)
14
+ 2026-06-25 | ba459785 | hardender | missing-artifact | rejected→first-occurrence | gherkin-mutator --help not supported; read source to find --feature flag
15
+ 2026-06-25 | 4c684992 | QA | tool-error | rejected→first-occurrence | extract.py null-arc: QA session confirms pattern (5th role reporting same failure)
16
+ 2026-06-26 | ae4e1d02 | cleaner | convention-gap | promoted→AGENTS.md | uv run mutate4py is correct invocation; uvx breaks self-referential scanning
17
+ 2026-06-26 | 93e42778 | coder | convention-gap | promoted→.agents/roles/coder.md | dead-code guard: delete stale partial impl after extracting a helper, before running tests
18
+ 2026-06-26 | 93e42778 | coder | convention-gap | rejected→first-occurrence | Gherkin label "renaming the function" ambiguous (function vs parameter rename); specifier should clarify
19
+ 2026-06-26 | 86d7f06f | hardender | convention-gap | promoted→.agents/roles/hardender.md | merge_and_process means git merge + hardening sequence, not a script on PATH
20
+ 2026-06-26 | 86d7f06f | hardender | convention-gap | promoted→.agents/roles/hardender.md | mutmut 3.x uses --max-children not --max-workers
21
+ 2026-06-26 | ba459785 | hardender | missing-artifact | promoted→AGENTS.md | gherkin-mutator flags: --feature, --generated-dir required; no --help; defaults to features/a-feature.feature
22
+ 2026-06-26 | 48c13d25 | QA | convention-gap | promoted→AGENTS.md | manifest QA fixtures are committed inputs; all manifest QA steps must use writable-copy pattern
23
+ 2026-06-26 | 14e97446 | specifier | convention-gap | promoted→AGENTS.md | gherkin-parser requires two args: gherkin-parser <feature-file> <json-output>
24
+ 2026-06-26 | d24200ea | architect | convention-gap | promoted→AGENTS.md | _coverage.py must not import _discovery.py; IO-near code must not depend on IO-free domain types
25
+ 2026-06-26 | b2aa029b | cleaner | convention-gap | promoted→AGENTS.md | acceptance step files are boundary files (15-site threshold); pure logic belongs in *_helpers.py modules
26
+ 2026-06-26 | b2aa029b | cleaner | convention-gap | promoted→AGENTS.md | coverage_helpers.py is testable module for acceptance step helper functions; tests in tests/test_coverage_helpers.py
27
+ 2026-06-26 | b2aa029b | cleaner | convention-gap | rejected→first-occurrence | agent-retro step 5: scan site list for per-pattern contributors before starting boundary-file mutation-site reduction
28
+ 2026-06-26 | c53799e5 | architect | tool-error | rejected→first-occurrence | fork agent stalled (600s) when dispatched for open-ended architectural review with large inherited context
29
+ 2026-06-26 | 0fe93f63 | coder | convention-gap | promoted→AGENTS.md | gherkin-parser must be called without rtk prefix; rtk breaks it
30
+ 2026-06-26 | 0fe93f63 | coder | convention-gap | promoted→AGENTS.md | generate_acceptance.py: pass just module_name, not acceptance.steps.module_name
31
+ 2026-06-26 | 0fe93f63 | coder | convention-gap | promoted→AGENTS.md | strip+modify+re-embed pattern: when modifying source with embedded manifest, strip first then re-embed
32
+ 2026-06-26 | bb18021c | architect | convention-gap | rejected→first-occurrence | apply_mutant must stay in _discovery.py alongside Site and line-index helpers; do not re-extract
33
+ 2026-06-26 | f72497fa | cleaner | convention-gap | promoted→AGENTS.md | mutate4py --scan accepts one file at a time; loop over files separately
34
+ 2026-06-26 | da863ce7 | hardender | convention-gap | promoted→.agents/roles/hardender.md | mutmut run takes mutant-name patterns, not file paths; use bare mutmut run to run all
35
+ 2026-06-26 | da863ce7 | hardender | convention-gap | promoted→AGENTS.md | runner_adapter.py must be executable (chmod +x) before gherkin-mutator can use it
36
+ 2026-06-26 | da863ce7 | hardender | convention-gap | promoted→.agents/references/equivalent-mutants.md | five equivalent mutant categories for this project (falsy None, argparse dest, help-text, single-comma DA, single-op compare)
37
+ 2026-06-28 | 976a22ac | hardender | convention-gap | promoted→.agents/roles/hardender.md | mutmut v3 module-path filtering fails (AssertionError); always run `mutmut run --max-children 8` first to populate stats before filtering
38
+ 2026-06-28 | 976a22ac | hardender | convention-gap | promoted→.agents/roles/hardender.md | gherkin-mutator uses --feature <path> (named), not positional; check Clojure source at /tmp/aps-build/bb/... if CLI unclear
39
+ 2026-06-28 | dc019dd9 | cleaner | convention-gap | promoted→.agents/roles/cleaner.md | boundary file 15-site threshold is a trigger not hard gate; document irreducible minimum when all testable logic is extracted
40
+ 2026-06-28 | dc019dd9 | cleaner | convention-gap | promoted→.agents/roles/cleaner.md | when writing test for refactored function, verify error message strings match new implementation — do not copy from old code
41
+ 2026-06-28 | a80e933d | integrator | convention-gap | promoted→.agents/roles/QA.md | QA must run ruff check+format before handoff (recurrence of 9fd9fe97); QA.md created with pre-handoff verification rule
42
+ 2026-06-28 | 4f7feec9 | QA | convention-gap | promoted→.agents/roles/QA.md | before marking QA done, grep run_acceptance.sh for every *_qa.feature and confirm QA_STEPS_MAP entry exists; silent skip masks test failures
43
+ 2026-06-28 | 3d5cea42 | coder | convention-gap | promoted→.agents/roles/coder.md | check for run_acceptance.sh wrapper before invoking acceptance generation scripts directly; scripts require positional args and fail silently
44
+ 2026-06-28 | 3814e69e | cleaner | convention-gap | promoted→.agents/roles/cleaner.md | manifest "NEW" hashes after coder handoff are expected; do not hand-edit — mutation tool refreshes them on first scan
45
+ 2026-06-28 | 8c38deb4 | architect | convention-gap | promoted→AGENTS.md | __main__.py is CLI adapter only; scan_report/scan_report_with_coverage/update_manifest belong in _runner.py and are tested directly
46
+ 2026-06-28 | dc019dd9 | cleaner | convention-gap | promoted→AGENTS.md | cli_surface_helpers.py is testable module for CLI surface step helpers; tests in tests/test_cli_surface_helpers.py
47
+ 2026-06-28 | 7b3678f5 | architect | tool-error | rejected→first-occurrence | agent-retro: $CLAUDE_SKILL_DIR not set in harness; extract.py path resolution requires find fallback
48
+ 2026-06-28 | 3b4f8734 | hardender | convention-gap | promoted→.agents/roles/hardender.md | git checkout <file> after mutmut apply discards all local changes; save with git stash or patch before restoring
49
+ 2026-06-28 | 3b4f8734 | hardender | convention-gap | promoted→.agents/roles/hardender.md | always regenerate acceptance entrypoints after modifying step handlers before running gherkin-mutator
50
+ 2026-06-28 | 3b4f8734 | hardender | convention-gap | promoted→.agents/roles/hardender.md | gherkin-mutator --workers N requires concurrent runner; runner_adapter.py is single-process; always use --workers 1
51
+ 2026-06-28 | 3b4f8734 | hardender | convention-gap | promoted→.agents/references/equivalent-mutants.md | _cmd.run_command capture_output variants and _copy_tree follow_symlinks=None/True are equivalent mutants
52
+ 2026-06-28 | 5707a6e5 | coder | convention-gap | promoted→.agents/roles/coder.md | merge from hardener/cleaner can silently revert API contracts; diff public signatures before running tests
53
+ 2026-06-28 | 19ff3fa9 | QA | convention-gap | promoted→.agents/roles/QA.md | QA harness must handle CLI-rejected values (e.g. --max-workers 0) without changing CLI validator
54
+ 2026-06-28 | 19ff3fa9 | QA | convention-gap | promoted→.agents/roles/QA.md | shell counter files in acceptance steps must use PID not $COUNT; run_parallel cleans run-PID/ not workers/ parent
@@ -0,0 +1,68 @@
1
+ # Ledger — SwarmForge Items
2
+
3
+ Work queue for swarmforge-scoped retro actions, prunable.
4
+ Format: `<date> | <session-id> | <role> | <failure-class> | <verdict> | <status> | <one-line summary>`
5
+
6
+ ---
7
+ 2026-06-25 | 9bc9e159 | architect | tool-error | promoted→ledger-swarmforge | pending | SSH/1Password signing failure: determine if swarm sessions should disable GPG signing by default
8
+ 2026-06-25 | 9bc9e159 | architect | convention-gap | promoted→ledger-swarmforge | pending | Constitution should list canonical role names to eliminate lookup errors
9
+ 2026-06-25 | 00466112 | cleaner | tool-error | promoted→ledger-swarmforge | pending | crap4py external install blocked by auto-mode; needs permission pre-approval or fallback rule
10
+ 2026-06-25 | 00466112 | cleaner | tool-error | promoted→ledger-swarmforge | pending | GPG commit fallback: document -c commit.gpgsign=false workaround for 1Password failures
11
+ 2026-06-25 | 58d11592 | integrator | missing-artifact | promoted→ledger-swarmforge | pending | gtimeout not on macOS; use gh pr checks --watch bare or install coreutils
12
+ 2026-06-25 | e4b18370 | curator | tool-error | promoted→ledger-swarmforge | pending | gh pr create blocked by auto-mode classifier; consider adding to curator allowed commands
13
+ 2026-06-25 | a9efd9cb | coder | convention-gap | promoted→ledger-swarmforge | pending | CLI flag names must be cross-checked against feature files before writing step handlers
14
+ 2026-06-25 | a9efd9cb | coder | convention-gap | promoted→ledger-swarmforge | pending | Write CLI step handlers when feature mixes API+CLI scenarios
15
+ 2026-06-25 | a9efd9cb | coder | convention-gap | promoted→ledger-swarmforge | pending | Regex step patterns capture concrete values not Gherkin placeholder names
16
+ 2026-06-25 | ba459785 | hardender | convention-gap | promoted→ledger-swarmforge | pending | Engineering rules mutation table: exception when project IS the mutation tool
17
+ 2026-06-25 | 4c684992 | QA | tool-error | promoted→ledger-swarmforge | pending | External tool install blocked by sandbox; add fallback-to-local-binary rule to engineering.prompt
18
+ 2026-06-26 | 34b59cea | specifier | convention-gap | promoted→ledger-swarmforge | pending | Specifier phase 3: for faithful-port features, exhaust upstream source before grilling the user
19
+ 2026-06-26 | 34b59cea | specifier | convention-gap | promoted→ledger-swarmforge | pending | Contradiction: grill-with-docs skill is disable-model-invocation:true but role says run it autonomously
20
+ 2026-06-26 | 34b59cea | specifier | missing-artifact | promoted→ledger-swarmforge | pending | ir-dry-checker (specifier phase 6) not installed; reword phase or provide the tool
21
+ 2026-06-26 | 34b59cea | specifier | tool-error | promoted→ledger-swarmforge | pending | git reset --hard blocked by auto-mode classifier in specifier startup; ready_for_next.sh should own sync
22
+ 2026-06-26 | ae4e1d02 | cleaner | convention-gap | promoted→ledger-swarmforge | pending | uv run mutate4py is correct (not uvx); uvx isolates env and breaks self-referential scanning
23
+ 2026-06-26 | 86d7f06f | hardender | convention-gap | promoted→ledger-swarmforge | pending | merge_and_process directive meaning not documented in hardender role; caused 2 extra tool calls
24
+ 2026-06-26 | 86d7f06f | hardender | convention-gap | promoted→ledger-swarmforge | pending | mutmut 3.x uses --max-children, not --max-workers; role prompt used wrong flag name
25
+ 2026-06-26 | 48c13d25 | QA | convention-gap | promoted→ledger-swarmforge | pending | git merge origin/<branch> fails for fetched branches; always use local branch name in merge commands
26
+ 2026-06-26 | f5e87210 | architect | convention-gap | promoted→ledger-swarmforge | pending | Handoff recipient typed from memory instead of conf lookup; already in AGENTS.md but not in architect role checklist
27
+ 2026-06-26 | f5e87210 | architect | convention-gap | promoted→ledger-swarmforge | pending | Before writing fast-check property tests, grep Object.keys(fc) to avoid unknown-arbitrary failures (fc.hexaString, fc.float 32-bit)
28
+ 2026-06-26 | 14e97446 | specifier | missing-artifact | promoted→ledger-swarmforge | pending | ir-dry-checker (phase 6) not installed; manual prune required; not recorded so future specifiers hunt for it again
29
+ 2026-06-26 | c53799e5 | architect | tool-error | promoted→ledger-swarmforge | pending | Fork agent stalled (600s watchdog) for architectural review; large swarm-persona context may cause fork hang on open-ended tasks
30
+ 2026-06-26 | 416dbe9a | cleaner | convention-gap | promoted→ledger-swarmforge | pending | When CRAP/DRY tools recorded as unavailable in memory/AGENTS.md, engineering startup should allow skipping with one-line note
31
+ 2026-06-26 | 416dbe9a | cleaner | convention-gap | promoted→ledger-swarmforge | pending | --update-manifest not yet implemented; cleaner should note manifest will be stale after src edits until a full run
32
+ 2026-06-26 | 9fd9fe97 | integrator | convention-gap | promoted→ledger-swarmforge | pending | QA role: before handing off, run ruff check --fix && ruff format and commit if any changes; prevents integrator fix cycles
33
+ 2026-06-26 | 9fd9fe97 | integrator | convention-gap | promoted→ledger-swarmforge | pending | Integrator: after gh pr merge, if error contains "cannot delete branch" (worktree conflict), treat as success and continue
34
+ 2026-06-26 | 9fd9fe97 | integrator | convention-gap | promoted→ledger-swarmforge | pending | Verify both ruff check and ruff format in local verification; both are separate CI steps
35
+ 2026-06-26 | eeab6b91 | QA | convention-gap | promoted→ledger-swarmforge | pending | QA verification: generate coverage LCOV before running crap4py (two-step: uv run coverage run then uv run coverage lcov)
36
+ 2026-06-26 | a6cab6bf | coder | convention-gap | promoted→ledger-swarmforge | pending | Scope find to src/ or specific subtree, never project root; venv noise bloats results by 50-100x
37
+ 2026-06-26 | 38ff0a59 | hardender | convention-gap | promoted→ledger-swarmforge | pending | After commit exit-code 128 with signing error, run git log to check if commit succeeded before retrying
38
+ 2026-06-26 | 4d4d0ea3 | integrator | convention-gap | promoted→ledger-swarmforge | pending | gh pr view without PR number resolves to current branch (swarmforge-integrator), not the feature branch; always pass explicit PR number
39
+ 2026-06-26 | 4d4d0ea3 | integrator | convention-gap | promoted→ledger-swarmforge | pending | gh pr comment may be blocked in auto-mode; include diagnosis inline in PR body/description as first-choice fallback
40
+ 2026-06-26 | 61ee6b27 | integrator | convention-gap | promoted→ledger-swarmforge | pending | Integrator: run ruff check && ruff format locally before pushing to confirm all issues resolved in single commit
41
+ 2026-06-26 | b0229ad6 | QA | missing-artifact | promoted→ledger-swarmforge | pending | QA DRY check: drywall binary download blocked by auto-mode; note SKIPPED if blocked and continue (binary may already exist at ~/.local/bin/drywall)
42
+ 2026-06-26 | d638c7e4 | QA | convention-gap | promoted→ledger-swarmforge | pending | Stale untracked test artifacts from prior QA sessions may exist in worktree root; prefer git stash -u over rm in auto-mode
43
+ 2026-06-26 | f585b9ac | architect | convention-gap | promoted→ledger-swarmforge | pending | Fork review prompts for src/ architectural review should include test/ property test files to catch type errors in test consumers
44
+ 2026-06-26 | 4d4d0ea3 | integrator | convention-gap | promoted→ledger-swarmforge | pending | After gh pr create fails with "already exists", capture PR URL from error output and continue with post-create gate
45
+ 2026-06-26 | 04c94859 | hardender | convention-gap | promoted→ledger-swarmforge | pending | Hardender: before first mutation run on a file, verify embedManifest format produces valid TS (/* */ wrapped JSON, not raw JSON)
46
+ 2026-06-26 | 04c94859 | hardender | convention-gap | promoted→ledger-swarmforge | pending | For TS/Bun mutation: use scoped test command per file (bun test test/X.test.ts) not full bun test — 6-8x speedup
47
+ 2026-06-26 | 52201f30 | coder | convention-gap | promoted→ledger-swarmforge | pending | Integrator handoff payload should signal "verify and forward" vs "implement" to disambiguate passthrough sessions
48
+ 2026-06-26 | fc5d7a74 | cleaner | convention-gap | promoted→ledger-swarmforge | pending | When adding type aliases, place them after all import statements, never between import blocks
49
+ 2026-06-26 | 0fe93f63 | coder | convention-gap | promoted→ledger-swarmforge | pending | Coder: before delegating implementation to a fork, run existing unit tests to confirm green baseline; prevents misattributing pre-existing failures
50
+ 2026-06-26 | b79e3962 | coder | convention-gap | promoted→ledger-swarmforge | pending | When spec text and spec examples contradict, trust examples first; validate algorithm against examples before overriding a fork's working implementation
51
+ 2026-06-26 | fc327d2f | QA | missing-artifact | promoted→ledger-swarmforge | pending | merge_and_process in PAYLOAD is not a script on PATH for non-hardender roles; all roles must infer: fetch+merge the named commit then run role-specific sequence
52
+ 2026-06-26 | 38acb0d3 | specifier | convention-gap | promoted→ledger-swarmforge | pending | Completion-cycle git_handoffs reuse fresh-spec payload template, giving no explicit "cycle done" signal; consider a distinct completion-notification type in handoff spec
53
+ 2026-06-28 | 8c38deb4 | architect | convention-gap | promoted→ledger-swarmforge | pending | Before moving domain functions out of a module, grep tests for direct imports of those function names; prevents post-hoc test-contract repair
54
+ 2026-06-28 | 8c38deb4 | architect | convention-gap | promoted→ledger-swarmforge | pending | Read existing test signatures for the old function before designing new API — don't discover test contract after implementing
55
+ 2026-06-28 | 8c38deb4 | architect | convention-gap | promoted→ledger-swarmforge | pending | Extend dependency-rule review phase to include test-import check for functions being moved before touching source file
56
+ 2026-06-28 | c6b84c63 | architect | convention-gap | promoted→ledger-swarmforge | pending | Think before Edit: if unsure whether a change is correct, articulate why before calling Edit — edit→revert pairs waste turns
57
+ 2026-06-28 | 4f7feec9 | QA | tool-error | promoted→ledger-swarmforge | pending | tool_result_sizes in extract.py output is a dict (keyed by tool name), not a list; retro SKILL.md Step 5 uses sizes[:5] list slice syntax — schema mismatch causes KeyError
58
+ 2026-06-28 | 5c32a862 | specifier | convention-gap | promoted→ledger-swarmforge | pending | When request names a flag/behavior the spec marks removed/locked, frontier brief must flag it as a reopenable assumption and ask; do not plan around spec stance as settled
59
+ 2026-06-28 | 5c32a862 | specifier | convention-gap | promoted→ledger-swarmforge | pending | When a decision reverses, grep for every assertion of the reversed fact across the whole contract (not just the named section) before claiming done
60
+ 2026-06-28 | b52f13f5 | specifier | convention-gap | promoted→ledger-swarmforge | pending | Default to terse Q→one-line-A when user signals non-expertise or confusion; offer depth on demand; lead dense explanations only when expertise is established
61
+ 2026-06-28 | b52f13f5 | specifier | convention-gap | promoted→ledger-swarmforge | pending | AskUserQuestion should follow shared mental model; if user answers options with new prerequisite questions, drop to prose and re-ask once rather than re-prompting same decision
62
+ 2026-06-28 | 3814e69e | cleaner | missing-artifact | promoted→ledger-swarmforge | pending | drywall binary download blocked in auto-mode again (cleaner); pre-install drywall in worktree setup or grant permission in settings.json (duplicate pattern, escalate)
63
+ 2026-06-28 | c8748468 | hardender | tool-error | promoted→ledger-swarmforge | pending | RTK swallows stdout when underlying process calls process.exit(1) before writing; use bare command without rtk when zero output is unexpected
64
+ 2026-06-28 | c8748468 | hardender | convention-gap | promoted→ledger-swarmforge | pending | Before writing handoff to: field, verify role name case with ls swarmforge/roles/ — names are case-sensitive (QA not qa)
65
+ 2026-06-28 | c8748468 | hardender | convention-gap | promoted→ledger-swarmforge | pending | Do not bun add -d <local-path> tools to package.json for analysis — install ephemerally, run tool, then revert package.json and bun.lock with git checkout --
66
+ 2026-06-28 | 5707a6e5 | coder | convention-gap | promoted→ledger-swarmforge | pending | After merge-result handoff, diff public function signatures of touched modules against pre-merge state before running tests
67
+ 2026-06-29 | eaa9acfe | integrator | convention-gap | promoted→ledger-swarmforge | pending | Integrator: explicit git push -u origin feat/<initiative> step must precede gh pr create; push is not implicit
68
+ 2026-06-29 | eaa9acfe | integrator | convention-gap | promoted→ledger-swarmforge | pending | Before pushing to CI, run both ruff check --fix AND ruff format in a single pass (they are separate CI steps)
@@ -0,0 +1,21 @@
1
+ # Equivalent Mutant Categories — mutate4py Project
2
+
3
+ Recognized equivalent mutant patterns for this project. Surviving mutants in these categories do NOT need new tests — they are structurally equivalent for all valid inputs.
4
+
5
+ ## Categories (from hardender session da863ce7, 2026-06-26)
6
+
7
+ 1. **Falsy None vs False init** — replacing `None` with `False` (or vice versa) in initialization where the code only tests truthiness; both evaluate identically.
8
+
9
+ 2. **argparse `dest=None`** — `dest` in argparse derives from the flag name; `dest=None` vs `dest="<flag>"` produces the same attribute name at runtime.
10
+
11
+ 3. **Help-text mutations** — mutations inside `help="..."` strings for argparse arguments; help text has no behavioral effect.
12
+
13
+ 4. **Single-comma DA lines with different `maxsplit`** — `_parse_da_line` mutations on lines that have exactly one comma; split with `maxsplit=1` or without produces the same result.
14
+
15
+ 5. **Compare between-text with single operator occurrence** — `_mutate_compare` mutations where the between-text region contains exactly one operator; replace-first and replace-all are equivalent.
16
+
17
+ ## Additional Categories (from hardender session 3b4f8734, 2026-06-28)
18
+
19
+ 6. **`_cmd.run_command` `capture_output` variants** — mutants 5, 10, 13 in `_cmd.py`; `capture_output=True/False` variants produce identical behavior for the project's test inputs.
20
+
21
+ 7. **`_copy_tree` `follow_symlinks=None/True`** — mutants 13, 14; the only distinction is for symlinks-to-directories, which crash with `IsADirectoryError` on both variants in the current call sites.
@@ -0,0 +1,16 @@
1
+ # QA Role — Operational Knowledge
2
+
3
+ ## Pre-Handoff Lint and Format Check
4
+ Before handing off, MUST run `uv run ruff check src/ tests/ && uv run ruff format --check src/ tests/`. Fix any failures before handoff. Do not hand off with lint or format violations — integrator absorbs CI fix cycles.
5
+
6
+ ## QA Feature Step Wiring
7
+ Before marking QA done, grep `acceptance/run_acceptance.sh` for every `*_qa.feature` file present in `features/`. Confirm each has a `QA_STEPS_MAP` entry. A missing `QA_STEPS_MAP` entry causes silent `SKIP QA: no steps module for X` output — the feature is silently skipped and failures are masked.
8
+
9
+ ## QA Harness: Handling CLI-Rejected Values (e.g. --max-workers 0)
10
+ When a QA feature passes a value that the CLI rejects (e.g., `--max-workers 0` to test serial mode), handle it in `_run_qa_cmd` — not by changing the CLI validator. Changing the CLI validator to accept test-only values breaks the cli-surface acceptance test.
11
+
12
+ ## Shell Counter Files in Acceptance Steps
13
+ Shell scripts in acceptance steps must not use `$COUNT` from `ls dir | wc -l` as unique file names with parallel workers — it is not safe under concurrency. Use `$$` (PID) or content-based detection (grep for a token in the worker's source copy) instead.
14
+
15
+ ## Worker Directory Cleanup Assertions
16
+ `run_parallel` cleans up `run-PID-NANOS/` (the run-specific subdirectory) but leaves the `workers/` parent directory. Assertions must check for empty run subdirs, not for the absence of `workers/`.
@@ -0,0 +1,10 @@
1
+ # Cleaner Role — Operational Knowledge
2
+
3
+ ## Boundary File Irreducible Minimum
4
+ The 15-mutation-site threshold is a trigger, not a hard gate. When all extractable testable logic is in `*_helpers.py` and remaining sites are Context class methods, subprocess calls, and guard clauses, document as "irreducible boundary minimum" and proceed. Do not loop indefinitely trying to reach 15.
5
+
6
+ ## Test Error Messages Must Match New Implementation
7
+ When writing a test for a refactored function, verify expected error message strings match the new implementation before committing. Do not copy message strings from old code — refactored functions may use different error strings.
8
+
9
+ ## Manifest "NEW" Hashes After Coder Handoff
10
+ When manifest entries show "NEW" hashes and stale line numbers after a coder handoff, this is expected — the mutation tool refreshes them on first scan. Do not hand-edit manifest entries; skip to cleanup work.
@@ -0,0 +1,10 @@
1
+ # Coder Role — Operational Knowledge
2
+
3
+ ## Dead-Code Guard After Refactor
4
+ After extracting a helper function from a function body, immediately delete all stale local variables, intermediate loops, and partial implementations before running tests. Do not rely on test failures (NameError, etc.) to surface dead code — it should be removed proactively as part of the refactor step.
5
+
6
+ ## Acceptance Convenience Wrapper
7
+ Before invoking acceptance generation steps manually (`generate_acceptance.py`, `runner_adapter.py`), check for `acceptance/run_acceptance.sh` first — it is the correct entry point and handles sequencing. Calling generation scripts directly without required args fails silently or with cryptic errors.
8
+
9
+ ## Merge Handoff: Verify Public API Signatures
10
+ After receiving a merge-result handoff (hardener or cleaner branch merged onto a feature branch), diff the public function signatures of all touched modules against their pre-merge state before running tests. A merge can silently revert API contract changes (e.g., function signature, return type); in a dynamically-typed project this manifests as a runtime TypeError, not a compile error.
@@ -0,0 +1,32 @@
1
+ # Hardender Role — Operational Knowledge
2
+
3
+ ## Mutation Tool for This Project
4
+ This project (mutate4py) is self-hosted — it generates and checks its own mutation manifests. Use `uv run mutate4py` (not `uvx mutate4py`; uvx isolates the env and breaks self-referential scanning).
5
+
6
+ Key commands:
7
+ - `uv run mutate4py src/ --check-manifest` — verify all manifests are current (CI gate; exits 0 if current, 1 if missing/stale)
8
+ - `uv run mutate4py <file> --scan` — scan a single file and print surviving mutants
9
+ - `uv run mutate4py <file> --update-manifest` — regenerate and embed a file's manifest
10
+
11
+ `--scan`, `--update-manifest`, and `--check-manifest` are mutually exclusive. `--scan` and `--update-manifest` accept exactly ONE file; for multi-file operations loop over files or use a directory with `--check-manifest`.
12
+
13
+ ## CRAP Tool
14
+ crap4py is installed from local sibling `~/workspace/addi/crap4py` via `uv tool install ~/workspace/addi/crap4py`, not from PyPI or GitHub URL.
15
+
16
+ ## merge_and_process Directive
17
+ `merge_and_process <role> <commit>` in a handoff payload is NOT a script on PATH. It means: run `git merge <commit>` in the hardender worktree, then execute the standard hardening sequence (unit → acceptance → property tests → mutation manifest check → Gherkin mutation → CRAP → DRY).
18
+
19
+ ## gherkin-mutator Named Arguments
20
+ gherkin-mutator uses `--feature <path>` (named option), not a positional argument. Check `/tmp/aps-build/bb/src/aps/cli/gherkin_mutator.clj` source if CLI is unclear.
21
+
22
+ ## Restoring Files After Manual Mutation Debugging
23
+ After manually editing a source file to simulate a mutant for debugging, restore with `git checkout <file>` ONLY if no other local changes exist in that file. If you have local edits (e.g. a DRY fix, refactor), first save them: `git stash` (or `git diff > patch.diff && git checkout <file> && git apply patch.diff`). `git checkout <file>` discards ALL unstaged and staged changes, not just the mutation.
24
+
25
+ ## Regenerate Acceptance Entrypoints After Step Handler Changes
26
+ After modifying any acceptance step handler file (`*_steps.py`), regenerate the acceptance entrypoints via `gherkin-parser` + `generate_acceptance.py` BEFORE running `gherkin-mutator`. Stale generated entrypoints cause all 19+ mutations to error.
27
+
28
+ ## gherkin-mutator --workers
29
+ `runner_adapter.py` is concurrent (ThreadPoolExecutor, default 4 workers via `RUNNER_WORKERS` env var). Use `--workers 4` with gherkin-mutator. For all features in parallel, use `acceptance/run_gherkin_mutation.sh`.
30
+
31
+ ## Equivalent Mutant Categories (Python)
32
+ See `.agents/references/equivalent-mutants.md` for recognized equivalent mutant patterns that do not need test coverage.
@@ -0,0 +1,219 @@
1
+ ---
2
+ name: agent-retro
3
+ description: Run a conversation retrospective — analyze what happened in this session, what worked, what didn't, and propose concrete improvements. Use when the user says "retro", "retrospective", "what happened in this session", "session review", "what did we do", "analyze this conversation", or when wrapping up a long session. Especially useful after using a skill you're developing. In swarmforge: invoked automatically as the last step before each role goes idle.
4
+ compatibility: Primary — requires `entire` CLI (0.6.2+) for transcript extraction. Fallback — Claude Code ~/.claude/projects/ path. Python 3.8+ for the extraction script.
5
+ metadata:
6
+ author: gabadi/swarm-forge (fork of giannimassi/agent-retro)
7
+ version: "0.1.0"
8
+ ---
9
+
10
+ # agent-retro
11
+
12
+ ## Step 1 — Extract Session Data
13
+
14
+ **Primary path (entire):**
15
+ The extractor script lives next to this SKILL.md at `scripts/extract.py`. Resolve its directory portably (Claude Code sets `$CLAUDE_SKILL_DIR`; pi does not):
16
+ ```bash
17
+ EXTRACT="${CLAUDE_SKILL_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)/..}/scripts/extract.py"; [ -f "$EXTRACT" ] || EXTRACT="scripts/extract.py"
18
+ ```
19
+ If neither resolves, ask the operator for the path to this skill's `scripts/extract.py`.
20
+
21
+ 1. Run `entire session current --json` to get the active session ID and worktree path.
22
+ 2. Check: does `worktree_path` in the result match `$PWD`?
23
+ - If **NO** (stale result — wrong repo or ended session) → skip `entire session info` entirely; go to **JSONL fallback** below.
24
+ - If **YES** → proceed:
25
+ - Run `entire session info <id> --transcript > /tmp/retro-session.jsonl`
26
+ - Verify: `python3 "$EXTRACT" /tmp/retro-session.jsonl --metadata-only`
27
+ - If verification succeeds, run full extraction: `python3 "$EXTRACT" /tmp/retro-session.jsonl --summary > /tmp/retro-extract.json`
28
+ - Proceed to Step 2 with `/tmp/retro-extract.json`.
29
+
30
+ **JSONL fallback:**
31
+ Use when: `entire` is not installed, `entire session current` returns no session, or `worktree_path` does not match `$PWD`. The fallback depends on the harness — `extract.py` auto-detects the format from the first line (`{"type":"session"` → pi; otherwise Claude Code).
32
+
33
+ **Claude Code fallback:**
34
+ 1. Find the Claude Code project dir for this worktree: `ls ~/.claude/projects/ | grep <last-segment-of-PWD>`. Note: dot-prefixed segments encode as double-dash (`.worktrees` → `--worktrees`), so do not use naive `sed` — use `grep` on the last path segment instead.
35
+ 2. Take the most recently modified `.jsonl` in that dir: `ls -t ~/.claude/projects/<encoded-cwd>/*.jsonl | head -1`.
36
+
37
+ **pi fallback:**
38
+ pi stores sessions under `~/.pi/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl`. The encoding wraps the cwd with `--` and replaces every `/`, `\`, and `:` with `-` (so `/Users/gabadi/.agents-skills` → `--Users-gabadi-.agents-skills--`). Dot-prefixed segments are **single**-dashed (`.worktrees/coder` → `-worktrees-coder`), unlike Claude's double-dash — do not reuse the Claude encoding.
39
+ 1. Encode `$PWD` the same way and locate the dir:
40
+ ```bash
41
+ ENCODED="--$(echo "$PWD" | sed 's|^[/\\]||; s|[/\\:]|-|g')--"
42
+ ls -t ~/.pi/agent/sessions/"$ENCODED"/*.jsonl | head -1
43
+ ```
44
+ If the encoded lookup misses, fall back to `ls ~/.pi/agent/sessions/ | grep "$(basename "$PWD")"` to find the right dir.
45
+ 2. The most recently modified `.jsonl` in that dir is the current/last session.
46
+
47
+ **Then (both harnesses):**
48
+ 3. Verify: `python3 "$EXTRACT" <path> --metadata-only`
49
+ 4. Run full extraction: `python3 "$EXTRACT" <path> --summary > /tmp/retro-extract.json`
50
+
51
+ The pi parser produces the same schema as the Claude parser (`conversation_arc`, `tokens.total`, `tokens.estimated_cost_usd`, `tool_result_sizes`, `tools`). `tokens.total` uses the same key names (`input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens`) mapped from pi's `usage.{input,output,cacheWrite,cacheRead}`. Cost comes from pi's own `usage.cost.total` when present.
52
+
53
+ **If no transcript is found:** Report "No session transcript found" and stop. Do not fabricate data.
54
+
55
+ Raw JSONL is 1MB+ per session — never stream transcript bytes inline into context. Always write to a temp file and pass the path to extract.py.
56
+
57
+ **Null-arc guard:** Before using the arc, check whether content is populated:
58
+ ```bash
59
+ python3 -c "
60
+ import json
61
+ d = json.load(open('/tmp/retro-extract.json'))
62
+ arc = d.get('conversation_arc', [])
63
+ non_null = sum(1 for e in arc if e.get('text') or e.get('content'))
64
+ print(f'arc entries: {len(arc)}, non-null content: {non_null}')
65
+ "
66
+ ```
67
+ (Both the Claude and pi parsers populate `text`; the guard checks `text` or `content` for compatibility.)
68
+ If `non_null == 0` and `len(arc) > 0`, `extract.py` silently failed. Fall back to **in-context reconstruction**: write the retro from live session memory — (1) what tool calls succeeded first try, (2) what failed or needed retries, (3) any user corrections or redirects, (4) token budget marked as `(unavailable — extract.py returned no cost data)`. Do not fabricate metrics.
69
+
70
+ ---
71
+
72
+ ## Step 2 — Read the Conversation Arc
73
+
74
+ Read `conversation_arc` from `/tmp/retro-extract.json`. This is the full story of the session: every user message and assistant response in order.
75
+
76
+ Identify:
77
+ - User corrections ("no, not that", "stop", "undo", "wrong")
78
+ - Redirects (user changing direction mid-task)
79
+ - Repeated instructions (same request given more than once)
80
+ - Pivots (abandoned approaches)
81
+ - Friction moments (back-and-forth on a single point)
82
+
83
+ ---
84
+
85
+ ## Step 3 — Classify Outcomes
86
+
87
+ Classify what the session produced:
88
+ - New code / feature
89
+ - Bug fix
90
+ - Communication (messages, comments, docs)
91
+ - Setup / configuration changes
92
+ - Spec or design artifact
93
+ - Process improvement
94
+ - Review or analysis
95
+ - Research
96
+ - Skill development
97
+
98
+ A session may have multiple outcomes.
99
+
100
+ ---
101
+
102
+ ## Step 4 — Analyze What Worked
103
+
104
+ Identify:
105
+ - First-try successes (task completed without corrections)
106
+ - Efficient delegation (agents dispatched with clear scope)
107
+ - Good skill matches (right skill for the task)
108
+ - Clean conversation flow (no redirects)
109
+ - Smart tool choice (right tool, right scope)
110
+
111
+ ---
112
+
113
+ ## Step 5 — Analyze What Didn't Work
114
+
115
+ Identify friction patterns:
116
+ - User corrections, redirects, repetitions, stops, frustration signals
117
+ - Wasted agent dispatches (dispatched but result unused)
118
+ - Oversized tool results (large reads never referenced)
119
+ - Tool call retries (same tool called multiple times for the same target)
120
+ - Abandoned approaches (started, then discarded)
121
+ - Over-engineering (more than the task required)
122
+ - Under-specification (task started with insufficient context)
123
+
124
+ For skill-development retros: read the active SKILL.md (the `${CLAUDE_SKILL_DIR}/SKILL.md` of the skill being developed, or this skill's own `SKILL.md` resolved as above) and identify which instruction caused each friction.
125
+
126
+ Read `tool_result_sizes` from the extract — flag any tool result over 50KB that was followed by no further reference to that file.
127
+
128
+ ---
129
+
130
+ ## Step 6 — Propose Actions
131
+
132
+ Lead with the defense-first question: **"What defensive rule did this session's work absorb that future maintainers must keep intact?"** Answer it before cataloging friction — rule-shaped learnings surface before cause-shaped ones.
133
+
134
+ Capture-first guard: enumerate every candidate learning from Steps 4–5 in full before writing anything to the retro file. Do not filter for "obviousness" or "self-correcting" here — capture everything; the curation stage downstream owns discards.
135
+
136
+ For each friction pattern, propose one of these action types:
137
+ - `skill-update` — change an existing skill. Include before/after text.
138
+ - `skill-create` — create a new skill.
139
+ - `rule-update` — change a rule or instruction in CLAUDE.md or a role prompt.
140
+ - `rule-create` — create a new rule.
141
+ - `setup-change` — change a configuration or environment setting.
142
+ - `memory-update` — update or create a memory entry.
143
+ - `investigate` — flag something for human review (uncertain root cause).
144
+ - `acknowledge` — nothing to change; note what worked well.
145
+
146
+ Be specific. "Improve X" is not a proposal. "Change the wording in Step 3 from Y to Z" is a proposal.
147
+
148
+ **Scope** — tag every proposed action with exactly one scope value:
149
+ - `project` — knowledge about the target project (its code, config, tools, conventions).
150
+ - `swarmforge` — knowledge about the harness itself (role prompts, constitution, scripts, pipeline mechanics).
151
+ - `skill` — a reusable procedure that should become or amend a skill.
152
+ - `ephemeral` — true one-offs; recorded for audit, never promoted.
153
+
154
+ ---
155
+
156
+ ## Step 7 — Write the Retro File
157
+
158
+ Write to `~/.claude/worklog/retros/YYYY-MM-DD-<slug>.md` where `<slug>` is a 3–5 word kebab-case summary of the session.
159
+
160
+ Structure:
161
+ ```markdown
162
+ # Session Retro: <slug>
163
+ Date: YYYY-MM-DD
164
+ Session ID: <id>
165
+ Role: <swarmforge role name, or "interactive" outside a swarm>
166
+ Branch: <branch>
167
+ Duration: <N>m
168
+ Cost: $<N>
169
+
170
+ ## Token Budget
171
+ | Category | Tokens | Cost |
172
+ |---|---|---|
173
+ | Input | N | $N |
174
+ | Output | N | $N |
175
+ | Cache create | N | $N |
176
+ | Cache read | N | $N |
177
+ | **Total** | **N** | **$N** |
178
+
179
+ ## Tool Result Waste
180
+ <table of oversized unused tool results, or "None detected">
181
+
182
+ ## What Worked
183
+ <bullet list>
184
+
185
+ ## What Didn't Work
186
+ <bullet list with root cause per item>
187
+
188
+ ## Actions
189
+ | # | Type | Scope | Description | Target |
190
+ |---|------|-------|-------------|--------|
191
+ | 1 | skill-update | project | ... | ... |
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Step 8 — Walk Through Actions
197
+
198
+ Determine the mode:
199
+
200
+ **Interactive session (a human is present):**
201
+ - Present the retro file path and summary counts (N worked, N didn't work, N actions).
202
+ - Walk through each proposed action one by one: show type, scope, description, target. Ask: "Apply? [y/n/defer]". Apply approved actions immediately; mark deferred/skipped in the table.
203
+ - After the walkthrough, show the final action table with statuses.
204
+
205
+ **Autonomous session (swarmforge role, no human in the loop):**
206
+ - Do not ask anything. Do not apply any action.
207
+ - Mark every action's status as `pending-curation` in the table and finish the retro file.
208
+ - The curator role consumes the file downstream; your only job is complete, well-tagged capture.
209
+
210
+ ---
211
+
212
+ ## Step 9 — Preemptive Handoff Recommendation
213
+
214
+ Check `session` metadata from the extract:
215
+ - If `turn_count` > 500, `duration_seconds` > 14400 (4h), or `estimated_cost_usd` > 300:
216
+ - Add a `investigate` action: "Session size threshold reached — consider handoff"
217
+ - Include two ready-to-paste prompts:
218
+ - For `/compact`: "Continue from: <brief state summary>"
219
+ - For `/clear`: "Resume from: <brief state summary> — key context: <3 bullet points>"