@gajae-code/coding-agent 0.2.1 → 0.2.3

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 (153) hide show
  1. package/CHANGELOG.md +59 -1
  2. package/dist/types/cli/setup-cli.d.ts +1 -0
  3. package/dist/types/commands/contribution-prep.d.ts +18 -0
  4. package/dist/types/commands/deep-interview.d.ts +41 -0
  5. package/dist/types/commands/session.d.ts +24 -0
  6. package/dist/types/commands/setup.d.ts +3 -0
  7. package/dist/types/config/model-registry.d.ts +2 -2
  8. package/dist/types/config/models-config-schema.d.ts +17 -9
  9. package/dist/types/config/settings-schema.d.ts +37 -24
  10. package/dist/types/discovery/helpers.d.ts +2 -0
  11. package/dist/types/extensibility/extensions/types.d.ts +6 -0
  12. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +33 -0
  13. package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
  14. package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -11
  15. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +25 -0
  16. package/dist/types/gjc-runtime/state-runtime.d.ts +13 -0
  17. package/dist/types/gjc-runtime/team-runtime.d.ts +37 -5
  18. package/dist/types/gjc-runtime/tmux-common.d.ts +41 -0
  19. package/dist/types/gjc-runtime/tmux-sessions.d.ts +17 -0
  20. package/dist/types/goals/runtime.d.ts +3 -9
  21. package/dist/types/goals/state.d.ts +3 -6
  22. package/dist/types/goals/tools/goal-tool.d.ts +1 -69
  23. package/dist/types/hooks/skill-state.d.ts +5 -0
  24. package/dist/types/memories/index.d.ts +1 -1
  25. package/dist/types/memory-backend/local-backend.d.ts +3 -3
  26. package/dist/types/modes/components/hook-selector.d.ts +7 -0
  27. package/dist/types/modes/components/settings-selector.d.ts +0 -2
  28. package/dist/types/modes/components/status-line/types.d.ts +0 -3
  29. package/dist/types/modes/components/status-line.d.ts +0 -3
  30. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  31. package/dist/types/modes/interactive-mode.d.ts +1 -12
  32. package/dist/types/modes/theme/defaults/index.d.ts +0 -2
  33. package/dist/types/modes/theme/theme.d.ts +1 -2
  34. package/dist/types/modes/types.d.ts +1 -7
  35. package/dist/types/modes/utils/context-usage.d.ts +6 -2
  36. package/dist/types/sdk.d.ts +6 -2
  37. package/dist/types/session/agent-session.d.ts +47 -1
  38. package/dist/types/session/contribution-prep.d.ts +47 -0
  39. package/dist/types/session/session-manager.d.ts +3 -0
  40. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
  41. package/dist/types/setup/provider-onboarding.d.ts +29 -5
  42. package/dist/types/skill-state/active-state.d.ts +30 -1
  43. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +6 -1
  44. package/dist/types/skill-state/initial-phase.d.ts +12 -0
  45. package/dist/types/skill-state/workflow-hud.d.ts +9 -4
  46. package/dist/types/skill-state/workflow-state-contract.d.ts +34 -0
  47. package/dist/types/task/executor.d.ts +2 -0
  48. package/dist/types/task/types.d.ts +11 -0
  49. package/dist/types/tools/index.d.ts +20 -1
  50. package/dist/types/tools/skill.d.ts +47 -0
  51. package/dist/types/utils/changelog.d.ts +18 -2
  52. package/package.json +7 -7
  53. package/src/cli/args.ts +3 -2
  54. package/src/cli/setup-cli.ts +26 -12
  55. package/src/cli.ts +7 -1
  56. package/src/commands/contribution-prep.ts +41 -0
  57. package/src/commands/deep-interview.ts +30 -23
  58. package/src/commands/launch.ts +10 -1
  59. package/src/commands/ralplan.ts +10 -22
  60. package/src/commands/session.ts +150 -0
  61. package/src/commands/setup.ts +2 -0
  62. package/src/commands/state.ts +15 -4
  63. package/src/commands/team.ts +23 -3
  64. package/src/config/model-registry.ts +10 -2
  65. package/src/config/models-config-schema.ts +120 -102
  66. package/src/config/settings-schema.ts +42 -25
  67. package/src/config.ts +1 -1
  68. package/src/defaults/gjc/skills/deep-interview/SKILL.md +32 -13
  69. package/src/defaults/gjc/skills/ralplan/SKILL.md +22 -2
  70. package/src/defaults/gjc/skills/team/SKILL.md +39 -7
  71. package/src/defaults/gjc/skills/ultragoal/SKILL.md +33 -25
  72. package/src/discovery/helpers.ts +24 -1
  73. package/src/eval/py/prelude.py +1 -1
  74. package/src/extensibility/extensions/types.ts +6 -0
  75. package/src/gjc-runtime/deep-interview-runtime.ts +546 -0
  76. package/src/gjc-runtime/goal-mode-request.ts +2 -19
  77. package/src/gjc-runtime/launch-tmux.ts +83 -43
  78. package/src/gjc-runtime/ralplan-runtime.ts +460 -0
  79. package/src/gjc-runtime/state-runtime.ts +731 -0
  80. package/src/gjc-runtime/team-runtime.ts +708 -52
  81. package/src/gjc-runtime/tmux-common.ts +119 -0
  82. package/src/gjc-runtime/tmux-sessions.ts +165 -0
  83. package/src/gjc-runtime/ultragoal-guard.ts +6 -3
  84. package/src/gjc-runtime/ultragoal-runtime.ts +5 -4
  85. package/src/goals/runtime.ts +38 -144
  86. package/src/goals/state.ts +36 -7
  87. package/src/goals/tools/goal-tool.ts +15 -172
  88. package/src/hooks/skill-state.ts +39 -18
  89. package/src/internal-urls/docs-index.generated.ts +5 -4
  90. package/src/internal-urls/memory-protocol.ts +3 -2
  91. package/src/main.ts +2 -3
  92. package/src/memories/index.ts +2 -1
  93. package/src/memory-backend/local-backend.ts +14 -6
  94. package/src/modes/components/hook-selector.ts +156 -1
  95. package/src/modes/components/settings-selector.ts +5 -12
  96. package/src/modes/components/skill-hud/render.ts +4 -0
  97. package/src/modes/components/status-line/segments.ts +5 -16
  98. package/src/modes/components/status-line/types.ts +0 -3
  99. package/src/modes/components/status-line.ts +0 -6
  100. package/src/modes/controllers/command-controller.ts +27 -4
  101. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  102. package/src/modes/controllers/input-controller.ts +0 -15
  103. package/src/modes/controllers/selector-controller.ts +4 -11
  104. package/src/modes/interactive-mode.ts +18 -219
  105. package/src/modes/theme/defaults/dark-poimandres.json +0 -1
  106. package/src/modes/theme/defaults/light-poimandres.json +0 -1
  107. package/src/modes/theme/theme.ts +0 -6
  108. package/src/modes/types.ts +1 -7
  109. package/src/modes/utils/context-usage.ts +66 -17
  110. package/src/prompts/agents/architect.md +3 -0
  111. package/src/prompts/agents/executor.md +2 -0
  112. package/src/prompts/agents/frontmatter.md +1 -0
  113. package/src/prompts/goals/goal-continuation.md +1 -4
  114. package/src/prompts/goals/goal-mode-active.md +3 -5
  115. package/src/prompts/system/subagent-system-prompt.md +6 -0
  116. package/src/prompts/system/system-prompt.md +5 -7
  117. package/src/prompts/tools/goal.md +4 -4
  118. package/src/prompts/tools/skill.md +28 -0
  119. package/src/prompts/tools/task.md +3 -0
  120. package/src/sdk.ts +51 -11
  121. package/src/session/agent-session.ts +222 -21
  122. package/src/session/contribution-prep.ts +320 -0
  123. package/src/session/session-manager.ts +9 -1
  124. package/src/setup/model-onboarding-guidance.ts +6 -3
  125. package/src/setup/provider-onboarding.ts +177 -16
  126. package/src/skill-state/active-state.ts +188 -25
  127. package/src/skill-state/deep-interview-mutation-guard.ts +72 -21
  128. package/src/skill-state/initial-phase.ts +17 -0
  129. package/src/skill-state/workflow-hud.ts +23 -5
  130. package/src/skill-state/workflow-state-contract.ts +121 -0
  131. package/src/slash-commands/builtin-registry.ts +75 -25
  132. package/src/slash-commands/helpers/context-report.ts +123 -13
  133. package/src/task/agents.ts +1 -0
  134. package/src/task/commands.ts +1 -5
  135. package/src/task/executor.ts +9 -1
  136. package/src/task/index.ts +91 -4
  137. package/src/task/types.ts +6 -0
  138. package/src/tools/ask.ts +2 -0
  139. package/src/tools/gh.ts +212 -2
  140. package/src/tools/index.ts +25 -6
  141. package/src/tools/skill.ts +153 -0
  142. package/src/utils/changelog.ts +67 -44
  143. package/dist/types/commands/gjc-runtime-bridge.d.ts +0 -30
  144. package/dist/types/commands/question.d.ts +0 -7
  145. package/dist/types/modes/loop-limit.d.ts +0 -22
  146. package/src/commands/gjc-runtime-bridge.ts +0 -227
  147. package/src/commands/question.ts +0 -12
  148. package/src/modes/loop-limit.ts +0 -140
  149. package/src/prompts/commands/orchestrate.md +0 -49
  150. package/src/prompts/goals/goal-budget-limit.md +0 -16
  151. package/src/prompts/tools/create-goal.md +0 -3
  152. package/src/prompts/tools/get-goal.md +0 -3
  153. package/src/prompts/tools/update-goal.md +0 -3
