@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
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env bash
2
+ # ---------------------------------------------------------------------------
3
+ # scripts/write-context-digest.sh
4
+ #
5
+ # Write helper for the resolved_context digest handoff convention (E49_S01).
6
+ # A sending agent (scrum-master dispatching to developer, developer
7
+ # dispatching to tester) calls this to persist a short digest of context it
8
+ # has already resolved, so the receiving subagent doesn't have to cold-re-read
9
+ # the same source documents. The receiving agent's sender object then carries
10
+ # a reference to (or holds) the resulting file path in its `resolved_context`
11
+ # field — see templates/SCRUM_BOARD_SCHEMA.md's resolved_context subsection.
12
+ #
13
+ # Physical convention (already documented by E49_S01_T01, implemented here):
14
+ # project/queue/context/<agent>-<session_id>-<task_id>.json
15
+ # — the exact same filename shape as project/queue/handoffs/, for the same
16
+ # reason: <session_id> alone is already collision-free (each session has a
17
+ # unique id and writes its digest at most once per task), <task_id> is
18
+ # appended for human debuggability.
19
+ #
20
+ # Size-cap discipline: templates/SCRUM_BOARD_SCHEMA.md documents a ~100-line
21
+ # / few-hundred-token cap on resolved_context — "a digest, not a dump". This
22
+ # script REJECTS (does not truncate) content over the cap. Truncating would
23
+ # silently cut a digest off mid-thought and could mislead the receiver into
24
+ # treating a partial thought as complete; a loud, immediate failure lets the
25
+ # sender shorten the digest itself, which is the only party that actually
26
+ # knows what's safe to cut.
27
+ #
28
+ # Usage:
29
+ # write-context-digest.sh --agent <agent> --session-id <id> --task-id <id>
30
+ # [--content <text> | --content-file <path>]
31
+ # [--max-lines <n>]
32
+ # <producer> | write-context-digest.sh --agent <agent> --session-id <id> --task-id <id>
33
+ #
34
+ # If neither --content nor --content-file is given, digest content is read
35
+ # from stdin (mirrors skills/uncharted/scripts/import-source.sh's snippet
36
+ # convention).
37
+ #
38
+ # Options:
39
+ # --agent <agent> scrum-master | developer | tester (required)
40
+ # --session-id <id> writing session's id, verbatim (required)
41
+ # --task-id <id> primary task ID this digest concerns (required)
42
+ # --content <text> digest content inline
43
+ # --content-file <path> digest content read from this file
44
+ # --max-lines <n> override the default 100-line cap
45
+ # (env: WRITE_CONTEXT_DIGEST_MAX_LINES)
46
+ # --queue-dir <dir> override project/queue (default: resolved via
47
+ # JENGA_PROJECT_DIR / git toplevel)
48
+ # -h, --help show this help
49
+ #
50
+ # Output (stdout):
51
+ # <absolute path to the written digest file> (only line printed on success)
52
+ #
53
+ # Exit codes:
54
+ # 0 digest written
55
+ # 1 usage error (missing/invalid flag)
56
+ # 2 environment error (jq unavailable, cannot create project/queue/context)
57
+ # 3 empty digest content
58
+ # 4 digest exceeds the line cap (rejected, not truncated)
59
+ # 5 write failed (atomic rename step)
60
+ # ---------------------------------------------------------------------------
61
+
62
+ set -euo pipefail
63
+
64
+ SELF="$(basename "$0")"
65
+
66
+ die() {
67
+ local code="$1"; shift
68
+ printf '%s: error: %s\n' "$SELF" "$*" >&2
69
+ exit "$code"
70
+ }
71
+
72
+ usage() {
73
+ sed -n '/^# Usage:/,/^# Exit codes:/p' "$0" | sed 's/^# \{0,1\}//' >&2
74
+ exit 1
75
+ }
76
+
77
+ command -v jq >/dev/null 2>&1 || die 2 "jq is required but not found on PATH"
78
+
79
+ # ---------------------------------------------------------------------------
80
+ # Resolve project root (mirrors lib/resolve-project-dir.sh's own probing
81
+ # order without requiring callers to source it, since this script must also
82
+ # work standalone from a plain shell during manual verification).
83
+ # ---------------------------------------------------------------------------
84
+ resolve_project_dir() {
85
+ if [ -n "${JENGA_PROJECT_DIR:-}" ]; then
86
+ printf '%s\n' "$JENGA_PROJECT_DIR"
87
+ return 0
88
+ fi
89
+ if [ -n "${CLAUDE_PROJECT_DIR:-}" ]; then
90
+ printf '%s\n' "$CLAUDE_PROJECT_DIR"
91
+ return 0
92
+ fi
93
+ git rev-parse --show-toplevel 2>/dev/null || pwd
94
+ }
95
+
96
+ AGENT=""
97
+ SESSION_ID=""
98
+ TASK_ID=""
99
+ CONTENT=""
100
+ CONTENT_SET=0
101
+ CONTENT_FILE=""
102
+ MAX_LINES="${WRITE_CONTEXT_DIGEST_MAX_LINES:-100}"
103
+ QUEUE_DIR=""
104
+
105
+ while [ "$#" -gt 0 ]; do
106
+ case "$1" in
107
+ --agent)
108
+ [ "$#" -ge 2 ] || die 1 "--agent requires a value"
109
+ AGENT="$2"; shift 2 ;;
110
+ --agent=*)
111
+ AGENT="${1#--agent=}"; shift ;;
112
+ --session-id)
113
+ [ "$#" -ge 2 ] || die 1 "--session-id requires a value"
114
+ SESSION_ID="$2"; shift 2 ;;
115
+ --session-id=*)
116
+ SESSION_ID="${1#--session-id=}"; shift ;;
117
+ --task-id)
118
+ [ "$#" -ge 2 ] || die 1 "--task-id requires a value"
119
+ TASK_ID="$2"; shift 2 ;;
120
+ --task-id=*)
121
+ TASK_ID="${1#--task-id=}"; shift ;;
122
+ --content)
123
+ [ "$#" -ge 2 ] || die 1 "--content requires a value"
124
+ CONTENT="$2"; CONTENT_SET=1; shift 2 ;;
125
+ --content=*)
126
+ CONTENT="${1#--content=}"; CONTENT_SET=1; shift ;;
127
+ --content-file)
128
+ [ "$#" -ge 2 ] || die 1 "--content-file requires a value"
129
+ CONTENT_FILE="$2"; shift 2 ;;
130
+ --content-file=*)
131
+ CONTENT_FILE="${1#--content-file=}"; shift ;;
132
+ --max-lines)
133
+ [ "$#" -ge 2 ] || die 1 "--max-lines requires a value"
134
+ MAX_LINES="$2"; shift 2 ;;
135
+ --max-lines=*)
136
+ MAX_LINES="${1#--max-lines=}"; shift ;;
137
+ --queue-dir)
138
+ [ "$#" -ge 2 ] || die 1 "--queue-dir requires a value"
139
+ QUEUE_DIR="$2"; shift 2 ;;
140
+ --queue-dir=*)
141
+ QUEUE_DIR="${1#--queue-dir=}"; shift ;;
142
+ -h|--help)
143
+ usage ;;
144
+ *)
145
+ die 1 "unknown argument: $1" ;;
146
+ esac
147
+ done
148
+
149
+ [ -n "$AGENT" ] || die 1 "--agent is required"
150
+ case "$AGENT" in
151
+ scrum-master|developer|tester) ;;
152
+ *) die 1 "invalid --agent '$AGENT' (expected scrum-master, developer, or tester)" ;;
153
+ esac
154
+ [ -n "$SESSION_ID" ] || die 1 "--session-id is required"
155
+ [ -n "$TASK_ID" ] || die 1 "--task-id is required"
156
+
157
+ case "$MAX_LINES" in
158
+ ''|*[!0-9]*) die 1 "--max-lines must be a positive integer, got '$MAX_LINES'" ;;
159
+ esac
160
+ [ "$MAX_LINES" -gt 0 ] || die 1 "--max-lines must be a positive integer, got '$MAX_LINES'"
161
+
162
+ # Session id / task id are used verbatim in a filename below — refuse path
163
+ # separators or traversal rather than silently mangling or escaping them.
164
+ case "$SESSION_ID" in
165
+ */*|*..*) die 1 "invalid --session-id '$SESSION_ID': must not contain '/' or '..'" ;;
166
+ esac
167
+ case "$TASK_ID" in
168
+ */*|*..*) die 1 "invalid --task-id '$TASK_ID': must not contain '/' or '..'" ;;
169
+ esac
170
+
171
+ # ---------------------------------------------------------------------------
172
+ # Resolve digest content: --content, then --content-file, then stdin.
173
+ # ---------------------------------------------------------------------------
174
+ if [ -n "$CONTENT_FILE" ]; then
175
+ [ "$CONTENT_SET" -eq 0 ] || die 1 "--content and --content-file are mutually exclusive"
176
+ [ -f "$CONTENT_FILE" ] || die 1 "--content-file '$CONTENT_FILE' does not exist"
177
+ CONTENT="$(cat "$CONTENT_FILE")"
178
+ CONTENT_SET=1
179
+ fi
180
+
181
+ if [ "$CONTENT_SET" -eq 0 ]; then
182
+ CONTENT="$(cat)"
183
+ fi
184
+
185
+ [ -n "$CONTENT" ] || die 3 "digest content is empty — nothing to write"
186
+
187
+ LINE_COUNT=$(printf '%s\n' "$CONTENT" | wc -l | tr -d ' ')
188
+ if [ "$LINE_COUNT" -gt "$MAX_LINES" ]; then
189
+ die 4 "digest is $LINE_COUNT lines, exceeding the $MAX_LINES-line cap documented in templates/SCRUM_BOARD_SCHEMA.md's resolved_context subsection (\"a digest, not a dump\") — shorten it rather than raising --max-lines/WRITE_CONTEXT_DIGEST_MAX_LINES, which exists for genuine exceptions only"
190
+ fi
191
+
192
+ # ---------------------------------------------------------------------------
193
+ # Resolve destination and write atomically.
194
+ # ---------------------------------------------------------------------------
195
+ PROJECT_DIR="$(resolve_project_dir)"
196
+ [ -n "$QUEUE_DIR" ] || QUEUE_DIR="$PROJECT_DIR/project/queue"
197
+ CONTEXT_DIR="$QUEUE_DIR/context"
198
+
199
+ mkdir -p "$CONTEXT_DIR" 2>/dev/null || die 2 "could not create $CONTEXT_DIR"
200
+
201
+ DEST_FILE="$CONTEXT_DIR/${AGENT}-${SESSION_ID}-${TASK_ID}.json"
202
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
203
+
204
+ TMP_FILE=$(mktemp "$CONTEXT_DIR/.digest_tmp.XXXXXX") || die 5 "could not create temp file in $CONTEXT_DIR"
205
+
206
+ if ! jq -n \
207
+ --arg agent "$AGENT" \
208
+ --arg session_id "$SESSION_ID" \
209
+ --arg task_id "$TASK_ID" \
210
+ --arg date "$TIMESTAMP" \
211
+ --arg digest "$CONTENT" \
212
+ --argjson line_count "$LINE_COUNT" \
213
+ '{
214
+ agent: $agent,
215
+ session_id: $session_id,
216
+ task_id: $task_id,
217
+ date: $date,
218
+ line_count: $line_count,
219
+ digest: $digest
220
+ }' > "$TMP_FILE"; then
221
+ rm -f "$TMP_FILE"
222
+ die 5 "failed to build digest JSON"
223
+ fi
224
+
225
+ if ! mv "$TMP_FILE" "$DEST_FILE"; then
226
+ rm -f "$TMP_FILE"
227
+ die 5 "failed to move temp file into place at $DEST_FILE"
228
+ fi
229
+
230
+ printf '%s\n' "$DEST_FILE"
@@ -1,21 +1,28 @@
1
1
  ---
