@kenkaiiii/ggcoder 5.69.0 → 5.71.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 (226) hide show
  1. package/assets/motion/bin/contact-sheet.mjs +9 -3
  2. package/assets/motion/bin/cues.mjs +337 -0
  3. package/assets/motion/bin/library.mjs +53 -10
  4. package/assets/motion/bin/motion-blur.mjs +943 -0
  5. package/assets/motion/bin/motion-check.mjs +354 -3
  6. package/assets/motion/bin/music-fit.mjs +436 -0
  7. package/assets/motion/bin/pdf-extract.mjs +22 -10
  8. package/assets/motion/bin/reference-study.mjs +346 -0
  9. package/assets/motion/bin/score-synth.mjs +1052 -93
  10. package/assets/motion/library/README.md +50 -14
  11. package/assets/motion/library/kit/moves.js +1981 -0
  12. package/assets/motion/library/library.json +232 -0
  13. package/assets/motion/library/pieces/camera-rig/meta.json +13 -0
  14. package/assets/motion/library/pieces/camera-rig/piece.html +153 -0
  15. package/assets/motion/library/pieces/camera-rig/preview.jpg +0 -0
  16. package/assets/motion/library/pieces/chain-knock/meta.json +13 -0
  17. package/assets/motion/library/pieces/chain-knock/piece.html +195 -0
  18. package/assets/motion/library/pieces/chain-knock/preview.jpg +0 -0
  19. package/assets/motion/library/pieces/gather-to-logo/meta.json +13 -0
  20. package/assets/motion/library/pieces/gather-to-logo/piece.html +159 -0
  21. package/assets/motion/library/pieces/gather-to-logo/preview.jpg +0 -0
  22. package/assets/motion/library/pieces/morph-carry/meta.json +13 -0
  23. package/assets/motion/library/pieces/morph-carry/piece.html +173 -0
  24. package/assets/motion/library/pieces/morph-carry/preview.jpg +0 -0
  25. package/assets/motion/library/pieces/one-shape-journey/meta.json +13 -0
  26. package/assets/motion/library/pieces/one-shape-journey/piece.html +195 -0
  27. package/assets/motion/library/pieces/one-shape-journey/preview.jpg +0 -0
  28. package/assets/motion/library/pieces/open-from-subject/meta.json +13 -0
  29. package/assets/motion/library/pieces/open-from-subject/piece.html +168 -0
  30. package/assets/motion/library/pieces/open-from-subject/preview.jpg +0 -0
  31. package/assets/motion/library/pieces/request-to-result/meta.json +13 -0
  32. package/assets/motion/library/pieces/request-to-result/piece.html +212 -0
  33. package/assets/motion/library/pieces/request-to-result/preview.jpg +0 -0
  34. package/assets/motion/library/pieces/scale-dive/meta.json +13 -0
  35. package/assets/motion/library/pieces/scale-dive/piece.html +321 -0
  36. package/assets/motion/library/pieces/scale-dive/preview.jpg +0 -0
  37. package/assets/motion/library/pieces/screen-replica-steps/meta.json +13 -0
  38. package/assets/motion/library/pieces/screen-replica-steps/piece.html +366 -0
  39. package/assets/motion/library/pieces/screen-replica-steps/preview.jpg +0 -0
  40. package/assets/motion/library/pieces/zoom-into-card/meta.json +13 -0
  41. package/assets/motion/library/pieces/zoom-into-card/piece.html +179 -0
  42. package/assets/motion/library/pieces/zoom-into-card/preview.jpg +0 -0
  43. package/assets/motion/library/sheets/diagram.jpg +0 -0
  44. package/assets/motion/library/sheets/frame.jpg +0 -0
  45. package/assets/motion/library/sheets/transition.jpg +0 -0
  46. package/assets/motion/library/sheets/ui.jpg +0 -0
  47. package/assets/motion/references/build-sheet.md +206 -0
  48. package/assets/motion/references/runtime/determinism-rules.md +1 -1
  49. package/assets/motion/references/runtime/gsap-easing-and-stagger.md +29 -29
  50. package/assets/motion/references/runtime/inputs-and-assets.md +7 -12
  51. package/assets/motion/references/runtime/lint-validate-inspect.md +3 -3
  52. package/assets/motion/references/runtime/minimal-composition.md +1 -1
  53. package/assets/motion/references/runtime/preview-render.md +3 -3
  54. package/assets/motion/skills/app-walkthrough/SKILL.md +66 -0
  55. package/assets/motion/skills/before-after/SKILL.md +53 -0
  56. package/assets/motion/skills/brand-kit/SKILL.md +3 -3
  57. package/assets/motion/skills/dev-tool-video/SKILL.md +57 -0
  58. package/assets/motion/skills/launch-video/SKILL.md +62 -0
  59. package/assets/motion/skills/match-reference/SKILL.md +58 -0
  60. package/assets/motion/skills/motion/SKILL.md +78 -85
  61. package/assets/motion/skills/source-ingest/SKILL.md +17 -6
  62. package/assets/motion/skills/website-video/SKILL.md +59 -0
  63. package/assets/skills/bulletproof/SKILL.md +36 -11
  64. package/assets/skills/bulletproof/references/agent-surface.md +19 -9
  65. package/assets/skills/bulletproof/references/audit-protocol.md +20 -5
  66. package/assets/skills/bulletproof/references/platform-playbooks.md +5 -4
  67. package/assets/skills/bulletproof/references/provenance.md +26 -1
  68. package/assets/skills/bulletproof/references/secure-defaults.md +6 -5
  69. package/assets/skills/bulletproof/references/supply-chain.md +21 -17
  70. package/assets/skills/bulletproof/references/threat-landscape.md +28 -26
  71. package/assets/skills/bulletproof/references/verification.md +2 -0
  72. package/assets/skills/clarify/SKILL.md +25 -16
  73. package/assets/skills/code-review/SKILL.md +71 -13
  74. package/assets/skills/code-review/references/agent-diffs.md +27 -0
  75. package/assets/skills/code-review/references/tests.md +19 -0
  76. package/assets/skills/compliance-guard/SKILL.md +20 -5
  77. package/assets/skills/compliance-guard/references/artifacts.md +1 -1
  78. package/assets/skills/compliance-guard/references/eu-uk.md +16 -16
  79. package/assets/skills/compliance-guard/references/lawsuit-vectors.md +5 -5
  80. package/assets/skills/compliance-guard/references/provenance.md +41 -2
  81. package/assets/skills/compliance-guard/references/sector-gates.md +3 -3
  82. package/assets/skills/compliance-guard/references/security-baseline.md +2 -2
  83. package/assets/skills/compliance-guard/references/trigger-map.md +5 -5
  84. package/assets/skills/compliance-guard/references/us.md +27 -21
  85. package/assets/skills/durable/SKILL.md +87 -79
  86. package/assets/skills/durable/references/agent-db-safety.md +69 -0
  87. package/assets/skills/durable/references/backups-and-runtime.md +19 -12
  88. package/assets/skills/durable/references/migrations-and-schema.md +13 -6
  89. package/assets/skills/evidence-led-ui/SKILL.md +69 -127
  90. package/assets/skills/evidence-led-ui/references/anti-defaults.md +107 -208
  91. package/assets/skills/evidence-led-ui/references/direction.md +124 -0
  92. package/assets/skills/evidence-led-ui/references/production-contract.md +8 -0
  93. package/assets/skills/evidence-led-ui/references/provenance.md +24 -1
  94. package/assets/skills/lean/SKILL.md +90 -71
  95. package/assets/skills/lean/references/memory-and-processes.md +3 -2
  96. package/assets/skills/lean/references/playbooks.md +37 -12
  97. package/assets/skills/refactoring/SKILL.md +24 -3
  98. package/assets/skills/refactoring/references/agent-pitfalls.md +4 -1
  99. package/assets/skills/refactoring/references/legacy.md +21 -0
  100. package/assets/skills/root-cause/SKILL.md +20 -10
  101. package/assets/skills/shared-language/SKILL.md +16 -14
  102. package/assets/skills/tdd/SKILL.md +27 -15
  103. package/dist/app-sidecar.js +56 -33
  104. package/dist/app-sidecar.js.map +1 -1
  105. package/dist/cli.js +2 -11
  106. package/dist/cli.js.map +1 -1
  107. package/dist/core/acceptance-checks.d.ts +48 -0
  108. package/dist/core/acceptance-checks.js +144 -0
  109. package/dist/core/acceptance-checks.js.map +1 -0
  110. package/dist/core/agent-session.d.ts +32 -70
  111. package/dist/core/agent-session.js +92 -413
  112. package/dist/core/agent-session.js.map +1 -1
  113. package/dist/core/agents.d.ts +6 -5
  114. package/dist/core/agents.js.map +1 -1
  115. package/dist/core/bundled-agents.js +1 -3
  116. package/dist/core/bundled-agents.js.map +1 -1
  117. package/dist/core/compaction/compactor.js +78 -48
  118. package/dist/core/compaction/compactor.js.map +1 -1
  119. package/dist/core/mcp/content.js +6 -2
  120. package/dist/core/mcp/content.js.map +1 -1
  121. package/dist/core/model-unavailable.d.ts +14 -0
  122. package/dist/core/model-unavailable.js +23 -0
  123. package/dist/core/model-unavailable.js.map +1 -0
  124. package/dist/core/node-debugger.d.ts +148 -0
  125. package/dist/core/node-debugger.js +642 -0
  126. package/dist/core/node-debugger.js.map +1 -0
  127. package/dist/core/process-manager.d.ts +14 -0
  128. package/dist/core/process-manager.js +61 -0
  129. package/dist/core/process-manager.js.map +1 -1
  130. package/dist/core/session-history.d.ts +12 -0
  131. package/dist/core/session-history.js +27 -0
  132. package/dist/core/session-history.js.map +1 -1
  133. package/dist/core/settings-manager.d.ts +0 -1
  134. package/dist/core/settings-manager.js +2 -5
  135. package/dist/core/settings-manager.js.map +1 -1
  136. package/dist/core/skills.js +3 -1
  137. package/dist/core/skills.js.map +1 -1
  138. package/dist/core/subagent-manager.d.ts +11 -5
  139. package/dist/core/subagent-manager.js +15 -7
  140. package/dist/core/subagent-manager.js.map +1 -1
  141. package/dist/core/test-impact.d.ts +73 -0
  142. package/dist/core/test-impact.js +467 -0
  143. package/dist/core/test-impact.js.map +1 -0
  144. package/dist/core/thinking-level.d.ts +1 -1
  145. package/dist/core/thinking-level.js +1 -1
  146. package/dist/core/thinking-level.js.map +1 -1
  147. package/dist/core/verification-gate.d.ts +8 -98
  148. package/dist/core/verification-gate.js +26 -256
  149. package/dist/core/verification-gate.js.map +1 -1
  150. package/dist/interactive.js +2 -1
  151. package/dist/interactive.js.map +1 -1
  152. package/dist/modes/subagent-worker-mode.js +17 -5
  153. package/dist/modes/subagent-worker-mode.js.map +1 -1
  154. package/dist/motion-agent/motion-agent.d.ts +6 -2
  155. package/dist/motion-agent/motion-agent.js +5 -7
  156. package/dist/motion-agent/motion-agent.js.map +1 -1
  157. package/dist/motion-agent/motion-prompt.d.ts +1 -1
  158. package/dist/motion-agent/motion-prompt.js +14 -19
  159. package/dist/motion-agent/motion-prompt.js.map +1 -1
  160. package/dist/motion-agent/motion-review.d.ts +5 -1
  161. package/dist/motion-agent/motion-review.js +8 -3
  162. package/dist/motion-agent/motion-review.js.map +1 -1
  163. package/dist/motion-agent/motion-studio-context.js +1 -1
  164. package/dist/motion-agent/motion-studio-context.js.map +1 -1
  165. package/dist/system-prompt.js +3 -1
  166. package/dist/system-prompt.js.map +1 -1
  167. package/dist/test-support/keep-alive.d.ts +14 -0
  168. package/dist/test-support/keep-alive.js +17 -0
  169. package/dist/test-support/keep-alive.js.map +1 -0
  170. package/dist/tools/bash-read-evidence.d.ts +10 -0
  171. package/dist/tools/bash-read-evidence.js +133 -0
  172. package/dist/tools/bash-read-evidence.js.map +1 -0
  173. package/dist/tools/bash.d.ts +10 -1
  174. package/dist/tools/bash.js +66 -3
  175. package/dist/tools/bash.js.map +1 -1
  176. package/dist/tools/debug.d.ts +54 -0
  177. package/dist/tools/debug.js +233 -0
  178. package/dist/tools/debug.js.map +1 -0
  179. package/dist/tools/edit.js +12 -4
  180. package/dist/tools/edit.js.map +1 -1
  181. package/dist/tools/index.d.ts +19 -2
  182. package/dist/tools/index.js +46 -6
  183. package/dist/tools/index.js.map +1 -1
  184. package/dist/tools/prompt-hints.js +2 -0
  185. package/dist/tools/prompt-hints.js.map +1 -1
  186. package/dist/tools/read-tracker.d.ts +5 -0
  187. package/dist/tools/read-tracker.js +19 -9
  188. package/dist/tools/read-tracker.js.map +1 -1
  189. package/dist/tools/skill.js +5 -0
  190. package/dist/tools/skill.js.map +1 -1
  191. package/dist/tools/steroids.d.ts +1 -1
  192. package/dist/tools/subagent-control.js +11 -3
  193. package/dist/tools/subagent-control.js.map +1 -1
  194. package/dist/tools/subagent-shared.d.ts +16 -8
  195. package/dist/tools/subagent-shared.js +21 -15
  196. package/dist/tools/subagent-shared.js.map +1 -1
  197. package/dist/tools/subagent.d.ts +8 -2
  198. package/dist/tools/subagent.js +16 -9
  199. package/dist/tools/subagent.js.map +1 -1
  200. package/dist/tools/tool-tiers.d.ts +2 -2
  201. package/dist/tools/tool-tiers.js +3 -2
  202. package/dist/tools/tool-tiers.js.map +1 -1
  203. package/dist/ui/App.d.ts +0 -7
  204. package/dist/ui/App.js +6 -79
  205. package/dist/ui/App.js.map +1 -1
  206. package/dist/ui/hooks/useAgentLoop.d.ts +0 -7
  207. package/dist/ui/hooks/useAgentLoop.js +1 -119
  208. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  209. package/dist/ui/render.d.ts +0 -4
  210. package/dist/ui/render.js +0 -2
  211. package/dist/ui/render.js.map +1 -1
  212. package/dist/utils/image.d.ts +14 -0
  213. package/dist/utils/image.js +16 -0
  214. package/dist/utils/image.js.map +1 -1
  215. package/package.json +4 -4
  216. package/assets/motion/references/motion-language.md +0 -128
  217. package/assets/motion/skills/video-qa/SKILL.md +0 -89
  218. package/dist/core/ideal-review-subagent.d.ts +0 -56
  219. package/dist/core/ideal-review-subagent.js +0 -112
  220. package/dist/core/ideal-review-subagent.js.map +0 -1
  221. package/dist/core/ideal-review.d.ts +0 -82
  222. package/dist/core/ideal-review.js +0 -242
  223. package/dist/core/ideal-review.js.map +0 -1
  224. package/dist/motion-agent/motion-check-tool.d.ts +0 -42
  225. package/dist/motion-agent/motion-check-tool.js +0 -564
  226. package/dist/motion-agent/motion-check-tool.js.map +0 -1