@@ -11,7 +11,7 @@ Use when the user asks for `ultragoal`, `create-goals`, `complete-goals`, durabl
11
11
 
12
12
  ## Purpose
13
13
 
14
- `ultragoal` turns a brief into repo-native artifacts and then drives a GJC goal safely through the named goal tools: `get_goal`, `create_goal`, and `update_goal`. New plans default to a stable pointer-style aggregate GJC goal for the whole durable plan in `.gjc/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while GJC tracks G001/G002 story progress in the ledger. Ultragoal does not call `/goal clear`; before multiple sequential ultragoal runs in one session/thread, manually run `/goal clear` in the UI so the previous completed aggregate goal does not block or confuse the next `create_goal`.
14
+ `ultragoal` turns a brief into repo-native artifacts and then drives a GJC goal safely through the unified `goal` tool. New plans default to a stable pointer-style aggregate GJC goal for the whole durable plan in `.gjc/ultragoal/goals.json`, including later accepted/appended stories under the original brief constraints, while GJC tracks G001/G002 story progress in the ledger. Ultragoal does not call `/goal clear`; before multiple sequential ultragoal runs in one session/thread, manually run `/goal clear` in the UI so the previous completed aggregate goal does not block or confuse the next `goal({"op":"create"})`.
15
15
 
16
16
  - `.gjc/ultragoal/brief.md`
17
17
  - `.gjc/ultragoal/goals.json`
@@ -30,21 +30,20 @@ gjc ultragoal create-goals --brief "<brief>"
30
30
  gjc ultragoal create-goals --brief-file <path>
31
31
  gjc ultragoal complete-goals
32
32
  gjc ultragoal complete-goals --retry-failed
33
- gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --gjc-goal-json <get-goal-json-or-path> --quality-gate-json <quality-gate-json-or-path>
33
+ gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --gjc-goal-json <goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>
34
34
  gjc ultragoal checkpoint --goal-id <id> --status failed --evidence "<blocker/evidence>"
35
- gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve final review blockers" --objective "<blocker-resolution objective>" --evidence "<review findings>" --gjc-goal-json <active-get-goal-json-or-path>
35
+ gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve final review blockers" --objective "<blocker-resolution objective>" --evidence "<review findings>" --gjc-goal-json <active-goal-get-json-or-path>
36
36
  ```
