@jenga-ai/agent 1.3.0 → 3.0.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 (175) hide show
  1. package/README.md +93 -256
  2. package/agents/developer.md +9 -8
  3. package/agents/scrum-master.md +57 -23
  4. package/agents/tester.md +51 -5
  5. package/hooks/on_session_end.sh +13 -1
  6. package/lib/generate-agent-context.js +18 -1
  7. package/lib/generate-copilot-instructions.js +18 -1
  8. package/lib/generate-skill-allow-list.js +197 -0
  9. package/lib/skill-allow-list.json +42 -0
  10. package/package.json +17 -13
  11. package/scripts/apply-j-prefix.sh +243 -0
  12. package/scripts/consume-context-digest.sh +103 -0
  13. package/scripts/generate-j-alias.sh +333 -0
  14. package/scripts/postinstall.js +25 -0
  15. package/scripts/sweep-stale-context-digests.sh +132 -0
  16. package/scripts/validate-board.sh +5 -0
  17. package/scripts/write-context-digest.sh +230 -0
  18. package/skills/{brainstorm → j-brainstorm}/SKILL.md +9 -2
  19. package/skills/{btw → j-btw}/SKILL.md +9 -2
  20. package/skills/{clearify → j-clearify}/SKILL.md +9 -2
  21. package/skills/{close-story → j-close-story}/SKILL.md +92 -13
  22. package/skills/j-close-story/scripts/check-privatized.sh +345 -0
  23. package/skills/{close-story → j-close-story}/scripts/check-story-closeable.sh +1 -1
  24. package/skills/{close-story → j-close-story}/scripts/extract-task-diff-stats.sh +1 -1
  25. package/skills/{commit → j-commit}/SKILL.md +9 -2
  26. package/skills/j-continue/SKILL.md +36 -0
  27. package/skills/{deep-dive → j-deep-dive}/SKILL.md +9 -8
  28. package/skills/{dev-done → j-dev-done}/SKILL.md +11 -4
  29. package/skills/{dev-done → j-dev-done}/scripts/classify-commit-outcome.sh +4 -4
  30. package/skills/{distribute → j-distribute}/SKILL.md +17 -10
  31. package/skills/{distribute → j-distribute}/scripts/distribute-changes.sh +1 -1
  32. package/skills/{do → j-do}/SKILL.md +111 -14
  33. package/skills/j-doc/README.md +155 -0
  34. package/skills/{doc → j-doc}/SKILL.md +55 -18
  35. package/skills/j-doc/authoring-notes.md +72 -0
  36. package/skills/j-doc/scripts/resolve_last_update.py +149 -0
  37. package/skills/{doc-sync → j-doc-sync}/SKILL.md +9 -2
  38. package/skills/{dooo → j-dooo}/SKILL.md +9 -2
  39. package/skills/j-error/SKILL.md +36 -0
  40. package/skills/{evaluate → j-evaluate}/SKILL.md +9 -2
  41. package/skills/j-examplify/SKILL.md +49 -0
  42. package/skills/{help → j-help}/SKILL.md +9 -2
  43. package/skills/{idea → j-idea}/SKILL.md +10 -3
  44. package/skills/{idea → j-idea}/assets/idea_handoff_template.md +1 -1
  45. package/skills/{improve → j-improve}/SKILL.md +9 -2
  46. package/skills/{init → j-init}/SKILL.md +21 -8
  47. package/skills/j-init/assets/scope-thresholds_template.json +7 -0
  48. package/skills/j-jbp/SKILL.md +32 -0
  49. package/skills/j-lgtm/SKILL.md +28 -0
  50. package/skills/{pi-plan → j-pi-plan}/SKILL.md +10 -3
  51. package/skills/{proceed → j-proceed}/SKILL.md +9 -2
  52. package/skills/{publish → j-publish}/SKILL.md +47 -40
  53. package/skills/{publish → j-publish}/adapters/droplet.md +1 -1
  54. package/skills/{publish → j-publish}/adapters/mobile-ios.md +3 -3
  55. package/skills/{publish → j-publish}/adapters/npm-ci.md +29 -7
  56. package/skills/{publish → j-publish}/adapters/npm.md +8 -8
  57. package/skills/{publish → j-publish}/assets/ci-contract.md +2 -2
  58. package/skills/{publish → j-publish}/schemas/publish.schema.json +1 -1
  59. package/skills/{publish → j-publish}/scripts/npm_ci_pipeline.sh +21 -1
  60. package/skills/{publish → j-publish}/scripts/npm_stage_inspect.sh +34 -1
  61. package/skills/{publish → j-publish}/scripts/npm_stage_pipeline.sh +9 -4
  62. package/skills/{publish → j-publish}/scripts/publish_deploy.sh +4 -4
  63. package/skills/{publish → j-publish}/scripts/validate_npm_stage_env.sh +1 -1
  64. package/skills/{publish → j-publish}/wizards/droplet.md +1 -1
  65. package/skills/{publish → j-publish}/wizards/mobile-ios.md +1 -1
  66. package/skills/{publish → j-publish}/wizards/npm-ci.md +1 -1
  67. package/skills/{publish → j-publish}/wizards/npm.md +1 -1
  68. package/skills/{reconcile → j-reconcile}/SKILL.md +12 -5
  69. package/skills/{reconcile → j-reconcile}/scripts/detect-unlinked-code.sh +2 -2
  70. package/skills/{reconcile → j-reconcile}/scripts/resolve-reconcile-scope.sh +3 -3
  71. package/skills/{reconcile-origin → j-reconcile-origin}/SKILL.md +13 -6
  72. package/skills/{redo → j-redo}/SKILL.md +9 -2
  73. package/skills/{skillify → j-skillify}/SKILL.md +10 -3
  74. package/skills/{spinoff → j-spinoff}/SKILL.md +9 -2
  75. package/skills/{status → j-status}/SKILL.md +9 -2
  76. package/skills/j-todo/SKILL.md +92 -0
  77. package/skills/{todo → j-todo}/assets/todo_handoff_template.md +1 -1
  78. package/skills/j-todo/scripts/add_trivial_task.sh +216 -0
  79. package/skills/j-todo/scripts/update_story_tasks.py +87 -0
  80. package/skills/{uncharted → j-uncharted}/SKILL.md +35 -28
  81. package/skills/{uncharted → j-uncharted}/assets/UNDERSTANDING_DOC_TEMPLATE.md +2 -2
  82. package/skills/{uncharted → j-uncharted}/scripts/detect-dependencies.sh +1 -1
  83. package/skills/{uncharted → j-uncharted}/scripts/detect-tests.sh +1 -1
  84. package/skills/{uncharted → j-uncharted}/scripts/directory-triage.sh +3 -3
  85. package/skills/{uncharted → j-uncharted}/scripts/elicitation-state.sh +3 -3
  86. package/skills/{uncharted → j-uncharted}/scripts/enumerate-target.sh +1 -1
  87. package/skills/{uncharted → j-uncharted}/scripts/import-source.sh +1 -1
  88. package/skills/{uncharted → j-uncharted}/scripts/inspect-provenance.sh +1 -1
  89. package/skills/{uncharted → j-uncharted}/scripts/resolve-segment-target.sh +5 -5
  90. package/skills/{uncharted → j-uncharted}/scripts/run-engine.sh +1 -1
  91. package/skills/{uncharted → j-uncharted}/scripts/validate-proposed-items.sh +2 -2
  92. package/skills/{uncharted → j-uncharted}/scripts/write-backfilled-epics.sh +1 -1
  93. package/skills/j-wtf/SKILL.md +27 -0
  94. package/skills/jenga/SKILL.md +1 -1
  95. package/skills/jenga/scripts/render-confirmation.sh +55 -18
  96. package/skills/jenga-permission-level/SKILL.md +1 -1
  97. package/templates/SCRUM_BOARD_SCHEMA.md +33 -2
  98. package/templates/agent-context.md.tpl +32 -9
  99. package/templates/copilot-instructions.md.tpl +66 -11
  100. package/skills/continue/SKILL.md +0 -29
  101. package/skills/error/SKILL.md +0 -29
  102. package/skills/examplify/SKILL.md +0 -42
  103. package/skills/init/assets/scope-thresholds_template.json +0 -7
  104. package/skills/jbp/SKILL.md +0 -25
  105. package/skills/lgtm/SKILL.md +0 -21
  106. package/skills/todo/SKILL.md +0 -48
  107. package/skills/wtf/SKILL.md +0 -20
  108. /package/skills/{close-story → j-close-story}/scripts/compute-scope-divergence.sh +0 -0
  109. /package/skills/{close-story → j-close-story}/scripts/extract-diff-stats.sh +0 -0
  110. /package/skills/{close-story → j-close-story}/scripts/update-task-frontmatter.sh +0 -0
  111. /package/skills/{commit → j-commit}/assets/user_instructions_template.md +0 -0
  112. /package/skills/{distribute → j-distribute}/CONFIG_SCHEMA.md +0 -0
  113. /package/skills/{distribute → j-distribute}/scripts/check-version.sh +0 -0
  114. /package/skills/{distribute → j-distribute}/scripts/commit-version-bump.sh +0 -0
  115. /package/skills/{do → j-do}/assets/intent-vs-diff-prompt.md +0 -0
  116. /package/skills/{do → j-do}/assets/sender_template.json +0 -0
  117. /package/skills/{doc → j-doc}/assets/path-objectives.yaml +0 -0
  118. /package/skills/{doc-sync → j-doc-sync}/assets/default_excludes.txt +0 -0
  119. /package/skills/{doc-sync → j-doc-sync}/assets/doc_targets.md +0 -0
  120. /package/skills/{evaluate → j-evaluate}/assets/evaluation_invokation_template.yml +0 -0
  121. /package/skills/{evaluate → j-evaluate}/assets/evaluation_rapport_template.md +0 -0
  122. /package/skills/{idea → j-idea}/assets/idea_template.md +0 -0
  123. /package/skills/{init → j-init}/assets/.gitignore_template +0 -0
  124. /package/skills/{init → j-init}/assets/PROJECT_SUMMARY_template.md +0 -0
  125. /package/skills/{init → j-init}/assets/directory_structure.txt +0 -0
  126. /package/skills/{init → j-init}/assets/strategy_stub_template.md +0 -0
  127. /package/skills/{init → j-init}/assets/test-config_template.json +0 -0
  128. /package/skills/{init → j-init}/assets/workflow_template.json +0 -0
  129. /package/skills/{init → j-init}/scripts/apply-project-visibility.sh +0 -0
  130. /package/skills/{init → j-init}/scripts/detect-existing-codebase.sh +0 -0
  131. /package/skills/{init → j-init}/scripts/init.sh +0 -0
  132. /package/skills/{pi-plan → j-pi-plan}/assets/epic.json +0 -0
  133. /package/skills/{pi-plan → j-pi-plan}/assets/story_template.md +0 -0
  134. /package/skills/{publish → j-publish}/assets/ExportOptions.plist.template +0 -0
  135. /package/skills/{publish → j-publish}/assets/ownership-matrix.md +0 -0
  136. /package/skills/{publish → j-publish}/assets/publish.example.json +0 -0
  137. /package/skills/{publish → j-publish}/assets/publish.example.npm-ci.json +0 -0
  138. /package/skills/{publish → j-publish}/assets/publish.example.npm.json +0 -0
  139. /package/skills/{publish → j-publish}/assets/secrets-guide.md +0 -0
  140. /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-minimal.json +0 -0
  141. /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-with-empty-secrets.json +0 -0
  142. /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-with-workflow-path.json +0 -0
  143. /package/skills/{publish → j-publish}/scripts/check_target_config.sh +0 -0
  144. /package/skills/{publish → j-publish}/scripts/droplet_pipeline.sh +0 -0
  145. /package/skills/{publish → j-publish}/scripts/finalize_changelog.sh +0 -0
  146. /package/skills/{publish → j-publish}/scripts/generate_release_notes.sh +0 -0
  147. /package/skills/{publish → j-publish}/scripts/ios_pipeline.sh +0 -0
  148. /package/skills/{publish → j-publish}/scripts/npm_pipeline.sh +0 -0
  149. /package/skills/{publish → j-publish}/scripts/publish_common.sh +0 -0
  150. /package/skills/{publish → j-publish}/scripts/reconcile_tags.sh +0 -0
  151. /package/skills/{publish → j-publish}/scripts/run_gates.sh +0 -0
  152. /package/skills/{publish → j-publish}/scripts/setup_wizard.sh +0 -0
  153. /package/skills/{publish → j-publish}/scripts/show_history.sh +0 -0
  154. /package/skills/{publish → j-publish}/scripts/suggest_semver_bump.sh +0 -0
  155. /package/skills/{publish → j-publish}/scripts/validate_config.sh +0 -0
  156. /package/skills/{publish → j-publish}/scripts/validate_droplet_env.sh +0 -0
  157. /package/skills/{publish → j-publish}/scripts/validate_ios_env.sh +0 -0
  158. /package/skills/{publish → j-publish}/scripts/validate_npm_ci_env.sh +0 -0
  159. /package/skills/{publish → j-publish}/scripts/validate_npm_env.sh +0 -0
  160. /package/skills/{publish → j-publish}/scripts/write_ledger_entry.sh +0 -0
  161. /package/skills/{reconcile → j-reconcile}/assets/report_format.md +0 -0
  162. /package/skills/{reconcile-origin → j-reconcile-origin}/scripts/reconcile-origin.sh +0 -0
  163. /package/skills/{skillify → j-skillify}/assets/init-new/SKILL.md +0 -0
  164. /package/skills/{skillify → j-skillify}/assets/init-new/assets/.gitignore_template +0 -0
  165. /package/skills/{skillify → j-skillify}/assets/init-new/assets/PROJECT_SUMMARY_template.md +0 -0
  166. /package/skills/{skillify → j-skillify}/assets/init-new/assets/directory_structure.txt +0 -0
  167. /package/skills/{skillify → j-skillify}/assets/init-new/assets/test-config_template.json +0 -0
  168. /package/skills/{skillify → j-skillify}/assets/init-new/assets/workflow_template.json +0 -0
  169. /package/skills/{skillify → j-skillify}/assets/init-new/scripts/init.sh +0 -0
  170. /package/skills/{skillify → j-skillify}/assets/init-old/SKILL.md +0 -0
  171. /package/skills/{status → j-status}/assets/output_format.md +0 -0
  172. /package/skills/{todo → j-todo}/assets/todo_template.md +0 -0
  173. /package/skills/{uncharted → j-uncharted}/assets/SEGMENT_PROPOSAL_TEMPLATE.md +0 -0
  174. /package/skills/{uncharted → j-uncharted}/scripts/apply-subsystem-cap.sh +0 -0
  175. /package/skills/{uncharted → j-uncharted}/scripts/discover-subsystems.sh +0 -0