@@ -1,30 +1,32 @@
1
1
  ---
2
2
  name: shared-language
3
- description: Use when a project's domain vocabulary is fuzzy or drifting, naming decisions keep recurring, or a hard-to-reverse architectural decision needs recording so it is not re-litigated or re-suggested later. Do NOT use for throwaway scripts or projects too small to have recurring vocabulary.
3
+ description: Use when a project's domain vocabulary is fuzzy or drifting (two names for one thing, one name for two), naming decisions keep recurring, or a hard-to-reverse architectural decision needs recording so it is not re-litigated or re-suggested — including mid-build when a term settles or a change contradicts an ADR. Do NOT use for throwaway scripts, projects too small to have recurring vocabulary, interviewing for requirements (clarify), or renames with no vocabulary decision (refactoring).
4
4
  ---
5
5
 
6
6
  # Shared Language
7
7
 
8
- A repo's terms are its compression. When you and the user mean the same thing by "reservation", every prompt, name, and doc gets shorter and sharper — and the agent stops spending thinking tokens re-deriving what a single word encodes. This skill builds and maintains that vocabulary.
8
+ Two artifacts: the glossary (`CONTEXT.md`) and decision records (`docs/adr/`). On entry, read both if they exist, then act on the trigger: term settled → glossary; hard call made → offer ADR; change contradicts an ADR → surface it.
9
9
 