37
37
 
38
38
  Use these exact goal-tool calls for the inline goal state:
39
39
 
40
40
  ```json
41
- get_goal({})
42
- create_goal({"objective":"<printed aggregate or per-story objective>"})
43
- update_goal({"status":"complete"})
41
+ goal({"op":"get"})
42
+ goal({"op":"create","objective":"<printed aggregate or per-story objective>"})
43
+ goal({"op":"complete"})
44
44
  ```
45
45
 
46
- `get_goal`, `create_goal`, and `update_goal` share the same session goal state as `/goal`; prefer these named tools inside Ultragoal because they produce JSON snapshots for ledger reconciliation.
47
-
46
+ The unified `goal` tool shares the same session goal state as `/goal`; use `goal({"op":"get"})` snapshots inside Ultragoal for ledger reconciliation.
48
47
 
49
48
  ## Create goals
50
49
 
@@ -61,17 +60,17 @@ Loop until `gjc ultragoal status` reports all goals complete:
61
60
 
62
61
  1. Run `gjc ultragoal complete-goals`.
63
62
  2. Read the printed handoff.
64
- 3. Call `get_goal({})`.
65
- 4. If no active GJC goal exists, call `create_goal({"objective":"<printed payload objective>"})` with the printed payload. In aggregate mode, if the same aggregate objective is already active, continue the current GJC story without creating a new GJC goal.
63
+ 3. Call `goal({"op":"get"})`.
64
+ 4. If no active GJC goal exists, call `goal({"op":"create","objective":"<printed payload objective>"})` with the printed payload. In aggregate mode, if the same aggregate objective is already active, continue the current GJC story without creating a new GJC goal.
66
65
  5. Complete the current GJC story only.