2
- name: brainstorm
3
- description: Engage the scrum-master agent in a focused planning session to define, refine, or challenge features, improvements, tasks, stories, and epics. The agent asks probing questions, challenges assumptions, and helps shape ideas into actionable backlog items.
2
+ name: j.brainstorm
3
+ description: Polyfill alias of the brainstorm skill under a collision-safe directory name. Identical behavior to /brainstorm — Engage the scrum-master agent in a focused planning session to define, refine, or challenge features, improvements, tasks, stories, and epics. The agent asks probing questions, challenges assumptions, and helps shape ideas into actionable backlog items. Use when the bare /brainstorm form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - brainstorm
6
6
  - plan
7
7
  - ideate
8
8
  - feature planning
9
9
  - requirements
10
+ - j-brainstorm
11
+ - polyfill
10
12
  examples:
11
13
  - "let's brainstorm ideas for X"
12
14
  - "I need to plan a new feature"
15
+ - "j-brainstorm"
13
16
  metadata:
14
17
  prefered_agent: scrum-master
15
18
  ---
16
19
 
17
20
  # Brainstorm — Collaborative Planning with the Scrum Master
18
21
 
22
+ This skill is a literal-directory-name duplicate of `skills/brainstorm/`. It exists so that `/j-brainstorm` (and `j.j-brainstorm`) give a guaranteed-unshadowed way to reach the same flow as `/brainstorm`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/brainstorm` 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 brainstorm` from `skills/brainstorm/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. **Invoke the `scrum-master` agent** — Pass the user's input directly to it as the opening prompt for the brainstorm session.
@@ -1,21 +1,28 @@
1
1
  ---
2
- name: btw
3
- description: Capture a new mission (feature, change, or addition) and fit it into the project's Epic/Story structure, then choose to implement now or defer.
2
+ name: j.btw
3
+ description: Polyfill alias of the btw skill under a collision-safe directory name. Identical behavior to /btw — Capture a new mission (feature, change, or addition) and fit it into the project's Epic/Story structure, then choose to implement now or defer. Use when the bare /btw form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - btw
6
6
  - capture
7
7
  - mission
8
8
  - new idea
9
9
  - side task
10
+ - j-btw
11
+ - polyfill
10
12
  examples:
11
13
  - "btw I also need to add X"
12
14
  - "capture this as a new task"
15
+ - "j-btw"
13
16
  metadata:
14
17
  prefered_agent: scrum-master
15
18
  ---
16
19
 
17
20
  # BTW — Capture a Mission
18
21
 
22
+ This skill is a literal-directory-name duplicate of `skills/btw/`. It exists so that `/j-btw` (and `j.j-btw`) give a guaranteed-unshadowed way to reach the same flow as `/btw`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/btw` 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 btw` from `skills/btw/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. **Gather mission details** — Ask the user:
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: clearify
3
- description: Clarifies ambiguous, dense, or under-specified prompts and conversation on request — inspects an attached prompt or falls back to the current conversation and surfaces plain-language clarifications with examples.
2
+ name: j.clearify
3
+ description: Polyfill alias of the clearify skill under a collision-safe directory name. Identical behavior to /clearify — Clarifies ambiguous, dense, or under-specified prompts and conversation on request — inspects an attached prompt or falls back to the current conversation and surfaces plain-language clarifications with examples. Use when the bare /clearify form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - clarify this
6
6
  - clarify