10
10
  ## The glossary — CONTEXT.md
11
11
 
12
- At the repo root. **A glossary and nothing else**: term — a one-to-three-line definition, no implementation details, no history. If a definition names a file path, it has become documentation; move that out.
12
+ At the repo root. **A glossary and nothing else**: `term — 1–3 line definition`, plus `Avoid: <synonyms>` where drift exists. No file paths, implementation, or history.
13
13
 
14
- - Challenge fuzzy terms against it: "the glossary defines *cancellation* as pre-charge; this change reads as post-charge — which is meant?"
15
- - Stress-test a new term with an invented edge case before recording it ("is a no-show a cancellation?").
16
- - Update **inline, the moment a term settles** — never batch glossary edits for "later"; later never comes.
17
- - Name files, functions, variables, and tests with glossary terms verbatim. When code and glossary disagree, one of them is wrong — find out which.
18
- - Create the file lazily on the first settled term, never as an empty template.
19
- - On first creation, add one line to the repo's instruction file (AGENTS.md, or CLAUDE.md if that is what the repo uses): `Read CONTEXT.md before naming anything.` CONTEXT.md is not auto-loaded — the pointer is what makes the glossary ambient in every session.
14
+ - Challenge fuzzy usage against it: "glossary says *cancellation* is pre-charge; this reads post-charge — which?"
15
+ - Test a candidate term with an invented edge case before recording it ("is a no-show a cancellation?").
16
+ - Update the moment a term settles; create the file lazily on the first settled term, never as an empty template.
17
+ - Code, tests, and UI use glossary terms verbatim. Code and glossary disagree → one is wrong; ask which.
18
+ - On creation, add to the repo's instruction file (AGENTS.md, or CLAUDE.md if that is what it uses): `Read CONTEXT.md before naming anything.` CONTEXT.md is not auto-loaded — that pointer is what makes it count in later sessions.
20
19
 