@@ -1,12 +1,19 @@
1
1
  ---
2
- name: reconcile
3
- description: Reconcile the scrum board with actual implementation state. Cross-checks every task's board status against git history and worktrees, merges orphaned worktree branches, demotes unimplemented "Done" items, promotes secretly-implemented items, flags code with no board provenance and offers /uncharted segment for it, and cleans stale entries from todo.md. Use when the board feels out of sync, after a big merge session, when tasks were completed outside the normal workflow, or when todo.md has grown stale. Trigger on phrases like "sync the board", "clean up the board", "reconcile", "board is out of date", "todo is stale", or "check what's really done".
2
+ name: j.reconcile
3
+ description: Polyfill alias of the reconcile skill under a collision-safe directory name. Identical behavior to /reconcile — Reconcile the scrum board with actual implementation state. Cross-checks every task's board status against git history and worktrees, merges orphaned worktree branches, demotes unimplemented "Done" items, promotes secretly-implemented items, flags code with no board provenance and offers /uncharted segment for it, and cleans stale entries from todo.md. Use when the board feels out of sync, after a big merge session, when tasks were completed outside the normal workflow, or when todo.md has grown stale. Trigger on phrases like "sync the board", "clean up the board", "reconcile", "board is out of date", "todo is stale", or "check what's really done". Use when the bare /reconcile form is shadowed by another tool's own built-in command of the same name.
4
4
  metadata:
5
5
  prefered_agent: scrum-master
6
+ keywords:
7
+ - j-reconcile
8
+ - polyfill
6
9
  ---
7
10
 
8
11
  # Reconcile — Board ↔ Code Synchronisation
9
12
 
13
+ This skill is a literal-directory-name duplicate of `skills/reconcile/`. It exists so that `/j-reconcile` (and `j.j-reconcile`) give a guaranteed-unshadowed way to reach the same flow as `/reconcile`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/reconcile` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
14
+
15
+ This file is generated/synced by `scripts/generate-j-alias.sh reconcile` from `skills/reconcile/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
16
+
10
17
  Walks the full board (epics → stories → tasks), verifies each item's status against what actually exists in git, and fixes any drift. Also cleans `project/todo.md` of entries that are already done. Then runs the same check in reverse — code that exists with no board item and no EST-tagged commit behind it — and offers `/uncharted segment` for what it finds.
11
18
 
12
19
  ## Scope argument
@@ -35,7 +42,7 @@ Omitting the argument entirely keeps today's full-board behavior completely unch
35
42
  phase below.
36
43
 
37
44
  Scope resolution itself is deterministic and handled entirely by
38
- `skills/reconcile/scripts/resolve-reconcile-scope.sh` (see Phase 0 immediately below) — this skill
45
+ `skills/j-reconcile/scripts/resolve-reconcile-scope.sh` (see Phase 0 immediately below) — this skill
39
46
  only interprets that script's output; it does not re-parse scope arguments or re-derive range
40
47
  expansion.
41
48
 