@@ -9,16 +9,23 @@ keywords:
9
9
  - wtf
10
10
  - explain that again
11
11
  - can you simplify
12
+ - j-clearify
13
+ - polyfill
12
14
  examples:
13
15
  - "clarify this"
14
16
  - "clearify the last message"
15
17
  - "wtf does this mean"
16
18
  - "I don't understand what you're asking me to do here"
19
+ - "j-clearify"
17
20
  alias: wtf
18
21
  ---
19
22
 
20
23
  # Clearify — Ambiguity Clarification
21
24
 
25
+ This skill is a literal-directory-name duplicate of `skills/clearify/`. It exists so that `/j-clearify` (and `j.j-clearify`) give a guaranteed-unshadowed way to reach the same flow as `/clearify`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/clearify` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
26
+
27
+ This file is generated/synced by `scripts/generate-j-alias.sh clearify` from `skills/clearify/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
28
+
22
29
  > **Note on the `alias: wtf` frontmatter field:** this repo has no runtime mechanism that reads an `alias` key to route slash commands — no existing `SKILL.md` implements one, and `project/configs/workflow.json` has no alias registry. The field here documents the intended relationship only. `/wtf` is made invocable as a working alias by the companion skill folder at `skills/wtf/SKILL.md`, which delegates to these same instructions.