21
20
  ## Decision records — docs/adr/
22
21
 
23
- An ADR earns its file only when a decision is **hard to reverse**, **surprising without context**, and **a real tradeoff** — all three. One file per decision: title, 1–3 sentences of context, the decision, the main rejected alternative and why. Numbered; immutable once accepted — supersede, never edit.
22
+ Only when a decision is **hard to reverse**, **surprising without context**, and **a real tradeoff** — all three. Offer it; don't write unasked.
24
23
 
25
- Read the ADRs before proposing a change that contradicts one: honor it, or surface the conflict to the user. Never silently relitigate a recorded decision, and never re-suggest a rejected alternative without new facts.
24
+ - Follow the repo's existing ADR format. None? Use the MADR 4 minimal shape: `NNNN-title-with-dashes.md` with Context and Problem Statement, Considered Options, Decision Outcome (chosen option + why), Consequences; `status: accepted` in front matter.
25
+ - Immutable once accepted — supersede, never edit: new ADR notes `Supersedes NNNN`; the old one's status becomes `superseded by NNNN` (the only allowed change).
26
+ - Before proposing a change that contradicts an ADR: honour it or raise the conflict. Never re-suggest a rejected option without new facts.
26
27
 
27
- ## Integration
28
+ ## Scaling: one agent or several
28
29
 
