@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.
- package/README.md +93 -256
- package/agents/developer.md +9 -8
- package/agents/scrum-master.md +57 -23
- package/agents/tester.md +51 -5
- package/hooks/on_session_end.sh +13 -1
- package/lib/generate-agent-context.js +18 -1
- package/lib/generate-copilot-instructions.js +18 -1
- package/lib/generate-skill-allow-list.js +197 -0
- package/lib/skill-allow-list.json +42 -0
- package/package.json +17 -13
- package/scripts/apply-j-prefix.sh +243 -0
- package/scripts/consume-context-digest.sh +103 -0
- package/scripts/generate-j-alias.sh +333 -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 → j-brainstorm}/SKILL.md +9 -2
- package/skills/{btw → j-btw}/SKILL.md +9 -2
- package/skills/{clearify → j-clearify}/SKILL.md +9 -2
- package/skills/{close-story → j-close-story}/SKILL.md +92 -13
- package/skills/j-close-story/scripts/check-privatized.sh +345 -0
- package/skills/{close-story → j-close-story}/scripts/check-story-closeable.sh +1 -1
- package/skills/{close-story → j-close-story}/scripts/extract-task-diff-stats.sh +1 -1
- package/skills/{commit → j-commit}/SKILL.md +9 -2
- package/skills/j-continue/SKILL.md +36 -0
- package/skills/{deep-dive → j-deep-dive}/SKILL.md +9 -8
- package/skills/{dev-done → j-dev-done}/SKILL.md +11 -4
- package/skills/{dev-done → j-dev-done}/scripts/classify-commit-outcome.sh +4 -4
- package/skills/{distribute → j-distribute}/SKILL.md +17 -10
- package/skills/{distribute → j-distribute}/scripts/distribute-changes.sh +1 -1
- package/skills/{do → j-do}/SKILL.md +111 -14
- package/skills/j-doc/README.md +155 -0
- package/skills/{doc → j-doc}/SKILL.md +55 -18
- package/skills/j-doc/authoring-notes.md +72 -0
- package/skills/j-doc/scripts/resolve_last_update.py +149 -0
- package/skills/{doc-sync → j-doc-sync}/SKILL.md +9 -2
- package/skills/{dooo → j-dooo}/SKILL.md +9 -2
- package/skills/j-error/SKILL.md +36 -0
- package/skills/{evaluate → j-evaluate}/SKILL.md +9 -2
- package/skills/j-examplify/SKILL.md +49 -0
- package/skills/{help → j-help}/SKILL.md +9 -2
- package/skills/{idea → j-idea}/SKILL.md +10 -3
- package/skills/{idea → j-idea}/assets/idea_handoff_template.md +1 -1
- package/skills/{improve → j-improve}/SKILL.md +9 -2
- package/skills/{init → j-init}/SKILL.md +21 -8
- package/skills/j-init/assets/scope-thresholds_template.json +7 -0
- package/skills/j-jbp/SKILL.md +32 -0
- package/skills/j-lgtm/SKILL.md +28 -0
- package/skills/{pi-plan → j-pi-plan}/SKILL.md +10 -3
- package/skills/{proceed → j-proceed}/SKILL.md +9 -2
- package/skills/{publish → j-publish}/SKILL.md +47 -40
- package/skills/{publish → j-publish}/adapters/droplet.md +1 -1
- package/skills/{publish → j-publish}/adapters/mobile-ios.md +3 -3
- package/skills/{publish → j-publish}/adapters/npm-ci.md +29 -7
- package/skills/{publish → j-publish}/adapters/npm.md +8 -8
- package/skills/{publish → j-publish}/assets/ci-contract.md +2 -2
- package/skills/{publish → j-publish}/schemas/publish.schema.json +1 -1
- package/skills/{publish → j-publish}/scripts/npm_ci_pipeline.sh +21 -1
- package/skills/{publish → j-publish}/scripts/npm_stage_inspect.sh +34 -1
- package/skills/{publish → j-publish}/scripts/npm_stage_pipeline.sh +9 -4
- package/skills/{publish → j-publish}/scripts/publish_deploy.sh +4 -4
- package/skills/{publish → j-publish}/scripts/validate_npm_stage_env.sh +1 -1
- package/skills/{publish → j-publish}/wizards/droplet.md +1 -1
- package/skills/{publish → j-publish}/wizards/mobile-ios.md +1 -1
- package/skills/{publish → j-publish}/wizards/npm-ci.md +1 -1
- package/skills/{publish → j-publish}/wizards/npm.md +1 -1
- package/skills/{reconcile → j-reconcile}/SKILL.md +12 -5
- package/skills/{reconcile → j-reconcile}/scripts/detect-unlinked-code.sh +2 -2
- package/skills/{reconcile → j-reconcile}/scripts/resolve-reconcile-scope.sh +3 -3
- package/skills/{reconcile-origin → j-reconcile-origin}/SKILL.md +13 -6
- package/skills/{redo → j-redo}/SKILL.md +9 -2
- package/skills/{skillify → j-skillify}/SKILL.md +10 -3
- package/skills/{spinoff → j-spinoff}/SKILL.md +9 -2
- package/skills/{status → j-status}/SKILL.md +9 -2
- package/skills/j-todo/SKILL.md +92 -0
- package/skills/{todo → j-todo}/assets/todo_handoff_template.md +1 -1
- package/skills/j-todo/scripts/add_trivial_task.sh +216 -0
- package/skills/j-todo/scripts/update_story_tasks.py +87 -0
- package/skills/{uncharted → j-uncharted}/SKILL.md +35 -28
- package/skills/{uncharted → j-uncharted}/assets/UNDERSTANDING_DOC_TEMPLATE.md +2 -2
- package/skills/{uncharted → j-uncharted}/scripts/detect-dependencies.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/detect-tests.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/directory-triage.sh +3 -3
- package/skills/{uncharted → j-uncharted}/scripts/elicitation-state.sh +3 -3
- package/skills/{uncharted → j-uncharted}/scripts/enumerate-target.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/import-source.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/inspect-provenance.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/resolve-segment-target.sh +5 -5
- package/skills/{uncharted → j-uncharted}/scripts/run-engine.sh +1 -1
- package/skills/{uncharted → j-uncharted}/scripts/validate-proposed-items.sh +2 -2
- package/skills/{uncharted → j-uncharted}/scripts/write-backfilled-epics.sh +1 -1
- package/skills/j-wtf/SKILL.md +27 -0
- 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/templates/SCRUM_BOARD_SCHEMA.md +33 -2
- package/templates/agent-context.md.tpl +32 -9
- package/templates/copilot-instructions.md.tpl +66 -11
- package/skills/continue/SKILL.md +0 -29
- package/skills/error/SKILL.md +0 -29
- package/skills/examplify/SKILL.md +0 -42
- package/skills/init/assets/scope-thresholds_template.json +0 -7
- package/skills/jbp/SKILL.md +0 -25
- package/skills/lgtm/SKILL.md +0 -21
- package/skills/todo/SKILL.md +0 -48
- package/skills/wtf/SKILL.md +0 -20
- /package/skills/{close-story → j-close-story}/scripts/compute-scope-divergence.sh +0 -0
- /package/skills/{close-story → j-close-story}/scripts/extract-diff-stats.sh +0 -0
- /package/skills/{close-story → j-close-story}/scripts/update-task-frontmatter.sh +0 -0
- /package/skills/{commit → j-commit}/assets/user_instructions_template.md +0 -0
- /package/skills/{distribute → j-distribute}/CONFIG_SCHEMA.md +0 -0
- /package/skills/{distribute → j-distribute}/scripts/check-version.sh +0 -0
- /package/skills/{distribute → j-distribute}/scripts/commit-version-bump.sh +0 -0
- /package/skills/{do → j-do}/assets/intent-vs-diff-prompt.md +0 -0
- /package/skills/{do → j-do}/assets/sender_template.json +0 -0
- /package/skills/{doc → j-doc}/assets/path-objectives.yaml +0 -0
- /package/skills/{doc-sync → j-doc-sync}/assets/default_excludes.txt +0 -0
- /package/skills/{doc-sync → j-doc-sync}/assets/doc_targets.md +0 -0
- /package/skills/{evaluate → j-evaluate}/assets/evaluation_invokation_template.yml +0 -0
- /package/skills/{evaluate → j-evaluate}/assets/evaluation_rapport_template.md +0 -0
- /package/skills/{idea → j-idea}/assets/idea_template.md +0 -0
- /package/skills/{init → j-init}/assets/.gitignore_template +0 -0
- /package/skills/{init → j-init}/assets/PROJECT_SUMMARY_template.md +0 -0
- /package/skills/{init → j-init}/assets/directory_structure.txt +0 -0
- /package/skills/{init → j-init}/assets/strategy_stub_template.md +0 -0
- /package/skills/{init → j-init}/assets/test-config_template.json +0 -0
- /package/skills/{init → j-init}/assets/workflow_template.json +0 -0
- /package/skills/{init → j-init}/scripts/apply-project-visibility.sh +0 -0
- /package/skills/{init → j-init}/scripts/detect-existing-codebase.sh +0 -0
- /package/skills/{init → j-init}/scripts/init.sh +0 -0
- /package/skills/{pi-plan → j-pi-plan}/assets/epic.json +0 -0
- /package/skills/{pi-plan → j-pi-plan}/assets/story_template.md +0 -0
- /package/skills/{publish → j-publish}/assets/ExportOptions.plist.template +0 -0
- /package/skills/{publish → j-publish}/assets/ownership-matrix.md +0 -0
- /package/skills/{publish → j-publish}/assets/publish.example.json +0 -0
- /package/skills/{publish → j-publish}/assets/publish.example.npm-ci.json +0 -0
- /package/skills/{publish → j-publish}/assets/publish.example.npm.json +0 -0
- /package/skills/{publish → j-publish}/assets/secrets-guide.md +0 -0
- /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-minimal.json +0 -0
- /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-with-empty-secrets.json +0 -0
- /package/skills/{publish → j-publish}/schemas/fixtures/npm-ci-with-workflow-path.json +0 -0
- /package/skills/{publish → j-publish}/scripts/check_target_config.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/droplet_pipeline.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/finalize_changelog.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/generate_release_notes.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/ios_pipeline.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/npm_pipeline.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/publish_common.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/reconcile_tags.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/run_gates.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/setup_wizard.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/show_history.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/suggest_semver_bump.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/validate_config.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/validate_droplet_env.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/validate_ios_env.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/validate_npm_ci_env.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/validate_npm_env.sh +0 -0
- /package/skills/{publish → j-publish}/scripts/write_ledger_entry.sh +0 -0
- /package/skills/{reconcile → j-reconcile}/assets/report_format.md +0 -0
- /package/skills/{reconcile-origin → j-reconcile-origin}/scripts/reconcile-origin.sh +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/SKILL.md +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/assets/.gitignore_template +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/assets/PROJECT_SUMMARY_template.md +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/assets/directory_structure.txt +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/assets/test-config_template.json +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/assets/workflow_template.json +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-new/scripts/init.sh +0 -0
- /package/skills/{skillify → j-skillify}/assets/init-old/SKILL.md +0 -0
- /package/skills/{status → j-status}/assets/output_format.md +0 -0
- /package/skills/{todo → j-todo}/assets/todo_template.md +0 -0
- /package/skills/{uncharted → j-uncharted}/assets/SEGMENT_PROPOSAL_TEMPLATE.md +0 -0
- /package/skills/{uncharted → j-uncharted}/scripts/apply-subsystem-cap.sh +0 -0
- /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.
|
|
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,
|
|
142
|
-
|
|
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
|
-
|
|
145
|
-
-
|
|
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 |
|