23
30
 
24
31
  ## Instructions
@@ -1,20 +1,27 @@
1
1
  ---
2
- name: close-story
3
- description: Close a story by verifying all tasks are in terminal state, extracting actual diff stats per task, computing scope divergence flags, and writing closure metadata to task frontmatter.
2
+ name: j.close-story
3
+ description: Polyfill alias of the close-story skill under a collision-safe directory name. Identical behavior to /close-story — Close a story by verifying all tasks are in terminal state, extracting actual diff stats per task, computing scope divergence flags, and writing closure metadata to task frontmatter. Use when the bare /close-story form is shadowed by another tool's own built-in command of the same name.
4
4
  keywords:
5
5
  - close story
6
6
  - close
7
7
  - finish story
8
8
  - complete story
9
9
  - story done
10
+ - j-close-story
11
+ - polyfill
10
12
  examples:
11
13
  - "close story E17_S06"
12
14
  - "/close-story E32_S06"
13
15
  - "mark story E12_S03 as done"
16
+ - "j-close-story"
14
17
  ---
15
18
 
16
19
  # close-story — Close a Story
17
20
 
21
+ This skill is a literal-directory-name duplicate of `skills/close-story/`. It exists so that `/j-close-story` (and `j.j-close-story`) give a guaranteed-unshadowed way to reach the same flow as `/close-story`, even if a host tool's own built-in command of the same name would otherwise shadow or override the bare `/close-story` alias (Claude Code's native skill resolution is a literal-string, directory-name-based match — see `docs/skill-authoring.md`'s "Invocation Convention").
22
+
23
+ This file is generated/synced by `scripts/generate-j-alias.sh close-story` from `skills/close-story/SKILL.md` — do not hand-edit it; re-run the generator instead to pick up source changes.
24
+
18
25
  ## Purpose