67
66
  6. Run a completion audit against the story objective and real artifacts/tests.
68
- 7. Before any `--status complete` checkpoint, run the mandatory final cleanup/review gate below. In aggregate mode, do **not** call `update_goal` for intermediate stories; checkpoint each story with a fresh `get_goal({})` snapshot whose aggregate objective is still `active`. On the final story, use the same fresh active snapshot to create the final aggregate receipt first; only after that receipt exists may `update_goal({"status":"complete"})` run.
67
+ 7. Before any `--status complete` checkpoint, run the mandatory final cleanup/review gate below. In aggregate mode, do **not** call `goal({"op":"complete"})` for intermediate stories; checkpoint each story with a fresh `goal({"op":"get"})` snapshot whose aggregate objective is still `active`. On the final story, use the same fresh active snapshot to create the final aggregate receipt first; only after that receipt exists may `goal({"op":"complete"})` run.
69
68
  8. Checkpoint the durable ledger with that fresh active snapshot. Complete checkpoints require `--quality-gate-json`; the runtime hook rejects closure without a clean architect review:
70
- `gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --gjc-goal-json <get_goal-json-or-path> --quality-gate-json <quality-gate-json-or-path>`
69
+ `gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --gjc-goal-json <goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>`
71
70
  9. If blocked or failed, checkpoint failure:
72
71
  `gjc ultragoal checkpoint --goal-id <id> --status failed --evidence "<blocker/evidence>"`
73
72
  11. For legacy per-story completed-goal blockers, preserve the non-terminal blocker with:
74
- `gjc ultragoal checkpoint --goal-id <id> --status blocked --evidence "<completed legacy GJC goal blocks create_goal in this thread>" --gjc-goal-json <get_goal-json-or-path>`
73
+ `gjc ultragoal checkpoint --goal-id <id> --status blocked --evidence "<completed legacy GJC goal blocks goal create in this thread>" --gjc-goal-json <goal-get-json-or-path>`
75
74
  12. Resume failed goals with `gjc ultragoal complete-goals --retry-failed`.
76
75
 
77
76
  ## Dynamic steering