29
- - During a clarify session: settled terms go to the glossary; qualifying hard calls get an ADR offer.
30
- - Before naming anything: read the glossary if it exists.
30
+ Main thread only. On a large repo, one `owl` may inventory competing terms across packages (occurrences with file:line); the main thread decides and edits.
31
+
32
+ Sources (accessed 3 October 2026): MADR 4.0.0, latest release (2024-09-17) — https://adr.github.io/madr/; ubiquitous language — https://martinfowler.com/bliki/UbiquitousLanguage.html
@@ -1,30 +1,42 @@
1
1
  ---
2
2
  name: tdd
3
- description: Use when the user asks for test-driven development, red-green-refactor, or "write the test first", or wants a feature built test-first. Do NOT use when tests are a verification step after the build, the project has no suite and the user has not asked for one, or the change is throwaway probe code.
3
+ description: Use when the user asks for test-driven development, red-green-refactor, "write the test first", or wants a feature or bug fix built test-first — including mid-build when they ask to switch to test-first. Do NOT use when tests are a verification step after the build, the project has no suite and the user has not asked for one, the change is throwaway probe code, or the goal is restructuring without behaviour change (refactoring) or finding an unknown cause (root-cause).
4
4
  ---
5
5
 
6
6
  # TDD
7
7
 
8
- Red → green, one slice at a time. This skill is the reference that makes the loop produce tests worth keeping — most of it applies on every cycle, so consult it before and during the loop, not after.
8
+ Red → green, one vertical slice at a time. Before the first test: agree seams (below). Then loop.
9
9
 
10
10
  ## Seams — agree before writing
11
11
 
12
- A **seam** is the public boundary where behavior is observable: an exported function, an HTTP route, a CLI invocation. Tests live at seams; they never reach into internals.
13
-
14
- Before the first test, write down the seams under test and confirm them with the user — which boundaries get tests and which stay untested is a decision, and settling it up front is what keeps effort on critical paths instead of every edge case. No test at an unagreed seam.
12
+ A **seam** is a public boundary where behaviour is observable: exported function, HTTP route, CLI invocation. Tests live at seams, never in internals. List the seams under test and confirm them with the user (one `ask_user` call, recommended set marked). No test at an unagreed seam.
15
13
 
16
14
  ## The loop
17
15
 