19
26
 
20
27
  `/close-story <story-id>` performs the final closure steps for a story:
@@ -22,7 +29,12 @@ examples:
22
29
  1. Verifies all tasks in the story are in a terminal state (Passed or Done).
23
30
  2. Extracts actual `git diff --stat` metrics for each task from the commit history.
24
31
  3. Writes `actual_files_changed`, `actual_lines_delta`, and `scope_divergence_flag` to each task's frontmatter.
25
- 4. Updates the story's frontmatter `status` to `Done` and records `date_completed`.
32
+ 4. Runs a static `.publicignore` blocklist check (E51_S03_T03) against each task's and the story's
33
+ own touched files, marking `status: Privatized` in place of the normal terminal status wherever
34
+ every touched file is permanently excluded from the public mirror — independent of any
35
+ `/mirror-public` run having occurred.
36
+ 5. Updates the story's frontmatter `status` to `Done` (or `Privatized`, per step 4) and records
37
+ `date_completed`.
26
38
 
27
39
  ---
28
40
 
@@ -33,7 +45,7 @@ examples:
33
45
  Run the guard script:
34
46
 
35
47
  ```bash
36
- bash skills/close-story/scripts/check-story-closeable.sh <story-id>
48
+ bash skills/j-close-story/scripts/check-story-closeable.sh <story-id>
37
49
  ```
38
50
 
39
51
  - If it exits with code 0 and prints `CLOSEABLE`, continue.
@@ -60,7 +72,7 @@ For **each task ID** listed in the story's `tasks:` frontmatter array:
60
72
 