@@ -50,7 +57,7 @@ Before touching anything else, resolve the scope argument (if any — see "Scope
50
57
  into a concrete set of epic/story/task ids:
51
58
 
52
59
  ```bash
53
- skills/reconcile/scripts/resolve-reconcile-scope.sh <scope-argument>
60
+ skills/j-reconcile/scripts/resolve-reconcile-scope.sh <scope-argument>
54
61
  ```
55
62
 
56
63
  Omit `<scope-argument>` entirely for an unscoped, full-board run (the script's own no-argument
@@ -176,7 +183,7 @@ Phases 2 and 3 ask "does this board item exist in the code?". This phase asks th
176
183
  Run:
177
184
 
178
185
  ```bash
179
- skills/reconcile/scripts/detect-unlinked-code.sh
186
+ skills/j-reconcile/scripts/detect-unlinked-code.sh
180
187
  ```
181
188
 
182
189
  It emits a single JSON object and exits `0` whether or not it finds anything; read
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
  # ---------------------------------------------------------------------------
3
- # skills/reconcile/scripts/detect-unlinked-code.sh
3
+ # skills/j-reconcile/scripts/detect-unlinked-code.sh
4
4
  #
5
5
  # The inverse half of `/reconcile`. The normal pass asks "does this board item
6
6
  # exist in the code?"; this asks "does this code exist on the board?" and finds
@@ -31,7 +31,7 @@
31
31
  # It scans, it classifies, it reports. It NEVER writes anything, never touches
32
32
  # the board, and never invokes `/uncharted`. Deciding which groups are worth
33
33
  # investigating and presenting the offer is agent judgement and lives in
34
- # `skills/reconcile/SKILL.md`.
34
+ # `skills/j-reconcile/SKILL.md`.
35
35
  #
36
36
  # ---------------------------------------------------------------------------
37
37
  # SIGNAL A IS BORROWED, NOT REBUILT
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env bash
2
2
  # ---------------------------------------------------------------------------
3
- # skills/reconcile/scripts/resolve-reconcile-scope.sh
3
+ # skills/j-reconcile/scripts/resolve-reconcile-scope.sh
4
4
  #
5
5
  # Deterministic scope-argument resolver backing `/reconcile`'s new scope
6
6
  # argument (story E17_S07). This script owns ALL scope-argument parsing and
7
- # id-range expansion for `/reconcile` — `skills/reconcile/SKILL.md` (wired in
7
+ # id-range expansion for `/reconcile` — `skills/j-reconcile/SKILL.md` (wired in
8
8
  # the sibling task E17_S07_T02) only interprets this script's structured
9
9
  # stdout output; it must not re-derive any parsing or resolution logic
10
10
  # inline.
@@ -124,7 +124,7 @@
124
124
  # "epic_ids": ["E12"],
125
125
  # "story_ids": ["E12_S03", "E12_S04", "E12_S05"],
126
126
  # "task_ids": ["E12_S03_T01", "..."],
127
- # "owned_path_hints": ["skills/reconcile/", "..."]
127
+ # "owned_path_hints": ["skills/j-reconcile/", "..."]
128
128
  # }
129
129
  #
130
130
  # scope_type "full" epic_ids/story_ids/task_ids are all EMPTY arrays.
@@ -1,19 +1,26 @@
1
1
  ---
2
- name: reconcile-origin
3
- description: Sync the current (or specified) branch with origin by rebasing local commits on top of the latest upstream state.
2
+ name: j.reconcile-origin
3
+ description: Polyfill alias of the reconcile-origin skill under a collision-safe directory name. Identical behavior to /reconcile-origin — Sync the current (or specified) branch with origin by rebasing local commits on top of the latest upstream state. Use when the bare /reconcile-origin form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - "sync branch"
6
6
  - "rebase origin"
7
7
  - "reconcile origin"
8
8
  - "pull rebase"
9
+ - j-reconcile-origin
10
+ - polyfill
9
11
  examples:
10
12
  - "sync my branch with origin"
11
13
  - "rebase local commits on top of origin"
12
14
  - "reconcile-origin feature/my-branch"
15
+ - "j-reconcile-origin"
13
16
  ---
14
17
 
15
18
  # Reconcile Origin
16
19
 
20
+ This skill is a literal-directory-name duplicate of `skills/reconcile-origin/`. It exists so that `/j-reconcile-origin` (and `j.j-reconcile-origin`) give a guaranteed-unshadowed way to reach the same flow as `/reconcile-origin`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/reconcile-origin` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
21
+
22
+ This file is generated/synced by `scripts/generate-j-alias.sh reconcile-origin` from `skills/reconcile-origin/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
23
+
17
24
  Use this skill to rebase local work on top of the latest `origin/<branch>` state without re-implementing git logic inline.
18
25
 
19
26
  ## Instructions
@@ -22,7 +29,7 @@ Use this skill to rebase local work on top of the latest `origin/<branch>` state
22
29
  - If the user passed an argument, use that branch name.
23
30
  - Otherwise, use the current branch name.
24
31
 
25
- 2. Invoke `.agents/skills/reconcile-origin/scripts/reconcile-origin.sh [<branch>]` and capture stdout.
32
+ 2. Invoke `.agents/skills/j-reconcile-origin/scripts/reconcile-origin.sh [<branch>]` and capture stdout.
26
33
  - Do not run any inline git commands in this skill — all git work is handled by the script.
27
34
  - The script handles dirty-worktree detection internally and returns `{"status":"error","code":"uncommitted_changes",...}` if the working tree is not clean.
28
35
 
@@ -38,7 +45,7 @@ Use this skill to rebase local work on top of the latest `origin/<branch>` state
38
45
  2. Cancel and inspect the branch setup manually
39
46
  3. Other (describe below)
40
47
 
41
- - If the user chooses option 1, invoke `.agents/skills/reconcile-origin/scripts/reconcile-origin.sh <branch> --create-tracking`.
48
+ - If the user chooses option 1, invoke `.agents/skills/j-reconcile-origin/scripts/reconcile-origin.sh <branch> --create-tracking`.
42
49
  - If `remote_exists` is `false`, explain that neither a local branch nor `origin/<branch>` was found and stop.
43
50
  - `conflict`
44
51
  - Present one structured conflict rapport per item in `conflicts`.
@@ -55,7 +62,7 @@ Use this skill to rebase local work on top of the latest `origin/<branch>` state
55
62
  3. Handle it later — leave annotated conflict markers in the file and continue the scripted flow
56
63
  4. Other (describe below)
57
64
 
58
- - If the user chooses “Handle it later”, invoke `.agents/skills/reconcile-origin/scripts/reconcile-origin.sh <branch> --handle-later <file>` for the selected conflict file.
65
+ - If the user chooses “Handle it later”, invoke `.agents/skills/j-reconcile-origin/scripts/reconcile-origin.sh <branch> --handle-later <file>` for the selected conflict file.
59
66
  - `handled_later`
60
67
  - Confirm that the selected file was annotated for later resolution.
61
68
  - Tell the user the conflict markers were intentionally preserved with a `# RECONCILE-ORIGIN CONFLICT:` note.
@@ -71,5 +78,5 @@ Use this skill to rebase local work on top of the latest `origin/<branch>` state
71
78
 
72
79
  ## Guard Rails
73
80
 
74
- - All git work must go through `.agents/skills/reconcile-origin/scripts/reconcile-origin.sh`.
81
+ - All git work must go through `.agents/skills/j-reconcile-origin/scripts/reconcile-origin.sh`.
75
82
  - Do not inline fetch, checkout, pull, merge, rebase, or status commands in this skill body.
@@ -1,21 +1,28 @@
1
1
  ---
2
- name: redo
3
- description: Redo parts or entire previous implementations identified by a commit SHA or an Epic/Story number (e.g. E01, E02_S03). Expects an identifier and a description of what to redo and why. Use when the user wants to revisit, rework, or rewrite previously completed work, including updating all affected documentation.
2
+ name: j.redo
3
+ description: Polyfill alias of the redo skill under a collision-safe directory name. Identical behavior to /redo — Redo parts or entire previous implementations identified by a commit SHA or an Epic/Story number (e.g. E01, E02_S03). Expects an identifier and a description of what to redo and why. Use when the user wants to revisit, rework, or rewrite previously completed work, including updating all affected documentation. Use when the bare /redo form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - redo
6
6
  - rework
7
7
  - rewrite
8
8
  - revisit
9
9
  - redo task
10
+ - j-redo
11
+ - polyfill
10
12
  examples:
11
13
  - "redo the login implementation"
12
14
  - "rewrite story E02_S01"
15
+ - "j-redo"
13
16
  metadata:
14
17
  prefered_agent: scrum-master
15
18
  ---
16
19
 
17
20
  # Redo — Rework a Previous Implementation
18
21
 
22
+ This skill is a literal-directory-name duplicate of `skills/redo/`. It exists so that `/j-redo` (and `j.j-redo`) give a guaranteed-unshadowed way to reach the same flow as `/redo`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/redo` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
23
+
24
+ This file is generated/synced by `scripts/generate-j-alias.sh redo` from `skills/redo/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
25
+
19
26
  ## Input Format
20
27
 
21
28
  ```
@@ -1,10 +1,17 @@
1
1
  ---
2
- name: skillify
3
- description: Refactor one or more existing skills into a cleaner, more maintainable structure — extracting hardcoded content into asset files, offloading deterministic steps into scripts, and reorganizing the skill body to reflect the leaner result. Use this whenever the user wants to clean up, improve, or restructure an existing skill, mentions that a skill has hardcoded content that could be templated, or asks to "skillify", "refactor", or "tidy up" a skill. Trigger even if the user just pastes a skill and says something like "can we make this better?".
2
+ name: j.skillify
3
+ description: Polyfill alias of the skillify skill under a collision-safe directory name. Identical behavior to /skillify — Refactor one or more existing skills into a cleaner, more maintainable structure — extracting hardcoded content into asset files, offloading deterministic steps into scripts, and reorganizing the skill body to reflect the leaner result. Use this whenever the user wants to clean up, improve, or restructure an existing skill, mentions that a skill has hardcoded content that could be templated, or asks to "skillify", "refactor", or "tidy up" a skill. Trigger even if the user just pastes a skill and says something like "can we make this better?". Use when the bare /skillify form is shadowed by another tool's own built-in command of the same name.
4
+ keywords:
5
+ - j-skillify
6
+ - polyfill
4
7
  ---
5
8
 
6
9
  # Skillify — Refactor a Skill into a Cleaner Structure
7
10
 
11
+ This skill is a literal-directory-name duplicate of `skills/skillify/`. It exists so that `/j-skillify` (and `j.j-skillify`) give a guaranteed-unshadowed way to reach the same flow as `/skillify`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/skillify` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
12
+
13
+ This file is generated/synced by `scripts/generate-j-alias.sh skillify` from `skills/skillify/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
14
+
8
15
  ## What this skill does
9
16
 
10
17
  Takes one or more existing skills and refactors them by:
@@ -65,4 +72,4 @@ The rewritten SKILL.md should:
65
72
  - `assets/init-old/SKILL.md` — The init skill before refactoring (hardcoded heredocs, inline JSON, hardcoded directory list)
66
73
  - `assets/init-new/SKILL.md` — The init skill after refactoring (all content in assets, steps delegated to `init.sh`)
67
74
 
68
- Read these when you need a concrete example of the before/after pattern.
75
+ Read these when you need a concrete example of the before/after pattern.
@@ -1,21 +1,28 @@
1
1
  ---
2
- name: spinoff
3
- description: Capture a diverging topic mid-conversation. Collects context and a mandatory origin, optionally runs /brainstorm for prerequisites, saves an /idea entry, and returns focus to the primary thread.
2
+ name: j.spinoff
3
+ description: Polyfill alias of the spinoff skill under a collision-safe directory name. Identical behavior to /spinoff — Capture a diverging topic mid-conversation. Collects context and a mandatory origin, optionally runs /brainstorm for prerequisites, saves an /idea entry, and returns focus to the primary thread. Use when the bare /spinoff form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - spinoff
6
6
  - diverge
7
7
  - side topic
8
8
  - capture topic
9
9
  - new thread
10
+ - j-spinoff
11
+ - polyfill
10
12
  examples:
11
13
  - "let's spinoff this idea"
12
14
  - "capture this as a separate thread"
15
+ - "j-spinoff"
13
16
  metadata:
14
17
  prefered_agent: scrum-master
15
18
  ---
16
19
 
17
20
  # Spinoff — Capture a Diverging Topic
18
21
 
22
+ This skill is a literal-directory-name duplicate of `skills/spinoff/`. It exists so that `/j-spinoff` (and `j.j-spinoff`) give a guaranteed-unshadowed way to reach the same flow as `/spinoff`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/spinoff` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
23
+
24
+ This file is generated/synced by `scripts/generate-j-alias.sh spinoff` from `skills/spinoff/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
25
+
19
26
  ## Instructions
20
27
 
21
28
  1. **Identify the diverging topic** — Ask the user to confirm or briefly describe the diverging topic.
@@ -1,19 +1,26 @@
1
1
  ---
2
- name: status
3
- description: Print a human-readable summary of the entire scrum board — all epics, stories, and tasks with their statuses — plus any open rapports and unprocessed queue triggers. Use when you want a quick overview of project state without reading raw files.
2
+ name: j.status
3
+ description: Polyfill alias of the status skill under a collision-safe directory name. Identical behavior to /status — Print a human-readable summary of the entire scrum board — all epics, stories, and tasks with their statuses — plus any open rapports and unprocessed queue triggers. Use when you want a quick overview of project state without reading raw files. Use when the bare /status form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - status
6
6
  - board summary
7
7
  - overview
8
8
  - project state
9
9
  - what's done
10
+ - j-status
11
+ - polyfill
10
12
  examples:
11
13
  - "show me the project status"
12
14
  - "what's the state of the board?"
15
+ - "j-status"
13
16
  ---
14
17
 
15
18
  # Status — Board Overview
16
19
 
20
+ This skill is a literal-directory-name duplicate of `skills/status/`. It exists so that `/j-status` (and `j.j-status`) give a guaranteed-unshadowed way to reach the same flow as `/status`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/status` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
21
+
22
+ This file is generated/synced by `scripts/generate-j-alias.sh status` from `skills/status/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
23
+
17
24
  ## Instructions
18
25
 
19
26
  1. **Read `project/configs/workflow.json`** to confirm board paths. Fall back to `project/board/` if the file does not exist.
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: j.todo
3
+ description: Polyfill alias of the todo skill under a collision-safe directory name. Identical behavior to /todo — Add missions to the project todo list (project/todo.md), optionally linking them to epics and stories. Loops until the user is done, then optionally executes the list. Use when the bare /todo form is shadowed by another tool's own built-in command of the same name.
4
+ keywords:
5
+ - todo
6
+ - add task
7
+ - queue work
8
+ - backlog
9
+ - add to list
10
+ - j-todo
11
+ - polyfill
12
+ examples:
13
+ - "add this to the todo list"
14
+ - "queue this as a task"
15
+ - "j-todo"
16
+ metadata:
17
+ prefered_agent: scrum-master
18
+ ---
19
+
20
+ # Todo — Add Missions to the Todo List
21
+
22
+ This skill is a literal-directory-name duplicate of `skills/todo/`. It exists so that `/j-todo` (and `j.j-todo`) give a guaranteed-unshadowed way to reach the same flow as `/todo`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/todo` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
23
+
24
+ This file is generated/synced by `scripts/generate-j-alias.sh todo` from `skills/todo/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
25
+
26
+ ## `--trivial` Flag
27
+
28
+ **Syntax:** `/todo --trivial <description>` — optionally combined with the same `: <Epic no.>_<Story no.>` linkage syntax normal `/todo` entries use, e.g. `/todo --trivial Fix typo in error message: E12_S03`.
29
+
30
+ When `--trivial` is present, the mission is written as a **fully-formed task board file immediately** (not just a raw `todo.md` line deferred to `/do`'s own breakdown pass) with `execution_scope: inline` forced unconditionally — no threshold computation is consulted for the scope value itself. See step 4.5 below for the mechanics.
31
+
32
+ **Human-only override.** `--trivial` is invoked by a human typing `/todo --trivial ...` — it is never applied by the scrum-master to itself during autonomous story/epic breakdown elsewhere (e.g. `/jenga`'s Phase 0.5, or `/do`'s own scrum-master decomposition step in `skills/do/SKILL.md` step 3). Those paths keep using the normal heuristic-only `execution_scope` assignment documented in `agents/scrum-master.md`'s Execution Scope Assignment section, unmodified by this flag.
33
+
34
+ **Fallback on failure is out of scope here.** If a `--trivial`-forced inline run fails the smoke-harness or shows scope creep at dispatch time, `/do`'s own `--trivial` handling (a separate task, E32_S14_T02) is responsible for falling back to the full `task` pipeline — this skill only ever writes the initial forced-inline task.
35
+
36
+ ## Instructions
37
+
38
+ 1. **Ensure `project/todo.md` exists** — If it doesn't exist, it will be auto-created by `todo_manager.sh` — no manual action needed.
39
+
40
+ 2. **Ask the user about the mission:**
41
+ - Where do you want to do this?
42
+ - What would you like to do?
43
+ - What is the goal?
44
+ - (If `--trivial` was passed, these answers still apply — `--trivial` changes how the mission is written to the board in step 4.5, not what's asked here.)
45
+
46
+ 3. **Classify the mission** — Check if it fits into:
47
+ - An existing story
48
+ - A new story inside an existing Epic
49
+ - A new story inside a new Epic
50
+ - None of the above
51
+
52
+ **`--trivial` requires an existing (or, in this same step, newly-created) story to attach to.** It forces the scope of a single task, not a container — if the mission has no story yet, create it now via step 4 below exactly as normal, then continue to step 4.5. `--trivial` cannot be used for "None of the above."
53
+
54
+ 4. **Update project documentation** — Add the mission to the appropriate files under `project/board/epics/` and `project/board/stories/` if applicable.
55
+ - If the mission involves implementing or modifying a skill, apply the **Skill Implementation Principle — Scripts Over Inline Logic** (see `CLAUDE.md` / `AGENTS.md`): note in the story/task's acceptance criteria that deterministic, repeatable steps must be offloaded to scripts under `skills/<name>/scripts/` (or `scripts/`) rather than encoded as inline agent instructions in `SKILL.md`.
56
+ - If the user indicates the mission is high-risk, or explicitly asks to flag it, set an elevated caution tier directly on the story or task frontmatter: `crucial_level` (one of `advisory`, `gated`, `locked` — see `templates/SCRUM_BOARD_SCHEMA.md` for valid values and their meaning), `crucial_set_by: user`, and `crucial_note` capturing the user's stated reason. This user-initiated flag is written immediately — it does not require the confirm-before-write gate, which applies only to scrum-master-*proposed* caution tiers (a separate, heuristic-driven path).
57
+
58
+ 4.5. **If `--trivial` was passed, create the task now** (skip step 5 — this step writes the todo.md entry itself):
59
+
60
+ a. **Estimate the change**, using the same judgment `agents/scrum-master.md`'s Execution Scope Assignment heuristic applies: how many files will this mission likely touch, and roughly how many lines. This is a reasoning step, not a script step — do not guess wildly, but a rough, honest estimate is sufficient.
61
+
62
+ b. **Determine `computed_tier`** — what `execution_scope` the normal heuristic would have assigned to this estimate, purely for the audit trail (it is never written as the actual `execution_scope`, which is always forced to `inline`):
63
+ - Read `inline_max_files`, `inline_max_lines`, and `story_max_files` from `project/configs/scope-thresholds.json` at run time — never hardcode these numbers here.
64
+ - Apply `agents/scrum-master.md`'s `inline` / `story` / `task` heuristics (file count vs. `inline_max_files`, line estimate vs. `inline_max_lines`, contention and cross-cutting checks for `story`) to the estimate from (a). The result is `computed_tier` — one of `inline`, `task`, or `story` (never `epic` — the heuristic never autonomously computes `epic`).
65
+
66
+ c. **Run the helper script**, which handles everything mechanical — next task-ID assignment, writing the task board file with `execution_scope: inline` forced, registering the new task ID into the parent story's `tasks:` frontmatter list, and adding the `project/todo.md` entry using the full task ID (so `/do` routes straight into its Inline Execution Path with no redundant breakdown pass):
67
+ ```
68
+ bash skills/j-todo/scripts/add_trivial_task.sh \
69
+ --story <E##_S##> \
70
+ --title "<mission title>" \
71
+ --description "<mission description>" \
72
+ --criteria "<criterion 1>|<criterion 2>|..." \
73
+ --computed-tier <inline|task|story> \
74
+ --est-files <N> \
75
+ --est-lines <M> \
76
+ [--prerequisites "<text>"]
77
+ ```
78
+ The script writes `scope_rationale` in the form `"forced inline via --trivial; computed scope would have been '<computed_tier>' — estimated <N> files, ~<M> lines"` and sets `jenga_assigned: false` with a matching `override_justification`, so `/do` step 4.1's existing override-validation logs the override on dispatch — no separate acknowledgement step needed here.
79
+ On success the script prints the new task ID to stdout; on failure (e.g. the story doesn't exist yet, or `--computed-tier` is invalid) it exits non-zero with an explanatory message on stderr — surface that to the user rather than retrying blindly.
80
+ d. Continue to step 6 (skip step 5 — the script already added the `todo.md` entry).
81
+
82
+ 5. **Add to `project/todo.md`** by running (skip this step if step 4.5 already ran):
83
+ ```
84
+ bash scripts/todo_manager.sh add '<mission title>: <Epic no.>_<Story no.>'
85
+ ```
86
+ The epic and story reference is only required if the mission is assigned to one.
87
+
88
+ 6. **Ask the user**: "Add another todo" or "Done"?
89
+ - If **add another** — go back to step 2. (`--trivial` applies only to the mission it was passed with — it does not carry over to the next mission unless the user says `--trivial` again.)
90
+ - If **done** — ask if they want to execute the todo list.
91
+ - If **yes** — invoke the `/do` skill.
92
+ - If **no** — exit.
@@ -13,7 +13,7 @@
13
13
  <!-- PLACEHOLDER: what this todo is trying to achieve -->
14
14
 
15
15
  ## Affected Files or Scope
16
- <!-- PLACEHOLDER: which files, modules, or areas are involved, e.g. src/auth/, skills/todo/ -->
16
+ <!-- PLACEHOLDER: which files, modules, or areas are involved, e.g. src/auth/, skills/j-todo/ -->
17
17
 
18
18
  ## Intended Approach
19
19
  <!-- PLACEHOLDER: step-by-step or high-level approach to the work -->
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env bash
2
+ # skills/j-todo/scripts/add_trivial_task.sh
3
+ #
4
+ # Creates a fully-formed task board file for a `/todo --trivial` mission,
5
+ # forced to execution_scope: inline unconditionally, and registers it both
6
+ # in its parent story's tasks: frontmatter list and in project/todo.md.
7
+ #
8
+ # This script performs only the MECHANICAL half of --trivial: templating the
9
+ # task file, assigning the next task number, and wiring it into the board.
10
+ # The JUDGMENT half — estimating file/line counts and deciding what
11
+ # execution_scope the normal heuristic in agents/scrum-master.md would have
12
+ # assigned (computed_tier) — happens in the calling agent's instructions
13
+ # (skills/j-todo/SKILL.md), per the Skill Implementation Principle: a step that
14
+ # requires reasoning about branching logic, new dependencies, etc. does not
15
+ # belong in a script. This script never reads project/configs/scope-thresholds.json
16
+ # or recomputes computed_tier itself — it only records what it was told.
17
+ #
18
+ # Usage:
19
+ # add_trivial_task.sh --story <E##_S##> --title "<title>" \
20
+ # --description "<description>" --criteria "<c1>|<c2>|..." \
21
+ # --computed-tier <inline|task|story> --est-files <N> --est-lines <M> \
22
+ # [--prerequisites "<text>"]
23
+ #
24
+ # Requires an ALREADY-EXISTING parent story file (--trivial does not create
25
+ # stories or epics — resolve/create those first via the normal /todo flow).
26
+ #
27
+ # On success, prints the new task ID (e.g. E32_S14_T05) to stdout and exits 0.
28
+
29
+ set -euo pipefail
30
+
31
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
32
+ cd "$REPO_ROOT"
33
+
34
+ TASKS_DIR="project/board/tasks"
35
+ STORIES_DIR="project/board/stories"
36
+ UPDATE_STORY_SCRIPT="skills/j-todo/scripts/update_story_tasks.py"
37
+
38
+ story_id=""
39
+ title=""
40
+ description=""
41
+ criteria=""
42
+ computed_tier=""
43
+ est_files=""
44
+ est_lines=""
45
+ prerequisites="None."
46
+
47
+ usage() {
48
+ cat >&2 <<EOF
49
+ Usage: $0 --story <E##_S##> --title "<title>" --description "<description>" \\
50
+ --criteria "<c1>|<c2>|..." --computed-tier <inline|task|story> \\
51
+ --est-files <N> --est-lines <M> [--prerequisites "<text>"]
52
+ EOF
53
+ exit 1
54
+ }
55
+
56
+ while [ $# -gt 0 ]; do
57
+ case "$1" in
58
+ --story) story_id="$2"; shift 2 ;;
59
+ --title) title="$2"; shift 2 ;;
60
+ --description) description="$2"; shift 2 ;;
61
+ --criteria) criteria="$2"; shift 2 ;;
62
+ --computed-tier) computed_tier="$2"; shift 2 ;;
63
+ --est-files) est_files="$2"; shift 2 ;;
64
+ --est-lines) est_lines="$2"; shift 2 ;;
65
+ --prerequisites) prerequisites="$2"; shift 2 ;;
66
+ -h|--help) usage ;;
67
+ *) echo "Error: unknown argument '$1'" >&2; usage ;;
68
+ esac
69
+ done
70
+
71
+ for req_name in story_id title description criteria computed_tier est_files est_lines; do
72
+ if [ -z "${!req_name}" ]; then
73
+ echo "Error: --${req_name//_/-} is required" >&2
74
+ exit 1
75
+ fi
76
+ done
77
+
78
+ if ! [[ "$story_id" =~ ^E[0-9]+_S[0-9]+$ ]]; then
79
+ echo "Error: --story must look like E##_S## (got '$story_id')" >&2
80
+ exit 1
81
+ fi
82
+
83
+ case "$computed_tier" in
84
+ inline|task|story) ;;
85
+ *) echo "Error: --computed-tier must be one of: inline, task, story (got '$computed_tier')" >&2; exit 1 ;;
86
+ esac
87
+
88
+ case "$est_files" in
89
+ ''|*[!0-9]*) echo "Error: --est-files must be a non-negative integer (got '$est_files')" >&2; exit 1 ;;
90
+ esac
91
+ case "$est_lines" in
92
+ ''|*[!0-9]*) echo "Error: --est-lines must be a non-negative integer (got '$est_lines')" >&2; exit 1 ;;
93
+ esac
94
+
95
+ epic_id="${story_id%%_S*}"
96
+
97
+ # Locate the parent story file. --trivial requires it to already exist.
98
+ story_file=""
99
+ for f in "${STORIES_DIR}/${story_id}_"*.md; do
100
+ if [ -f "$f" ]; then
101
+ story_file="$f"
102
+ break
103
+ fi
104
+ done
105
+ if [ -z "$story_file" ]; then
106
+ echo "Error: no story file found for $story_id under $STORIES_DIR/. --trivial requires an already-resolved story — create it via the normal /todo flow first." >&2
107
+ exit 1
108
+ fi
109
+
110
+ if [ ! -f "$UPDATE_STORY_SCRIPT" ]; then
111
+ echo "Error: $UPDATE_STORY_SCRIPT not found." >&2
112
+ exit 1
113
+ fi
114
+
115
+ # Determine the next task number for this story by scanning existing task files.
116
+ max_num=0
117
+ shopt -s nullglob
118
+ for f in "${TASKS_DIR}/${story_id}_T"*.md; do
119
+ base="$(basename "$f")"
120
+ num="$(printf '%s' "$base" | sed -nE "s/^${story_id}_T([0-9]+)_.*/\1/p")"
121
+ if [ -n "$num" ]; then
122
+ num=$((10#$num))
123
+ if [ "$num" -gt "$max_num" ]; then
124
+ max_num=$num
125
+ fi
126
+ fi
127
+ done
128
+ shopt -u nullglob
129
+ next_num=$((max_num + 1))
130
+ next_num_padded="$(printf '%02d' "$next_num")"
131
+ task_id="${story_id}_T${next_num_padded}"
132
+
133
+ shopt -s nullglob
134
+ existing_matches=("${TASKS_DIR}/${task_id}_"*.md)
135
+ shopt -u nullglob
136
+ if [ "${#existing_matches[@]}" -gt 0 ]; then
137
+ echo "Error: a task file for $task_id already exists (ID collision). Aborting." >&2
138
+ exit 1
139
+ fi
140
+
141
+ # Slugify the title for the filename.
142
+ slug="$(printf '%s' "$title" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')"
143
+ slug="${slug:0:60}"
144
+ slug="${slug%-}"
145
+ if [ -z "$slug" ]; then
146
+ slug="trivial-task"
147
+ fi
148
+
149
+ today="$(date -u +%Y-%m-%d)"
150
+
151
+ scope_rationale="forced inline via --trivial; computed scope would have been '${computed_tier}' — estimated ${est_files} files, ~${est_lines} lines"
152
+ override_justification="/todo --trivial invoked by user on ${today}; execution_scope forced to 'inline', overriding the heuristic's computed '${computed_tier}' tier (see scope_rationale)."
153
+
154
+ # Build the Acceptance Criteria block from the pipe-separated --criteria value.
155
+ criteria_block=""
156
+ IFS='|' read -ra crit_arr <<< "$criteria"
157
+ for c in "${crit_arr[@]}"; do
158
+ c_trimmed="$(printf '%s' "$c" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
159
+ if [ -n "$c_trimmed" ]; then
160
+ criteria_block+="- [ ] ${c_trimmed}"$'\n'
161
+ fi
162
+ done
163
+ if [ -z "$criteria_block" ]; then
164
+ echo "Error: --criteria produced no usable acceptance criteria" >&2
165
+ exit 1
166
+ fi
167
+
168
+ task_file="${TASKS_DIR}/${task_id}_${slug}.md"
169
+
170
+ cat > "$task_file" <<EOF
171
+ ---
172
+ id: ${task_id}
173
+ story_id: ${story_id}
174
+ epic_id: ${epic_id}
175
+ title: ${title}
176
+ status: Pending
177
+ date_created: ${today}
178
+ date_started:
179
+ date_completed:
180
+ dates_previously_completed:
181
+ reopened_on:
182
+ reopened_reason:
183
+ assigned_to: developer
184
+ docs: []
185
+ execution_scope: inline
186
+ needs_docs: false
187
+ scope_rationale: "${scope_rationale}"
188
+ jenga_assigned: false
189
+ override_justification: "${override_justification}"
190
+ ---
191
+
192
+ # Task: ${title}
193
+
194
+ ## Description
195
+ ${description}
196
+
197
+ ## Prerequisites
198
+ ${prerequisites}
199
+
200
+ ## Acceptance Criteria
201
+ ${criteria_block}
202
+ EOF
203
+
204
+ echo "Wrote task file: ${task_file}"
205
+
206
+ # Register the new task under its parent story's tasks: frontmatter list.
207
+ if ! scripts/with-lock.sh "$story_file" -- python3 "$UPDATE_STORY_SCRIPT" "$story_file" "$task_id"; then
208
+ echo "Error: failed to register ${task_id} in ${story_file}'s tasks: list (lock timeout or write failure)." >&2
209
+ exit 1
210
+ fi
211
+
212
+ # Register the todo entry using the FULL task ID, so /do routes straight into
213
+ # its Inline Execution Path without a redundant breakdown pass.
214
+ bash scripts/todo_manager.sh add "${title}: ${task_id}"
215
+
216
+ echo "${task_id}"