18
- 1. **Red.** One failing test at an agreed seam, for the next smallest real behavior. Run it; watch it fail for the right reason.
19
- 2. **Green.** The least code that passes — nothing speculative. Run it.
20
- 3. **Repeat.** The next test responds to what the last cycle taught. Work in vertical slices, never layers: writing all tests then all implementation verifies *imagined* behavior and locks in structure before understanding.
21
- 4. **Refactor outside the loop.** Cleanup happens at a checkpoint after a green cycle or in a review pass — not interleaved guesswork inside red-green.
16
+ 1. **Red.** One failing test at an agreed seam for the next smallest real behaviour. Run it; confirm it fails for the right reason (assertion, not import/syntax error).
17
+ 2. **Green.** Least code that passes. Run the test and the touched suite.
18
+ 3. **Repeat.** The next test follows from what the last cycle taught. Never write all tests first, then all code.
19
+ 4. **Refactor** only on green, as a separate step; rerun tests after.
20
+
21
+ ## Test integrity (agent guard)
22
+
23
+ - **Tests are frozen during green.** Never edit, delete, skip, loosen, or `.only` a test to make it pass. If a test is wrong, stop, say why, and get agreement before changing it.
24
+ - Never special-case test inputs in production code (hard-coded returns for the test's literal).
25
+ - Before claiming done, `git diff` the test files; explain any change made during a green step.
26
+
27
+ ## Test quality
28
+
29
+ - **Expected values from an outside source of truth** — a known literal, worked example, or the spec. Never recompute the expected value the way the code does.
30
+ - **Behaviour, not structure.** A test that breaks under a behaviour-preserving refactor is coupled to internals; rewrite it at the seam.
31
+ - **Mock only external boundaries** (network, clock, filesystem), and only when slow or stateful.
32
+ - **Name like a spec**: "user can check out with an empty cart".
33
+ - **Property tests for rules over many inputs** (parsers, round-trips, invariants) when the project already has a property library (fast-check, Hypothesis, proptest); otherwise a table of examples.
34
+ - **Optional strength check:** if a mutation tool is already installed (Stryker, mutmut, cargo-mutants), run it on the changed module; surviving mutants point to missing assertions. Do not install one unasked. Manual alternative: break one line of the new code, confirm a test goes red, revert.
35
+
36
+ Never claim a cycle green that you did not run.
22
37
 
23
- ## Test quality rules
38
+ ## Scaling: one agent or several
24
39
 
25
- - **Expected values from an outside source of truth** — a known literal, a worked example, the spec. Never recompute the expected value the same way the code does; that test can only agree with itself and can never catch the bug.
26
- - **Behavior, not structure.** Assert on what the interface does. A test that breaks under a refactor with unchanged behavior is coupled to implementation — rewrite it at the seam, never patch it with mocks of internals.
27
- - **Real paths over mocks.** Exercise real code; mock only external boundaries (network, clock, filesystem) and only when they are slow or stateful.
28
- - **Named like a spec.** "user can check out with an empty cart" — the name alone states the capability.
40
+ Main thread only — the loop is sequential by design. Never parallelise red/green steps or let a child edit tests.
29
41
 
30
- The loop inherits the verification gate: never claim a cycle green that you did not run.
42
+ Sources (accessed 3 October 2026): https://code.claude.com/docs/en/best-practices (failing test before the fix); https://stryker-mutator.io/docs/ (killed vs surviving mutants); https://hypothesis.readthedocs.io/
@@ -37,7 +37,7 @@ import { isWorkflowCommandText, countAssistantMessages, shouldStartAutopilotCycl
37
37
  import { driveAutopilotCycle, frameAutopilotInjection } from "./core/autopilot-cycle.js";
38
38
  import { describeRunVerification, describeTurnVerification } from "./core/run-status.js";
39
39
  import { validateKenModelPref, effectiveKenModel } from "./core/ken-model.js";
40
- import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeKenTurnsForHistory, getHistoryMessageVisibility, replayMessagesInOrder, restoreUserRow, restoreAssistantTexts, resolveRestoredCommand, autopilotMarkerCopySeed, } from "./core/session-history.js";
40
+ import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeKenTurnsForHistory, getHistoryMessageVisibility, replayMessagesInOrder, restoreUserRow, restoreAssistantTexts, resolveRestoredCommand, autopilotMarkerCopySeed, extractToolImagePaths, } from "./core/session-history.js";
41
41
  import { sessionToMarkdown, defaultExportFilename, } from "./core/session-export.js";
42
42
  import { AuthStorage } from "./core/auth-storage.js";
43
43
  import { advancesPhase, explainPullFailure, isGgufShard, isValidHfRepoId, parseOllamaPullLine, pickGgufQuant, SHARDED_MESSAGE, toHfSearchRow, } from "./hf-pull.js";
@@ -72,7 +72,8 @@ import { installTerminationHandlers } from "./core/shutdown.js";
72
72
  import { KeepAwake } from "./core/keep-awake.js";
73
73
  import { RADIO_STATIONS, getCurrentStation, getRadioVolume, playRadio, setRadioVolume, stopRadio, } from "./core/radio.js";
74
74
  import { enrichProcessPath } from "./core/shell-path.js";
75
- import { downscaleForPreview, shrinkToFit, validateVisionImage } from "./utils/image.js";
75
+ import { downscaleForPreview, IMAGE_MEDIA_TYPES, shrinkToFit, validateVisionImage, } from "./utils/image.js";
76
+ import { readFileBounded } from "./tools/operations.js";
76
77
  import { startServeMode } from "./modes/serve-mode.js";
77
78
  import { installSteroids, probeSteroids } from "./core/steroids.js";
78
79
  import { loadTelegramConfig, saveTelegramConfig, verifyBotToken } from "./core/telegram-config.js";