61
73
  3. **Run per-task diff stat extraction:**
62
74
  ```bash
63
- bash skills/close-story/scripts/extract-task-diff-stats.sh <task-id>
75
+ bash skills/j-close-story/scripts/extract-task-diff-stats.sh <task-id>
64
76
  ```
65
77
  The script outputs:
66
78
  ```
@@ -71,11 +83,11 @@ For **each task ID** listed in the story's `tasks:` frontmatter array:
71
83
 
72
84
  4. **Write stats to task frontmatter:**
73
85
  ```bash
74
- bash skills/close-story/scripts/update-task-frontmatter.sh \
86
+ bash skills/j-close-story/scripts/update-task-frontmatter.sh \
75
87
  "project/board/tasks/<task-id>_*.md" \
76
88
  actual_files_changed <N>
77
89
 
78
- bash skills/close-story/scripts/update-task-frontmatter.sh \
90
+ bash skills/j-close-story/scripts/update-task-frontmatter.sh \
79
91
  "project/board/tasks/<task-id>_*.md" \
80
92
  actual_lines_delta <N>
81
93
  ```
@@ -92,13 +104,13 @@ For **each task ID** listed in the story's `tasks:` frontmatter array:
92
104
 
93
105
  Run the divergence computation:
94
106
  ```bash
