@jenga-ai/agent 1.2.4 → 2.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.
- package/README.md +97 -91
- package/agents/developer.md +26 -7
- package/agents/scrum-master.md +57 -22
- package/agents/tester.md +68 -4
- package/hooks/on_session_end.sh +40 -1
- package/lib/generate-agent-context.js +18 -1
- package/lib/generate-copilot-instructions.js +18 -1
- package/lib/generate-skill-allow-list.js +191 -0
- package/lib/skill-allow-list.json +43 -0
- package/package.json +35 -20
- package/scripts/apply-j-prefix.sh +230 -0
- package/scripts/consume-context-digest.sh +103 -0
- package/scripts/postinstall.js +25 -0
- package/scripts/sweep-stale-context-digests.sh +132 -0
- package/scripts/validate-board.sh +5 -0
- package/scripts/write-context-digest.sh +230 -0
- package/skills/brainstorm/SKILL.md +1 -1
- package/skills/btw/SKILL.md +1 -1
- package/skills/clearify/SKILL.md +1 -1
- package/skills/close-story/SKILL.md +78 -6
- package/skills/close-story/scripts/check-privatized.sh +345 -0
- package/skills/commit/SKILL.md +12 -2
- package/skills/continue/SKILL.md +1 -1
- package/skills/deep-dive/SKILL.md +1 -1
- package/skills/dev-done/SKILL.md +46 -0
- package/skills/dev-done/scripts/classify-commit-outcome.sh +114 -0
- package/skills/distribute/SKILL.md +1 -1
- package/skills/do/SKILL.md +100 -10
- package/skills/doc/README.md +155 -0
- package/skills/doc/SKILL.md +43 -13
- package/skills/doc/authoring-notes.md +72 -0
- package/skills/doc/scripts/resolve_last_update.py +149 -0
- package/skills/doc-sync/SKILL.md +1 -1
- package/skills/dooo/SKILL.md +1 -1
- package/skills/error/SKILL.md +1 -1
- package/skills/evaluate/SKILL.md +1 -1
- package/skills/examplify/SKILL.md +1 -1
- package/skills/help/SKILL.md +1 -1
- package/skills/idea/SKILL.md +1 -1
- package/skills/improve/SKILL.md +1 -1
- package/skills/init/SKILL.md +8 -7
- package/skills/init/assets/scope-thresholds_template.json +7 -0
- package/skills/init/scripts/init.sh +6 -0
- package/skills/j-init/SKILL.md +168 -0
- package/skills/j-init/assets/.gitignore_template +15 -0
- package/skills/j-init/assets/PROJECT_SUMMARY_template.md +13 -0
- package/skills/j-init/assets/directory_structure.txt +14 -0
- package/skills/j-init/assets/scope-thresholds_template.json +7 -0
- package/skills/j-init/assets/strategy_stub_template.md +38 -0
- package/skills/j-init/assets/test-config_template.json +4 -0
- package/skills/j-init/assets/workflow_template.json +30 -0
- package/skills/j-init/scripts/apply-project-visibility.sh +176 -0
- package/skills/j-init/scripts/detect-existing-codebase.sh +166 -0
- package/skills/j-init/scripts/init.sh +116 -0
- package/skills/jbp/SKILL.md +1 -1
- package/skills/jenga/SKILL.md +1 -1
- package/skills/jenga/scripts/render-confirmation.sh +55 -18
- package/skills/jenga-permission-level/SKILL.md +1 -1
- package/skills/lgtm/SKILL.md +1 -1
- package/skills/pi-plan/SKILL.md +1 -1
- package/skills/proceed/SKILL.md +1 -1
- package/skills/publish/SKILL.md +67 -1
- package/skills/publish/adapters/npm-ci.md +60 -4
- package/skills/publish/adapters/npm.md +18 -0
- package/skills/publish/assets/ci-contract.md +27 -0
- package/skills/publish/assets/publish.example.json +27 -0
- package/skills/publish/schemas/publish.schema.json +20 -0
- package/skills/publish/scripts/npm_ci_pipeline.sh +50 -1
- package/skills/publish/scripts/npm_stage_inspect.sh +829 -0
- package/skills/publish/scripts/npm_stage_pipeline.sh +427 -0
- package/skills/publish/scripts/publish_common.sh +16 -0
- package/skills/publish/scripts/show_history.sh +12 -5
- package/skills/publish/scripts/validate_npm_stage_env.sh +184 -0
- package/skills/publish/scripts/write_ledger_entry.sh +92 -2
- package/skills/reconcile/SKILL.md +122 -12
- package/skills/reconcile/assets/report_format.md +17 -0
- package/skills/reconcile/scripts/resolve-reconcile-scope.sh +489 -0
- package/skills/reconcile-origin/SKILL.md +1 -1
- package/skills/redo/SKILL.md +1 -1
- package/skills/skillify/SKILL.md +1 -1
- package/skills/spinoff/SKILL.md +1 -1
- package/skills/status/SKILL.md +1 -1
- package/skills/todo/SKILL.md +40 -3
- package/skills/todo/scripts/add_trivial_task.sh +216 -0
- package/skills/todo/scripts/update_story_tasks.py +87 -0
- package/skills/uncharted/SKILL.md +201 -22
- package/skills/uncharted/scripts/directory-triage.sh +342 -0
- package/skills/uncharted/scripts/elicitation-state.sh +457 -0
- package/skills/wtf/SKILL.md +1 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +90 -2
- package/templates/agent-context.md.tpl +47 -12
- package/templates/copilot-instructions.md.tpl +36 -9
- package/mcp/router/README.md +0 -19
- package/mcp/router/embedder.js +0 -23
- package/mcp/router/index.js +0 -204
- package/mcp/router/matcher.js +0 -87
- package/mcp/router/package-lock.json +0 -1048
- package/mcp/router/package.json +0 -11
- package/mcp/router/skill-index.js +0 -104
- package/skills/route/SKILL.md +0 -180
|
@@ -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,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: brainstorm
|
|
2
|
+
name: j:brainstorm
|
|
3
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.
|
|
4
4
|
keywords:
|
|
5
5
|
- brainstorm
|
package/skills/btw/SKILL.md
CHANGED
package/skills/clearify/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: clearify
|
|
2
|
+
name: j:clearify
|
|
3
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.
|
|
4
4
|
keywords:
|
|
5
5
|
- clarify this
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: close-story
|
|
2
|
+
name: j:close-story
|
|
3
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.
|
|
4
4
|
keywords:
|
|
5
5
|
- close story
|
|
@@ -22,7 +22,12 @@ examples:
|
|
|
22
22
|
1. Verifies all tasks in the story are in a terminal state (Passed or Done).
|
|
23
23
|
2. Extracts actual `git diff --stat` metrics for each task from the commit history.
|
|
24
24
|
3. Writes `actual_files_changed`, `actual_lines_delta`, and `scope_divergence_flag` to each task's frontmatter.
|
|
25
|
-
4.
|
|
25
|
+
4. Runs a static `.publicignore` blocklist check (E51_S03_T03) against each task's and the story's
|
|
26
|
+
own touched files, marking `status: Privatized` in place of the normal terminal status wherever
|
|
27
|
+
every touched file is permanently excluded from the public mirror — independent of any
|
|
28
|
+
`/mirror-public` run having occurred.
|
|
29
|
+
5. Updates the story's frontmatter `status` to `Done` (or `Privatized`, per step 4) and records
|
|
30
|
+
`date_completed`.
|
|
26
31
|
|
|
27
32
|
---
|
|
28
33
|
|
|
@@ -111,6 +116,28 @@ For **each task ID** listed in the story's `tasks:` frontmatter array:
|
|
|
111
116
|
field is present but do not treat this as an error. Run divergence
|
|
112
117
|
computation with `0 0` — this will return `false` for all scopes.
|
|
113
118
|
|
|
119
|
+
7. **Run the static Privatized check** (E51_S03_T03) — immediately after the
|
|
120
|
+
frontmatter writes and divergence computation above, check whether this
|
|
121
|
+
task's own work is permanently excluded from the public mirror:
|
|
122
|
+
```bash
|
|
123
|
+
bash skills/close-story/scripts/check-privatized.sh <task-id> "project/board/tasks/<task-id>_*.md"
|
|
124
|
+
```
|
|
125
|
+
This is a **static** check (per `templates/SCRUM_BOARD_SCHEMA.md`'s "Static
|
|
126
|
+
vs. Reactive Status Setting" section) — it derives the task's touched-file
|
|
127
|
+
list from its own EST-tagged commit history (same technique as Step 2) and
|
|
128
|
+
tests every file against `.publicignore`, with **no dependency on any
|
|
129
|
+
`/mirror-public` run having ever occurred**.
|
|
130
|
+
- Prints `PRIVATIZED` on stdout if every touched file matched the
|
|
131
|
+
blocklist — the script has already written `status: Privatized` to the
|
|
132
|
+
task's frontmatter (superseding whatever status was there, including a
|
|
133
|
+
contradictory `Publicized`, in which case the script also logs a
|
|
134
|
+
`publicized_privatized_mismatch` event to `project/logs/events.json`).
|
|
135
|
+
- Prints `UNCHANGED` if the task has zero matched commits, only partial
|
|
136
|
+
blocklist coverage, or is already `Privatized` — no error, no board
|
|
137
|
+
write.
|
|
138
|
+
- Track any task that came back `PRIVATIZED` for the final report
|
|
139
|
+
(Step 5).
|
|
140
|
+
|
|
114
141
|
---
|
|
115
142
|
|
|
116
143
|
### Step 3 — Bundle task attribution
|
|
@@ -138,11 +165,29 @@ IDs (e.g. `task(E32_S06_T01, E32_S06_T02): ...`). In this case:
|
|
|
138
165
|
|
|
139
166
|
### Step 4 — Update story frontmatter
|
|
140
167
|
|
|
141
|
-
After all tasks have been updated,
|
|
142
|
-
|
|
168
|
+
After all tasks have been updated, run the same static Privatized check
|
|
169
|
+
against the story's own direct commits (E51_S03_T03) **before** deciding the
|
|
170
|
+
story's terminal status:
|
|
143
171
|
|
|
144
|
-
|
|
145
|
-
-
|
|
172
|
+
```bash
|
|
173
|
+
bash skills/close-story/scripts/check-privatized.sh <story-id> "project/board/stories/<story-id>_*.md"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Passing the story id (`E##_S##`) rather than a task id makes the script's
|
|
177
|
+
anchored-grep commit matching (`"<id>([^0-9_]|$)"`) match only the story's
|
|
178
|
+
own direct commits (e.g. `story(E51_S03): ...`) — not its children's, since
|
|
179
|
+
a story id is a literal string prefix of every one of its own tasks' ids.
|
|
180
|
+
|
|
181
|
+
- If the script prints `PRIVATIZED`, it has already written
|
|
182
|
+
`status: Privatized` to the story's frontmatter. **Do not also write
|
|
183
|
+
`status: Done`** — `Privatized` supersedes `Done` as the more specific
|
|
184
|
+
terminal status (a story cannot be both), matching how `Merged`/`Publicized`
|
|
185
|
+
supersede an otherwise-unremarkable closed status on tasks. Still set
|
|
186
|
+
`date_completed: <YYYY-MM-DD>` (today's date in UTC).
|
|
187
|
+
- If the script prints `UNCHANGED`, proceed as normal: set the following
|
|
188
|
+
fields in the story's frontmatter:
|
|
189
|
+
- `status: Done`
|
|
190
|
+
- `date_completed: <YYYY-MM-DD>` (today's date in UTC)
|
|
146
191
|
|
|
147
192
|
Use `update-task-frontmatter.sh` targeting the story file, or edit directly.
|
|
148
193
|
|
|
@@ -164,6 +209,32 @@ If any task had `0` for both fields, note it as potentially untracked:
|
|
|
164
209
|
<task-id>: files_changed=0, lines_delta=0 (no EST-tagged commit found)
|
|
165
210
|
```
|
|
166
211
|
|
|
212
|
+
#### Privatized
|
|
213
|
+
|
|
214
|
+
Include a "Privatized" note listing any task (from Step 2) or the story itself (from Step 4) that
|
|
215
|
+
`check-privatized.sh` marked `status: Privatized` — every one of its touched files was permanently
|
|
216
|
+
excluded from the public mirror via `.publicignore`, independent of any `/mirror-public` run.
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Privatized:
|
|
220
|
+
<task-id>: all touched files matched .publicignore
|
|
221
|
+
...
|
|
222
|
+
Story <story-id>: Privatized (all touched files matched .publicignore) — closed as Privatized, not Done
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Or, if none were Privatized:
|
|
226
|
+
```
|
|
227
|
+
Privatized: none
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
If any ticket was overwritten from `Publicized` to `Privatized` (a precedence mismatch), note it
|
|
231
|
+
explicitly and point to the logged `publicized_privatized_mismatch` event in
|
|
232
|
+
`project/logs/events.json` for investigation:
|
|
233
|
+
```
|
|
234
|
+
<id>: WARNING — was Publicized, found fully blocklisted, overwritten to Privatized (see
|
|
235
|
+
project/logs/events.json: publicized_privatized_mismatch)
|
|
236
|
+
```
|
|
237
|
+
|
|
167
238
|
#### Scope Divergence
|
|
168
239
|
|
|
169
240
|
Include a "Scope Divergence" section listing every task whose `scope_divergence_flag` was set
|
|
@@ -201,3 +272,4 @@ Scope Divergence: skipped (scope-thresholds.json missing or malformed)
|
|
|
201
272
|
| `scripts/extract-task-diff-stats.sh <task-id>` | Per-task diff stats from EST-tagged commits |
|
|
202
273
|
| `scripts/update-task-frontmatter.sh <file> <key> <value>` | Write/update a YAML field in task or story frontmatter |
|
|
203
274
|
| `scripts/compute-scope-divergence.sh <execution_scope> <actual_files_changed> <actual_lines_delta>` | Compute scope divergence flag: prints `true` or `false` |
|
|
275
|
+
| `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 |
|