@@ -996,6 +997,11 @@ async function main() {
996
997
  const shutdown = installTerminationHandlers({
997
998
  scope: "app-sidecar",
998
999
  teardown: async () => {
1000
+ // Before any await: background commands live outside the daemon's process
1001
+ // group, and the app force-kills that group after 3 s. If a slow session
1002
+ // teardown is still pending then, these would never be stopped.
1003
+ for (const c of sessions.values())
1004
+ c.stopBackgroundProcesses();
999
1005
  clearInterval(parentWatch);
1000
1006
  // Radio playback is app-wide (one stream across all windows), so it stops
1001
1007
  // at the daemon level, not per session.
@@ -1988,7 +1994,7 @@ async function createSession(deps, opts) {
1988
1994
  session.eventBus.on("hook", (d) => broadcast("hook", d));
1989
1995
  session.eventBus.on("diagnostics", (d) => broadcast("diagnostics", d));
1990
1996
  // Fires BEFORE the candidate final answer streams. The webview holds assistant
1991
- // text back while armed, so an Ideal review supersedes a draft that was never
1997
+ // text back while armed, so an injected follow-up supersedes a draft that was never
1992
1998
  // painted instead of deleting one the user already started reading.
1993
1999
  session.eventBus.on("hook_armed", (d) => broadcast("hook_armed", d));
1994
2000
  session.eventBus.on("subagent_state", (d) => broadcast("subagent_state", d));
@@ -2060,10 +2066,8 @@ async function createSession(deps, opts) {
2060
2066
  // Autopilot (auto-review) toggle for THIS window's project. Loaded from
2061
2067
  // gg-app.json on boot; flipped via POST /autopilot. When on, POST /prompt runs
2062
2068
  // runAutopilotCycle after the user's turn settles — Ken auto-reviews the work
2063
- // and drives the review→prompt→review loop. Ken is the sole verification
2064
- // owner in this mode, so suppress the build session's redundant Ideal hook.
2069
+ // and drives the review→prompt→review loop.
2065
2070
  let autopilot = mode === "code" && (await loadAutopilot(cwd));
2066
- session.setIdealReviewSuppressed(autopilot);
2067
2071
  // True while an autopilot review is in flight (used to defer kenAuto model
2068
2072
  // switches, like kenRunning does for chat Ken, and to drive the spinner).
2069
2073
  let autopilotReviewing = false;
@@ -2269,9 +2273,6 @@ async function createSession(deps, opts) {
2269
2273
  // (often >5 min) regardless of the user's global speedProfile pick.
2270
2274
  forceLongCacheRetention: true,
2271
2275
  });
2272
- // Ken is already the independent autopilot reviewer; recursively running
2273
- // his own Ideal self-review adds latency and can corrupt the verdict shape.
2274
- ken.setIdealReviewSuppressed(true);
2275
2276
  await ken.initialize();
2276
2277
  // Keep review text/tools silent; report usage only for whole-task accounting.
2277
2278
  ken.eventBus.on("turn_end", (d) => {
@@ -2536,7 +2537,6 @@ async function createSession(deps, opts) {
2536
2537
  const generation = runLifecycle.begin(abortOwnedWork).generation;
2537
2538
  pendingCancelDrain = null;
2538
2539
  autopilotActive = true;
2539
- session.setIdealReviewSuppressed(true);
2540
2540
  // Generation captured by the last plan review; acceptPlan re-checks it so
2541
2541
  // a user Accept/Reject landing mid-review always wins.
2542
2542
  let planGenAtReview = -1;
@@ -2654,7 +2654,6 @@ async function createSession(deps, opts) {
2654
2654
  }
2655
2655
  finally {
2656
2656
  autopilotActive = false;
2657
- session.setIdealReviewSuppressed(autopilot);
2658
2657
  finishOwnedGeneration(generation, true, session.getVerificationProblem() ? "unverified" : "completed");
2659
2658
  queueMicrotask(() => void runStrandedQueue());
2660
2659
  }
@@ -3289,7 +3288,16 @@ async function createSession(deps, opts) {
3289
3288
  // Pre-index tool results by toolCallId so we can pair tool calls with
3290
3289
  // their results (for sub-agent status + image extraction).
3291
3290
  const toolResultMap = new Map();
3291
+ // Tool name per call, so restore only trusts generate_image's own text
3292
+ // when it reads extra images from disk (an MCP server could fake it).
3293
+ const toolNameById = new Map();
3292
3294
  for (const msg of messages) {
3295
+ if (msg.role === "assistant" && typeof msg.content !== "string") {
3296
+ for (const c of msg.content) {
3297
+ if (c.type === "tool_call")
3298
+ toolNameById.set(c.id, c.name);
3299
+ }
3300
+ }
3293
3301
  if (msg.role !== "tool")
3294
3302
  continue;
3295
3303
  for (const tr of msg.content) {
@@ -3449,31 +3457,43 @@ async function createSession(deps, opts) {
3449
3457
  const imageBlocks = tr.content.filter((c) => c.type === "image");
3450
3458
  if (imageBlocks.length === 0)
3451
3459
  continue;
3452
- // Extract the path from the text block (e.g. "Generated image → /path").
3460
+ // Extract the path from the text block so the restored image
3461
+ // stays clickable (read / screenshot / generate_image formats).
3453
3462
  const textBlock = tr.content.find((c) => c.type === "text" && "text" in c && typeof c.text === "string");
3454
3463
  const textContent = textBlock && textBlock.type === "text" ? textBlock.text : "";
3455
- const pathMatch = textContent.match(/→\s*(\S+)/);
3456
- const imgPath = pathMatch?.[1];
3457
- // Downscale each image for the webview preview.
3464
+ const imgPaths = extractToolImagePaths(textContent);
3465
+ // Downscale each image for the webview preview. Paths pair with
3466
+ // image blocks in order (a tool saves one file per image).
3458
3467
  const toolImages = [];
3468
+ let blockIndex = 0;
3459
3469
  for (const block of imageBlocks) {
3460
3470
  if (block.type !== "image")
3461
3471
  continue;
3462
- try {
3463
- const rawBuf = Buffer.from(block.data, "base64");
3464
- const previewBuf = await downscaleForPreview(rawBuf);
3465
- toolImages.push({
3466
- src: `data:${block.mediaType};base64,${previewBuf.toString("base64")}`,
3467
- path: imgPath,
3468
- });
3469
- }
3470
- catch {
3471
- // Downscale failed — use the raw data.
3472
- toolImages.push({
3473
- src: `data:${block.mediaType};base64,${block.data}`,
3474
- path: imgPath,
3475
- });
3476
- }
3472
+ const imgPath = imgPaths[blockIndex++];
3473
+ const previewBuf = await downscaleForPreview(Buffer.from(block.data, "base64"));
3474
+ toolImages.push({
3475
+ src: `data:${block.mediaType};base64,${previewBuf.toString("base64")}`,
3476
+ path: imgPath,
3477
+ });
3478
+ }
3479
+ // generate_image persists only its first image's pixels; the
3480
+ // rest exist only on disk, so preview them from their files.
3481
+ // Skip silently if a file was moved or deleted since.
3482
+ const extraPaths = toolNameById.get(tr.toolCallId) === "generate_image"
3483
+ ? imgPaths.slice(blockIndex)
3484
+ : [];
3485
+ for (const extraPath of extraPaths) {
3486
+ const mediaType = IMAGE_MEDIA_TYPES[path.extname(extraPath).toLowerCase()];
3487
+ if (!mediaType)
3488
+ continue;
3489
+ const raw = await readFileBounded(extraPath).catch(() => null);
3490
+ if (!raw)
3491
+ continue;
3492
+ const previewBuf = await downscaleForPreview(raw);
3493
+ toolImages.push({
3494
+ src: `data:${mediaType};base64,${previewBuf.toString("base64")}`,
3495
+ path: extraPath,
3496
+ });
3477
3497
  }
3478
3498
  if (toolImages.length > 0) {
3479
3499
  history.push({
@@ -3904,9 +3924,6 @@ async function createSession(deps, opts) {
3904
3924
  return;
3905
3925
  }
3906
3926
  autopilot = enabled;
3907
- // A toggle-off during an active cycle takes effect after Ken finishes;
3908
- // until then, injected build runs must not re-enable Ideal self-review.
3909
- session.setIdealReviewSuppressed(enabled || autopilotActive);
3910
3927
  await saveAutopilot(cwd, enabled);
3911
3928
  log("INFO", "app-sidecar", "autopilot toggled", { enabled: String(enabled) });
3912
3929
  broadcast("autopilot", { autopilot: enabled });
@@ -5238,6 +5255,11 @@ async function createSession(deps, opts) {
5238
5255
  await kenAutoSession?.dispose().catch(() => { });
5239
5256
  await session.dispose().catch(() => { });
5240
5257
  }
5258
+ function stopBackgroundProcesses() {
5259
+ session.stopBackgroundProcesses();
5260
+ kenSession?.stopBackgroundProcesses();
5261
+ kenAutoSession?.stopBackgroundProcesses();
5262
+ }
5241
5263
  return {
5242
5264
  id: opts.id,
5243
5265
  mode,
@@ -5251,6 +5273,7 @@ async function createSession(deps, opts) {
5251
5273
  broadcast,
5252
5274
  handle,
5253
5275
  dispose,
5276
+ stopBackgroundProcesses,
5254
5277
  };
5255
5278
  }
5256
5279
  main().catch(async (err) => {