95
- DIVERGENCE_FLAG=$(bash skills/close-story/scripts/compute-scope-divergence.sh \
107
+ DIVERGENCE_FLAG=$(bash skills/j-close-story/scripts/compute-scope-divergence.sh \
96
108
  "<execution_scope>" <actual_files_changed> <actual_lines_delta>)
97
109
  ```
98
110
 
99
111
  Write the result to task frontmatter:
100
112
  ```bash
101
- bash skills/close-story/scripts/update-task-frontmatter.sh \
113
+ bash skills/j-close-story/scripts/update-task-frontmatter.sh \
102
114
  "project/board/tasks/<task-id>_*.md" \
103
115
  scope_divergence_flag "$DIVERGENCE_FLAG"
104
116
  ```
@@ -111,6 +123,28 @@ For **each task ID** listed in the story's `tasks:` frontmatter array:
111
123
  field is present but do not treat this as an error. Run divergence
112
124
  computation with `0 0` — this will return `false` for all scopes.
113
125
 
126
+ 7. **Run the static Privatized check** (E51_S03_T03) — immediately after the
127
+ frontmatter writes and divergence computation above, check whether this
128
+ task's own work is permanently excluded from the public mirror:
129
+ ```bash
130
+ bash skills/j-close-story/scripts/check-privatized.sh <task-id> "project/board/tasks/<task-id>_*.md"
131
+ ```
132
+ This is a **static** check (per `templates/SCRUM_BOARD_SCHEMA.md`'s "Static
133
+ vs. Reactive Status Setting" section) — it derives the task's touched-file
134
+ list from its own EST-tagged commit history (same technique as Step 2) and
135
+ tests every file against `.publicignore`, with **no dependency on any
136
+ `/mirror-public` run having ever occurred**.
137
+ - Prints `PRIVATIZED` on stdout if every touched file matched the
138
+ blocklist — the script has already written `status: Privatized` to the
139
+ task's frontmatter (superseding whatever status was there, including a
140
+ contradictory `Publicized`, in which case the script also logs a
141
+ `publicized_privatized_mismatch` event to `project/logs/events.json`).
142
+ - Prints `UNCHANGED` if the task has zero matched commits, only partial
143
+ blocklist coverage, or is already `Privatized` — no error, no board
144
+ write.
145
+ - Track any task that came back `PRIVATIZED` for the final report
146
+ (Step 5).
147
+
114
148
  ---
115
149
 
116
150
  ### Step 3 — Bundle task attribution
@@ -138,11 +172,29 @@ IDs (e.g. `task(E32_S06_T01, E32_S06_T02): ...`). In this case:
138
172
 
139
173
  ### Step 4 — Update story frontmatter
140
174
 
141
- After all tasks have been updated, set the following fields in the story's
142
- frontmatter:
175
+ After all tasks have been updated, run the same static Privatized check
176
+ against the story's own direct commits (E51_S03_T03) **before** deciding the
177
+ story's terminal status:
143
178
 
144
- - `status: Done`
145
- - `date_completed: <YYYY-MM-DD>` (today's date in UTC)
179
+ ```bash
180
+ bash skills/j-close-story/scripts/check-privatized.sh <story-id> "project/board/stories/<story-id>_*.md"
181
+ ```
182
+
183
+ Passing the story id (`E##_S##`) rather than a task id makes the script's
184
+ anchored-grep commit matching (`"<id>([^0-9_]|$)"`) match only the story's
185
+ own direct commits (e.g. `story(E51_S03): ...`) — not its children's, since
186
+ a story id is a literal string prefix of every one of its own tasks' ids.
187
+
188
+ - If the script prints `PRIVATIZED`, it has already written
189
+ `status: Privatized` to the story's frontmatter. **Do not also write
190
+ `status: Done`** — `Privatized` supersedes `Done` as the more specific
191
+ terminal status (a story cannot be both), matching how `Merged`/`Publicized`
192
+ supersede an otherwise-unremarkable closed status on tasks. Still set
193
+ `date_completed: <YYYY-MM-DD>` (today's date in UTC).
194
+ - If the script prints `UNCHANGED`, proceed as normal: set the following
195
+ fields in the story's frontmatter:
196
+ - `status: Done`
197
+ - `date_completed: <YYYY-MM-DD>` (today's date in UTC)
146
198
 
147
199
  Use `update-task-frontmatter.sh` targeting the story file, or edit directly.
148
200
 
@@ -164,6 +216,32 @@ If any task had `0` for both fields, note it as potentially untracked:
164
216
  <task-id>: files_changed=0, lines_delta=0 (no EST-tagged commit found)
165
217
  ```
166
218
 
219
+ #### Privatized
220
+
221
+ Include a "Privatized" note listing any task (from Step 2) or the story itself (from Step 4) that
222
+ `check-privatized.sh` marked `status: Privatized` — every one of its touched files was permanently
223
+ excluded from the public mirror via `.publicignore`, independent of any `/mirror-public` run.
224
+
225
+ ```
226
+ Privatized:
227
+ <task-id>: all touched files matched .publicignore
228
+ ...
229
+ Story <story-id>: Privatized (all touched files matched .publicignore) — closed as Privatized, not Done
230
+ ```
231
+
232
+ Or, if none were Privatized:
233
+ ```
234
+ Privatized: none
235
+ ```
236
+
237
+ If any ticket was overwritten from `Publicized` to `Privatized` (a precedence mismatch), note it
238
+ explicitly and point to the logged `publicized_privatized_mismatch` event in
239
+ `project/logs/events.json` for investigation:
240
+ ```
241
+ <id>: WARNING — was Publicized, found fully blocklisted, overwritten to Privatized (see
242
+ project/logs/events.json: publicized_privatized_mismatch)
243
+ ```
244
+
167
245
  #### Scope Divergence
168
246
 
169
247
  Include a "Scope Divergence" section listing every task whose `scope_divergence_flag` was set
@@ -201,3 +279,4 @@ Scope Divergence: skipped (scope-thresholds.json missing or malformed)
201
279
  | `scripts/extract-task-diff-stats.sh <task-id>` | Per-task diff stats from EST-tagged commits |
202
280
  | `scripts/update-task-frontmatter.sh <file> <key> <value>` | Write/update a YAML field in task or story frontmatter |
203
281
  | `scripts/compute-scope-divergence.sh <execution_scope> <actual_files_changed> <actual_lines_delta>` | Compute scope divergence flag: prints `true` or `false` |
282
+ | `scripts/check-privatized.sh <id> <board-file-path>` | Static `.publicignore` membership check (task or story); prints `PRIVATIZED` (status written) or `UNCHANGED` — no `/mirror-public` run required |