@@ -104,7 +103,6 @@ Steering invariants:
104
103
 
105
104
  UserPromptSubmit uses the same steering API only for structured directives such as `GJC_ULTRAGOAL_STEER: { ... }`, `gjc.ultragoal.steer: { ... }`, or `gjc ultragoal steer: { ... }`. Normal prose does not mutate state, and repeated prompt-submit directives dedupe by prompt signature or idempotency key.
106
105
 
107
-
108
106
  ## Role-agent delegation guidance
109
107
 
110
108
  Ultragoal execution should use GJC's bundled role-agent roster when a durable story is large enough to benefit from delegation:
@@ -126,10 +124,10 @@ For large subgoals with independent slices, the Ultragoal leader must spawn para
126
124
 
127
125
  Use ultragoal and team together for a durable Ultragoal story that benefits from one visible tmux worker session. Ultragoal remains leader-owned: `.gjc/ultragoal/goals.json` stores the story plan and `.gjc/ultragoal/ledger.jsonl` stores checkpoints. Team is the single-worker tmux execution engine and returns task/evidence status to the leader.
128
126
 
129
- The leader checkpoints Ultragoal from Team evidence with a fresh `get_goal` snapshot:
127
+ The leader checkpoints Ultragoal from Team evidence with a fresh `goal({"op":"get"})` snapshot:
130
128
 
131
129
  ```sh
132
- gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/ultragoal and <id>>" --gjc-goal-json <fresh-get_goal-json-or-path> --quality-gate-json <quality-gate-json-or-path>
130
+ gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/ultragoal and <id>>" --gjc-goal-json <fresh-goal-get-json-or-path> --quality-gate-json <quality-gate-json-or-path>
133
131
  ```
134
132
 
135
133
  Workers do not own ultragoal goal state, do not create worker ultragoal ledgers, and do not checkpoint Ultragoal. Workers must not run `gjc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Team launch remains explicit; Ultragoal does not auto-launch Team and performs no hidden goal mutation.
@@ -142,7 +140,7 @@ An ultragoal story cannot be checkpointed `complete` until the active agent has
142
140
  2. Run a cleanup/refactor review pass on changed files only; if there are no relevant edits, the cleaner still runs and records a passed/no-op report.
143
141
  3. Rerun verification after the cleaner pass.
144
142
  4. Run a final code review pass and fold it into the strict quality gate. Clean means `architectReview.architectureStatus`, `architectReview.productStatus`, and `architectReview.codeStatus` are all `"CLEAR"`, `architectReview.recommendation` is `"APPROVE"`, executor QA statuses are `"passed"`, iteration is `"passed"` with `fullRerun: true`, every evidence field is non-empty, and every blockers array is empty. `COMMENT`, `WATCH`, `REQUEST CHANGES`, `BLOCK`, missing evidence, or non-empty blockers are non-clean.
145
- 5. If review is non-clean, do **not** call `update_goal`. Record durable blocker work instead:
143
+ 5. If review is non-clean, do **not** call `goal({"op":"complete"})`. Record durable blocker work instead:
146
144
 
147
145
  1. Run targeted implementation verification for the story.
148
146
  2. Delegate an `architect` review covering all three lanes:
@@ -150,12 +148,12 @@ An ultragoal story cannot be checkpointed `complete` until the active agent has
150
148
  - product-side: user-visible behavior, acceptance criteria, edge cases, regressions.
151
149
  - code-side: maintainability, tests, integration points, and unsafe shortcuts.
152
150
  3. Delegate an `executor` QA/red-team lane to build and run the e2e/read-teaming QA suite appropriate for the story. This lane must try to break the change, not just confirm the happy path.
153
- 4. If any lane finds an issue, do **not** checkpoint `complete` and do **not** call `update_goal`. Record durable blocker work instead:
151
+ 4. If any lane finds an issue, do **not** checkpoint `complete` and do **not** call `goal({"op":"complete"})`. Record durable blocker work instead:
154
152
  ```sh
155
- gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve verification blockers" --objective "<blocker-resolution objective>" --evidence "<architect/executor findings>" --gjc-goal-json <active-get-goal-json-or-path>
153
+ gjc ultragoal record-review-blockers --goal-id <id> --title "Resolve verification blockers" --objective "<blocker-resolution objective>" --evidence "<architect/executor findings>" --gjc-goal-json <active-goal-get-json-or-path>
156
154
  ```
157
155
  5. Complete or steer through the blocker story, then rerun the full blocking verification loop. Repeat until all verifier lanes are clean.
158
- 6. Only after the loop is clean, checkpoint the story as complete with a structured quality gate and a fresh active `get_goal` snapshot. The checkpoint creates a receipt; `goals.json.status` alone is not proof. In aggregate mode, the final aggregate receipt must exist before `update_goal({"status":"complete"})` is allowed.
156
+ 6. Only after the loop is clean, checkpoint the story as complete with a structured quality gate and a fresh active `goal({"op":"get"})` snapshot. The checkpoint creates a receipt; `goals.json.status` alone is not proof. In aggregate mode, the final aggregate receipt must exist before `goal({"op":"complete"})` is allowed.
159
157
 
160
158
  The native `checkpoint --status complete` command rejects missing or shallow gates. `--quality-gate-json` must include:
161
159
 
@@ -194,13 +192,23 @@ Receipts are freshness-scoped:
194
192
  - Normal later `goal_started` or clean receipt-backed `goal_checkpointed` events for other goals do not stale older per-goal receipts.
195
193
  - Appending required goals or changing final required-goal state stales final aggregate receipts. Final aggregate completion requires a fresh final aggregate receipt proving no incomplete, blocked, or `review_blocked` required goals remain.
196
194
 
195
+ ## Handoff back to planning
196
+
197
+ When the aggregate ultragoal is complete OR the user requests return to planning/clarification, mark ultragoal ready for handoff so the skill tool's chain guard permits the backward transition:
198
+
199
+ ```
200
+ gjc state ultragoal write --input '{"current_phase":"handoff"}' --json
201
+ ```
202
+
203
+ The skill tool then dispatches `/skill:ralplan` or `/skill:deep-interview` same-turn and runs `gjc state ultragoal handoff --to <ralplan|deep-interview> --json` in-process to atomically demote ultragoal, promote the callee, and sync both `skill-active-state.json` files. You do not need to run the handoff verb yourself.
204
+
197
205
  ## Constraints
198
206
 
199
207
  - The shell command cannot directly invoke interactive `/goal`; it emits a model-facing handoff for the active GJC agent.
200
- - Ultragoal intentionally does not invoke `/goal clear` or hidden `thread/goal/clear`; use only the named goal-tool surface: `get_goal`, `create_goal`, and `update_goal`.
208
+ - Ultragoal intentionally does not invoke `/goal clear` or hidden `thread/goal/clear`; use only the unified goal-tool surface: `goal({"op":"get"})`, `goal({"op":"create"})`, and `goal({"op":"complete"})`.
201
209
  - After a completed aggregate ultragoal run, clear the goal manually with `/goal clear` before starting another ultragoal run in the same session/thread.
202
- - Never call `create_goal` when `get_goal` reports a different active goal.
203
- - Never call `update_goal` unless the aggregate run or legacy per-story goal is actually complete.
204
- - In aggregate mode, intermediate and final story checkpoints require a matching `active` GJC goal snapshot; the final story checkpoint creates the final aggregate receipt before `update_goal({"status":"complete"})` may reconcile the inline goal state.
205
- - Completion checkpoints require read-only goal snapshot reconciliation: pass fresh `get_goal` JSON/path with `--gjc-goal-json`; shell commands and hooks must not mutate goal state.
210
+ - Never call `goal({"op":"create"})` when `goal({"op":"get"})` reports a different active goal.
211
+ - Never call `goal({"op":"complete"})` unless the aggregate run or legacy per-story goal is actually complete.
212
+ - In aggregate mode, intermediate and final story checkpoints require a matching `active` GJC goal snapshot; the final story checkpoint creates the final aggregate receipt before `goal({"op":"complete"})` may reconcile the inline goal state.
213
+ - Completion checkpoints require read-only goal snapshot reconciliation: pass fresh `goal({"op":"get"})` JSON/path with `--gjc-goal-json`; shell commands and hooks must not mutate goal state.
206
214
  - Treat `ledger.jsonl` as the durable audit trail; checkpoint after every success or failure.
@@ -8,6 +8,7 @@ import {
8
8
  getConfigDirName,
9
9
  getPluginsDir,
10
10
  getProjectDir,
11
+ logger,
11
12
  parseFrontmatter,
12
13
  tryParseJson,
13
14
  } from "@gajae-code/utils";
@@ -16,6 +17,7 @@ import { invalidate as invalidateFsCache, readDirEntries, readFile } from "../ca
16
17
  import { parseRuleConditionAndScope, type Rule, type RuleFrontmatter } from "../capability/rule";
17
18
  import type { Skill, SkillFrontmatter } from "../capability/skill";
18
19
  import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
20
+ import type { ForkContextPolicy } from "../task/types";
19
21
  import { parseThinkingLevel } from "../thinking";
20
22
 
21
23
  import { buildPluginDirRoot } from "./plugin-dir-roots";
@@ -214,6 +216,7 @@ export interface ParsedAgentFields {
214
216
  autoloadSkills?: string[];
215
217
  blocking?: boolean;
216
218
  hide?: boolean;
219
+ forkContext?: ForkContextPolicy;
217
220
  }
218
221
 
219
222
  /**
@@ -267,10 +270,30 @@ export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAg
267
270
  const model = parseModelList(frontmatter.model);
268
271
  const blocking = parseBoolean(frontmatter.blocking);
269
272
  const hide = parseBoolean(frontmatter.hide);
273
+ const forkContext = parseForkContextPolicy(frontmatter.forkContext);
270
274
  const autoloadSkills = parseArrayOrCSV(frontmatter.autoloadSkills)
271
275
  ?.map(s => s.trim())
272
276
  .filter(Boolean);
273
- return { name, description, tools, spawns, model, output, thinkingLevel, blocking, autoloadSkills, hide };
277
+ return {
278
+ name,
279
+ description,
280
+ tools,
281
+ spawns,
282
+ model,
283
+ output,
284
+ thinkingLevel,
285
+ blocking,
286
+ autoloadSkills,
287
+ hide,
288
+ forkContext,
289
+ };
290
+ }
291
+
292
+ function parseForkContextPolicy(value: unknown): ForkContextPolicy | undefined {
293
+ if (value === undefined) return undefined;
294
+ if (value === "forbidden" || value === "allowed") return value;
295
+ logger.warn("Invalid agent forkContext frontmatter; expected 'allowed' or 'forbidden', ignoring", { value });
296
+ return undefined;
274
297
  }
275
298
 
276
299
  async function globIf(
@@ -431,7 +431,7 @@ if "__gjc_prelude_loaded__" not in globals():
431
431
  return data.get("value")
432
432
 
433
433
  class _ToolProxy:
434
- """`tool.<name>(args)` proxy mirroring the JS runtime bridge."""
434
+ """`tool.<name>(args)` proxy mirroring the JS session tool API."""
435
435
 
436
436
  __slots__ = ("_base", "_token", "_session")
437
437
 
@@ -110,6 +110,12 @@ export interface ExtensionUIDialogOptions {
110
110
  onExternalEditor?: () => void;
111
111
  /** Optional footer hint text rendered by interactive selector */
112
112
  helpText?: string;
113
+ /**
114
+ * For interactive TUI select dialogs, render the focused option across
115
+ * multiple rows instead of truncating it. This is a select-only rendering
116
+ * hint; non-TUI bridges (RPC, ACP) drop it and do not serialize it.
117
+ */
118
+ wrapFocused?: boolean;
113
119
  }
114
120
 
115
121
  /** Raw terminal input listener for extensions. */