@jenga-ai/agent 1.0.1 → 1.1.1
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 +10 -7
- package/agents/developer.md +82 -2
- package/agents/scrum-master.md +215 -21
- package/agents/tester.md +90 -8
- package/hooks/on_session_end.sh +171 -20
- package/mcp/router/embedder.js +1 -1
- package/mcp/training_runner/index.js +239 -0
- package/mcp/training_runner/package-lock.json +1065 -0
- package/mcp/training_runner/package.json +15 -0
- package/package.json +14 -16
- package/scripts/check-permission-level.sh +107 -0
- package/scripts/check-publicignore-match.sh +122 -0
- package/scripts/check-worktree-liveness.sh +193 -0
- package/scripts/generate-rapport-manifest.sh +43 -0
- package/scripts/idea_manager.sh +47 -0
- package/scripts/install-worktree-commit-guard.sh +134 -0
- package/scripts/jenga-permission-level-switch.sh +109 -0
- package/scripts/smoke-harness.sh +139 -0
- package/scripts/validate-board.sh +62 -0
- package/scripts/with-lock.sh +158 -0
- package/scripts/worktree-remove-guard.sh +204 -0
- package/skills/clearify/SKILL.md +52 -0
- package/skills/close-story/SKILL.md +203 -0
- package/skills/close-story/scripts/check-story-closeable.sh +195 -0
- package/skills/close-story/scripts/compute-scope-divergence.sh +128 -0
- package/skills/close-story/scripts/extract-diff-stats.sh +48 -0
- package/skills/close-story/scripts/extract-task-diff-stats.sh +97 -0
- package/skills/close-story/scripts/update-task-frontmatter.sh +103 -0
- package/skills/commit/SKILL.md +30 -3
- package/skills/distribute/CONFIG_SCHEMA.md +148 -0
- package/skills/distribute/SKILL.md +173 -0
- package/skills/distribute/scripts/check-version.sh +74 -0
- package/skills/distribute/scripts/commit-version-bump.sh +108 -0
- package/skills/distribute/scripts/distribute-changes.sh +381 -0
- package/skills/do/SKILL.md +352 -1
- package/skills/do/assets/intent-vs-diff-prompt.md +69 -0
- package/skills/doc/assets/path-objectives.yaml +13 -0
- package/skills/doc-sync/SKILL.md +16 -0
- package/skills/doc-sync/assets/doc_targets.md +11 -0
- package/skills/idea/SKILL.md +56 -0
- package/skills/idea/assets/idea_handoff_template.md +26 -0
- package/skills/idea/assets/idea_template.md +3 -0
- package/skills/init/SKILL.md +101 -7
- package/skills/init/assets/directory_structure.txt +1 -0
- package/skills/init/assets/strategy_stub_template.md +38 -0
- package/skills/init/assets/workflow_template.json +1 -1
- package/skills/init/scripts/apply-project-visibility.sh +176 -0
- package/skills/init/scripts/detect-existing-codebase.sh +166 -0
- package/skills/init/scripts/init.sh +35 -1
- package/skills/jenga/SKILL.md +206 -14
- package/skills/jenga/scripts/board-scan.sh +238 -0
- package/skills/jenga/scripts/cascade-resolve.sh +297 -0
- package/skills/jenga/scripts/render-confirmation.sh +679 -0
- package/skills/jenga/scripts/render-picker.sh +439 -0
- package/skills/jenga/scripts/resolve-id.sh +367 -0
- package/skills/jenga-permission-level/SKILL.md +81 -0
- package/skills/proceed/SKILL.md +1 -1
- package/skills/publish/SKILL.md +8 -5
- package/skills/publish/assets/ci-contract.md +2 -2
- package/skills/publish/assets/ownership-matrix.md +1 -1
- package/skills/publish/scripts/finalize_changelog.sh +115 -0
- package/skills/publish/scripts/generate_release_notes.sh +475 -28
- package/skills/publish/scripts/npm_ci_pipeline.sh +44 -6
- package/skills/publish/scripts/publish_deploy.sh +38 -8
- package/skills/publish/scripts/run_gates.sh +2 -2
- package/skills/reconcile/SKILL.md +117 -5
- package/skills/reconcile/scripts/detect-unlinked-code.sh +741 -0
- package/skills/skillify/assets/init-new/assets/directory_structure.txt +5 -1
- package/skills/spinoff/SKILL.md +12 -7
- package/skills/todo/SKILL.md +2 -0
- package/skills/uncharted/SKILL.md +711 -0
- package/skills/uncharted/assets/SEGMENT_PROPOSAL_TEMPLATE.md +129 -0
- package/skills/uncharted/assets/UNDERSTANDING_DOC_TEMPLATE.md +160 -0
- package/skills/uncharted/scripts/apply-subsystem-cap.sh +573 -0
- package/skills/uncharted/scripts/detect-dependencies.sh +732 -0
- package/skills/uncharted/scripts/detect-tests.sh +553 -0
- package/skills/uncharted/scripts/discover-subsystems.sh +1029 -0
- package/skills/uncharted/scripts/enumerate-target.sh +470 -0
- package/skills/uncharted/scripts/import-source.sh +517 -0
- package/skills/uncharted/scripts/inspect-provenance.sh +573 -0
- package/skills/uncharted/scripts/resolve-segment-target.sh +640 -0
- package/skills/uncharted/scripts/run-engine.sh +655 -0
- package/skills/uncharted/scripts/validate-proposed-items.sh +125 -0
- package/skills/uncharted/scripts/write-backfilled-epics.sh +498 -0
- package/skills/wtf/SKILL.md +20 -0
- package/templates/CHANGELOG_TEMPLATE.md +13 -0
- package/templates/PROBLEM_RAPPORT_TEMPLATE.md +4 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +206 -10
- package/templates/permission-levels/README.md +73 -0
- package/templates/permission-levels/level-1-locked.json +71 -0
- package/templates/permission-levels/level-2-guarded.json +64 -0
- package/templates/permission-levels/level-3-standard.json +62 -0
- package/templates/permission-levels/level-4-elevated.json +60 -0
- package/templates/permission-levels/level-5-unrestricted.json +58 -0
- package/skills/convert/SKILL.md +0 -124
- package/skills/convert/convert_cli.py +0 -235
- package/skills/convert/tests/sample.csv +0 -4
- package/skills/convert/tests/sample.json +0 -5
- package/skills/convert/tests/sample.jsonl +0 -3
- package/skills/convert/tests/sample.yaml +0 -18
- package/skills/convert/tests/sample_obj.csv +0 -2
- package/skills/convert/tests/sample_obj.json +0 -9
- package/skills/mirror-public/SKILL.md +0 -237
- package/skills/mirror-public/assets/config.json +0 -5
- package/skills/mirror-public/scripts/mirror.sh +0 -374
- package/skills/self-sync/SKILL.md +0 -73
- package/skills/self-sync/scripts/run.js +0 -136
- package/skills/train/SKILL.md +0 -116
- package/skills/train/assets/dashboard-templates/classifiers.html +0 -106
- package/skills/train/assets/dashboard-templates/nlp.html +0 -102
- package/skills/train/assets/dashboard-templates/transformers.html +0 -98
- package/skills/train/assets/results-parsers/__init__.py +0 -9
- package/skills/train/assets/results-parsers/classifiers.py +0 -84
- package/skills/train/assets/results-parsers/nlp.py +0 -88
- package/skills/train/assets/results-parsers/reporter.py +0 -154
- package/skills/train/assets/results-parsers/transformers.py +0 -120
- package/skills/train/train_cli.py +0 -786
package/skills/do/SKILL.md
CHANGED
|
@@ -18,9 +18,256 @@ metadata:
|
|
|
18
18
|
|
|
19
19
|
## Instructions
|
|
20
20
|
|
|
21
|
+
### 0. Load threshold config
|
|
22
|
+
|
|
23
|
+
Read `project/configs/scope-thresholds.json`.
|
|
24
|
+
|
|
25
|
+
If the file does not exist, emit:
|
|
26
|
+
```
|
|
27
|
+
ERROR: project/configs/scope-thresholds.json not found. Cannot proceed.
|
|
28
|
+
```
|
|
29
|
+
and halt. Do not fall back to any default values.
|
|
30
|
+
|
|
31
|
+
If the file is not valid JSON, emit:
|
|
32
|
+
```
|
|
33
|
+
ERROR: project/configs/scope-thresholds.json is malformed (invalid JSON). Cannot proceed.
|
|
34
|
+
```
|
|
35
|
+
and halt.
|
|
36
|
+
|
|
37
|
+
Extract the following named values for use throughout this skill:
|
|
38
|
+
- `inline_max_files` — maximum files a task may touch to qualify for inline execution scope
|
|
39
|
+
- `inline_max_lines` — maximum total lines changed for inline scope
|
|
40
|
+
- `story_max_files` — maximum files a task may touch to qualify for story-scope bundling
|
|
41
|
+
- `bundle_lock_ttl_minutes` — time-to-live in minutes for a story-scope bundle lock
|
|
42
|
+
|
|
43
|
+
These values must be read fresh on each invocation. Never use hardcoded fallbacks.
|
|
44
|
+
|
|
21
45
|
### 1. Check for `project/todo.md`
|
|
22
46
|
Run `bash scripts/todo_manager.sh exists`. If it exits non-zero, inform the user there are no queued tasks and exit.
|
|
23
47
|
|
|
48
|
+
### 1.5. Story-Bundle Execution Mode
|
|
49
|
+
|
|
50
|
+
When `/do` is invoked with a story ID (e.g., `/do E##_S##`), skip steps 2–4 and enter story-bundle execution mode:
|
|
51
|
+
|
|
52
|
+
1. **Read the story file** from `project/board/stories/<E##_S##>_*.md`. Extract the `tasks:` list. If the story file does not exist, emit:
|
|
53
|
+
```
|
|
54
|
+
ERROR: Story file for <story_id> not found. Cannot execute bundle.
|
|
55
|
+
```
|
|
56
|
+
and halt.
|
|
57
|
+
|
|
58
|
+
#### Epic-Level Bundle Lock
|
|
59
|
+
|
|
60
|
+
Before proceeding, acquire the epic-level sequential lock for this bundle:
|
|
61
|
+
|
|
62
|
+
a. **Derive the lock file path**: `project/queue/epic-lock-<E##>.json` where `<E##>` is the epic ID extracted from the story ID.
|
|
63
|
+
|
|
64
|
+
b. **Check for an existing lock**:
|
|
65
|
+
- If `project/queue/epic-lock-<E##>.json` exists:
|
|
66
|
+
1. Parse the JSON and read the `started_at` field (ISO 8601 UTC timestamp).
|
|
67
|
+
2. Compute the lock age: `age_minutes = (now_utc - started_at) / 60`.
|
|
68
|
+
3. Read `bundle_lock_ttl_minutes` from `project/configs/scope-thresholds.json` (already loaded in step 0).
|
|
69
|
+
4. If `age_minutes < bundle_lock_ttl_minutes` (lock is **non-stale**), emit:
|
|
70
|
+
```
|
|
71
|
+
BLOCKED: Epic <E##> already has a running bundle (<bundle_story_id>, started <started_at>). Wait for it to complete or for the TTL to expire.
|
|
72
|
+
```
|
|
73
|
+
and **halt** — do not proceed with this bundle.
|
|
74
|
+
5. If `age_minutes >= bundle_lock_ttl_minutes` (lock is **stale**), delete it with `rm -f project/queue/epic-lock-<E##>.json` and continue to the write step below.
|
|
75
|
+
- If `project/queue/epic-lock-<E##>.json` does not exist, continue to the write step below.
|
|
76
|
+
|
|
77
|
+
c. **Write the lock atomically**:
|
|
78
|
+
1. Compose the lock JSON:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"epic_id": "<E##>",
|
|
82
|
+
"bundle_story_id": "<E##_S##>",
|
|
83
|
+
"started_at": "<current ISO 8601 UTC timestamp>"
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
2. Write this JSON to `project/queue/epic-lock-<E##>.json.tmp` (temporary file in the same directory).
|
|
87
|
+
3. Rename (move) `project/queue/epic-lock-<E##>.json.tmp` to `project/queue/epic-lock-<E##>.json`. This rename is atomic on POSIX filesystems and prevents any observer from reading a partially-written lock file.
|
|
88
|
+
|
|
89
|
+
> **Note:** Each epic has its own lock file keyed by `<E##>`. Bundles belonging to different epics have separate lock files and do not block each other.
|
|
90
|
+
|
|
91
|
+
> **Cleanup contract:** The epic lock file **must** be deleted on every exit path — success, failure, and interruption. Register a cleanup/trap handler immediately after writing the lock so that the lock is released even if the skill is interrupted mid-execution (e.g., `trap 'rm -f project/queue/epic-lock-<E##>.json' EXIT` in a shell implementation, or equivalent in other runtimes). Deleting a non-existent lock file must be idempotent — always use `rm -f` (never `rm` alone).
|
|
92
|
+
|
|
93
|
+
#### Pre-execution cross-bundle conflict check
|
|
94
|
+
|
|
95
|
+
After acquiring the epic lock and before writing the bundle manifest, scan all other active bundle manifests to detect file-level overlap with the current bundle:
|
|
96
|
+
|
|
97
|
+
1. **Glob other bundle manifests**: list all files matching `project/queue/bundle-*.json`. Exclude the current bundle's own file (`project/queue/bundle-<E##_S##>.json` — it does not exist yet at this point, so no special filter is needed; simply exclude any path whose basename equals `bundle-<E##_S##>.json`).
|
|
98
|
+
|
|
99
|
+
2. **If no other manifests exist**: skip steps 3–6 entirely — this step completes silently.
|
|
100
|
+
|
|
101
|
+
3. **For each other manifest file found**:
|
|
102
|
+
a. Parse the JSON and read its `task_changed_files` map.
|
|
103
|
+
b. Collect the union of all file-path arrays across every key in `task_changed_files` into a flat, deduplicated set called `other_touched_files`.
|
|
104
|
+
c. Record the other bundle's `story_id` (or derive it from the filename: `bundle-<story_id>.json`).
|
|
105
|
+
|
|
106
|
+
4. **Build the expected file set for the current bundle** (`current_expected_files`):
|
|
107
|
+
For each task in the current bundle's `tasks:` list:
|
|
108
|
+
a. Read the task file at `project/board/tasks/<task_id>_*.md`.
|
|
109
|
+
b. Extract file paths from the task's `scope_rationale` frontmatter field and from the full text of the task's `## Description` section. A string is treated as a file path if it contains a forward-slash (`/`) or a dot-separated extension (e.g. `.md`, `.json`, `.sh`, `.ts`, `.js`, `.py`). Extract all such tokens.
|
|
110
|
+
c. Add all extracted paths to `current_expected_files` (deduplicated set).
|
|
111
|
+
|
|
112
|
+
5. **Compute overlap**: for each other bundle scanned in step 3, compute the intersection of `other_touched_files` and `current_expected_files`.
|
|
113
|
+
|
|
114
|
+
6. **If any overlap is found**:
|
|
115
|
+
a. Emit the following log line to the console (one line per conflicting bundle):
|
|
116
|
+
```
|
|
117
|
+
[CROSS-BUNDLE CONFLICT] Bundle <current_story_id> and bundle <other_story_id> share expected files: <file1>, <file2>
|
|
118
|
+
```
|
|
119
|
+
b. Store the conflict data in memory as `pending_conflicts`:
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"<other_story_id>": ["<file1>", "<file2>"]
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
If multiple other bundles each have overlap, accumulate all of them under their respective story IDs in `pending_conflicts`.
|
|
126
|
+
|
|
127
|
+
7. **Pass `pending_conflicts` forward**: when writing the bundle manifest in the next step (step 2 below), initialise the `cross_bundle_conflicts` key in the manifest with the contents of `pending_conflicts` (or `{}` if no conflicts were found). See "### Bundle Manifest and Rollback Anchor" for the updated manifest structure.
|
|
128
|
+
|
|
129
|
+
> **This check is non-blocking.** Regardless of whether conflicts are found, execution always continues to step 2. The conflict data is recorded for later review only.
|
|
130
|
+
|
|
131
|
+
2. **Invoke rollback anchor**: write a bundle manifest at `project/queue/bundle-<E##_S##>.json` before the first task executes. See "### Bundle Manifest and Rollback Anchor" below for the full procedure.
|
|
132
|
+
|
|
133
|
+
3. **Spawn one developer subagent** in one shared worktree named `bundle-<E##_S##>`. This is the only developer subagent for the entire story bundle — do not spawn additional subagents per task.
|
|
134
|
+
|
|
135
|
+
4. **Execute tasks sequentially** in `tasks:` list order, within the same shared developer subagent context:
|
|
136
|
+
|
|
137
|
+
For each task in the `tasks:` list:
|
|
138
|
+
|
|
139
|
+
a. **Before the task begins** — write `status: In Progress` and `date_started: <today>` to the task's frontmatter using the file-locking protocol:
|
|
140
|
+
1. Locate the task file: `project/board/tasks/<task_id>_*.md`.
|
|
141
|
+
2. Check for an existing lock file at `project/board/tasks/<task_id>_*.md.lock`. If it exists and is less than 60 seconds old, wait 10 seconds and retry once. If still locked after the retry, log a warning and skip this status write (do not block task execution).
|
|
142
|
+
3. Create the lock file: write the current ISO 8601 timestamp into `project/board/tasks/<task_id>_*.md.lock`.
|
|
143
|
+
4. Update the task frontmatter fields `status: In Progress` and `date_started: <YYYY-MM-DD>` (today's date).
|
|
144
|
+
5. Delete the lock file immediately after the write completes (before step b).
|
|
145
|
+
|
|
146
|
+
b. **Pass task context** to the shared developer subagent: task file content (title, description, acceptance criteria), parent story file, and parent epic file.
|
|
147
|
+
|
|
148
|
+
c. **After successful task**: first run the **Intent-vs-Diff Check** (see `### 5.1. Intent-vs-Diff Check` below) for this task. Then write `status: Passed` and `date_completed: <today>` to the task's frontmatter using the file-locking protocol:
|
|
149
|
+
1. Check for an existing lock file at `project/board/tasks/<task_id>_*.md.lock`. If it exists and is less than 60 seconds old, wait 10 seconds and retry once. If still locked, log a warning and skip this status write.
|
|
150
|
+
2. Create the lock file: write the current ISO 8601 timestamp into `project/board/tasks/<task_id>_*.md.lock`.
|
|
151
|
+
3. Update the task frontmatter fields `status: Passed` and `date_completed: <YYYY-MM-DD>` (today's date).
|
|
152
|
+
4. Delete the lock file immediately after the write completes.
|
|
153
|
+
> The lock must be released before proceeding to task N+1. Never hold a lock across task execution.
|
|
154
|
+
|
|
155
|
+
c.1. **Post-task file extraction** — immediately after the status write in step c and before proceeding to the next task, record the files changed by this task into the bundle manifest:
|
|
156
|
+
1. Run `git diff --name-only HEAD~1` to obtain the list of files changed by the just-completed task. Capture each line as a relative file path. If the command returns empty output (the task made no commits), treat the result as an empty array `[]` — this is not an error.
|
|
157
|
+
2. Read the bundle manifest at `project/queue/bundle-<E##_S##>.json`.
|
|
158
|
+
3. Add or update the key `task_changed_files` in the manifest object. Set `task_changed_files[<task_id>]` to the captured file list (an array of strings, or `[]` if no files changed). If `task_changed_files` does not yet exist in the manifest, create it as an empty object first.
|
|
159
|
+
4. Write the updated manifest atomically:
|
|
160
|
+
a. Serialise the updated manifest to JSON.
|
|
161
|
+
b. Write the JSON to `project/queue/bundle-<E##_S##>.json.tmp`.
|
|
162
|
+
c. Rename (move) `project/queue/bundle-<E##_S##>.json.tmp` to `project/queue/bundle-<E##_S##>.json`. The rename is atomic on POSIX filesystems and prevents any consumer from reading a partially-written file.
|
|
163
|
+
> This step is mandatory before proceeding to task N+1. The extraction must complete (even if the file list is empty) before the next task begins.
|
|
164
|
+
|
|
165
|
+
c.2. **Conflict report** — immediately after step c.1, compare the extracted file list against the files the task was expected to touch, and write a conflict report if unexpected files are found:
|
|
166
|
+
|
|
167
|
+
1. **Extract expected files** from the task's frontmatter field `scope_rationale` and from the task's `## Description` section. Use a best-effort prose heuristic: split the text on whitespace and punctuation, then retain any token that either (a) contains a `/` character or (b) matches the pattern `*.*` (a dot surrounded by non-dot characters on both sides, e.g. `SKILL.md`, `foo.json`). Collect all retained tokens into a set called `expected_files`. This is intentionally permissive — false positives (expected files that were never actually changed) are acceptable and produce no report.
|
|
168
|
+
|
|
169
|
+
2. **Compute unexpected files**: let `actual_files` = the array stored at `task_changed_files[<task_id>]` in the bundle manifest (from step c.1). Compute `unexpected = actual_files − expected_files` (set difference: files in `actual_files` that have no match in `expected_files`). Matching is case-sensitive and exact against the relative path or the basename of the path — a token like `SKILL.md` matches any actual file whose basename is `SKILL.md` (e.g. `skills/do/SKILL.md`).
|
|
170
|
+
|
|
171
|
+
3. **If `unexpected` is non-empty**:
|
|
172
|
+
a. Write a Markdown conflict report to `project/queue/conflict-<task_id>.md` with the following structure:
|
|
173
|
+
```markdown
|
|
174
|
+
# Conflict Report: <task_id>
|
|
175
|
+
|
|
176
|
+
**Generated:** <ISO 8601 UTC timestamp>
|
|
177
|
+
**Bundle:** <E##_S##>
|
|
178
|
+
|
|
179
|
+
## Task ID
|
|
180
|
+
<task_id>
|
|
181
|
+
|
|
182
|
+
## Expected Files
|
|
183
|
+
Files inferred from scope_rationale and description:
|
|
184
|
+
- <file1>
|
|
185
|
+
- ...
|
|
186
|
+
|
|
187
|
+
## Actual Files Changed
|
|
188
|
+
Files changed by this task (from git diff):
|
|
189
|
+
- <file1>
|
|
190
|
+
- ...
|
|
191
|
+
|
|
192
|
+
## Unexpected Files
|
|
193
|
+
Files changed that were not anticipated by the task definition:
|
|
194
|
+
- <file1>
|
|
195
|
+
- ...
|
|
196
|
+
```
|
|
197
|
+
b. Read the bundle manifest at `project/queue/bundle-<E##_S##>.json`.
|
|
198
|
+
c. Append `<task_id>` to the `conflict_reports` array in the manifest. If the key `conflict_reports` does not yet exist, create it as an empty array first.
|
|
199
|
+
d. Write the updated manifest atomically (tmp-file rename pattern — same as step c.1.4).
|
|
200
|
+
|
|
201
|
+
4. **If `unexpected` is empty**: skip this step entirely. Do not write a conflict report. Do not modify the bundle manifest.
|
|
202
|
+
|
|
203
|
+
> **This step is non-blocking.** A conflict report does NOT affect the task's `Passed` status or halt bundle execution. It is informational only — a human can review `project/queue/conflict-<task_id>.md` after the bundle completes.
|
|
204
|
+
|
|
205
|
+
d. **After task failure** — write `status: Failed` to the task's frontmatter using the file-locking protocol:
|
|
206
|
+
1. Check for an existing lock file at `project/board/tasks/<task_id>_*.md.lock`. If it exists and is less than 60 seconds old, wait 10 seconds and retry once. If still locked, log a warning and skip this status write.
|
|
207
|
+
2. Create the lock file: write the current ISO 8601 timestamp into `project/board/tasks/<task_id>_*.md.lock`.
|
|
208
|
+
3. Update the task frontmatter field `status: Failed`.
|
|
209
|
+
4. Delete the lock file immediately after the write completes.
|
|
210
|
+
Then invoke the rollback anchor cleanup procedure (see "### Bundle Manifest and Rollback Anchor" — failure path). After the rollback anchor completes, **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`. Mark the bundle as failed and **halt** — do not execute any remaining tasks in the sequence.
|
|
211
|
+
|
|
212
|
+
5. **Post-bundle verification** (runs only if all tasks completed without failure):
|
|
213
|
+
- Inspect each task in the bundle for `needs_docs: true` in its frontmatter.
|
|
214
|
+
- **If any task has `needs_docs: true`**: invoke the tester agent once for the full story. Pass the story ID, the list of all task IDs in the bundle, and the shared worktree path. The tester is responsible for updating individual task statuses.
|
|
215
|
+
- **If all tasks have `needs_docs: false`**: the developer agent self-verifies — reviews each task's implementation against its acceptance criteria without invoking the tester. After self-verification passes, write `status: Passed` and `date_completed: <YYYY-MM-DD>` (today's date) to each task file using the file-locking protocol (steps c.1–c.4 above). No tester invocation occurs.
|
|
216
|
+
|
|
217
|
+
6. **Cleanup**: on successful bundle completion, invoke the rollback anchor success path (see "### Bundle Manifest and Rollback Anchor" — success path) to delete the bundle manifest. Then **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`.
|
|
218
|
+
|
|
219
|
+
### Bundle Manifest and Rollback Anchor
|
|
220
|
+
|
|
221
|
+
The bundle manifest records the repository state before any task in the bundle executes. It serves as the anchor for rollback on failure and as a reference for conflict reports (E32_S07) and concurrency locks (E32_S08).
|
|
222
|
+
|
|
223
|
+
#### Before the first task executes
|
|
224
|
+
|
|
225
|
+
1. Run `git rev-parse HEAD` to capture the current HEAD SHA as `anchor_sha`.
|
|
226
|
+
2. Write `project/queue/bundle-<E##_S##>.json` with the following structure:
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"story_id": "<E##_S##>",
|
|
230
|
+
"anchor_sha": "<SHA from git rev-parse HEAD>",
|
|
231
|
+
"started_at": "<ISO 8601 UTC timestamp>",
|
|
232
|
+
"tasks": ["<E##_S##_T##>", "..."],
|
|
233
|
+
"task_changed_files": {},
|
|
234
|
+
"conflict_reports": [],
|
|
235
|
+
"cross_bundle_conflicts": {}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
- `story_id`: the story ID for this bundle (e.g. `E32_S05`)
|
|
239
|
+
- `anchor_sha`: the full 40-character SHA returned by `git rev-parse HEAD`
|
|
240
|
+
- `started_at`: current UTC timestamp in ISO 8601 format (e.g. `2026-08-16T12:00:00Z`)
|
|
241
|
+
- `tasks`: ordered array of task IDs drawn from the story's `tasks:` frontmatter list
|
|
242
|
+
- `task_changed_files`: starts as an empty object `{}`; populated after each task completes (see step 4c.1). Each key is a task ID and each value is an array of relative file paths changed by that task.
|
|
243
|
+
- `conflict_reports`: starts as an empty array `[]`; populated after each task's step 4c.2 conflict check. Each entry is a task ID string for which a conflict report was written to `project/queue/conflict-<task_id>.md`.
|
|
244
|
+
- `cross_bundle_conflicts`: populated from the pre-execution conflict check (see "Pre-execution cross-bundle conflict check" above). Each key is the `story_id` of a conflicting bundle and each value is an array of overlapping file paths. Initialised with the `pending_conflicts` data collected during the conflict check; if no conflicts were found, initialised as `{}`.
|
|
245
|
+
|
|
246
|
+
Do not proceed to the first task until this file is written successfully.
|
|
247
|
+
|
|
248
|
+
#### On any task failure (failure path)
|
|
249
|
+
|
|
250
|
+
Execute the following steps in order. Do not skip any step.
|
|
251
|
+
|
|
252
|
+
1. **Save partial diff**: run `git diff <anchor_sha> HEAD` and write the output to `project/queue/bundle-<E##_S##>-partial.patch`. This captures all commits made since the anchor, providing a record of partial work for diagnosis.
|
|
253
|
+
2. **Verify clean worktree**: run `git status --porcelain`. If the output is non-empty, there are uncommitted changes that would cause `git reset --hard` to error or lose work. In this case, emit:
|
|
254
|
+
```
|
|
255
|
+
ROLLBACK WARNING: worktree has uncommitted changes. Stashing before reset.
|
|
256
|
+
```
|
|
257
|
+
Then run `git stash` before proceeding. This ensures the reset completes without git complaints.
|
|
258
|
+
3. **Reset to anchor**: run `git reset --hard <anchor_sha>`. The repository returns to the exact state it was in before the bundle started.
|
|
259
|
+
4. **Delete bundle manifest**: remove `project/queue/bundle-<E##_S##>.json`.
|
|
260
|
+
|
|
261
|
+
After completing the failure path, halt bundle execution. Do not execute any remaining tasks in the sequence.
|
|
262
|
+
|
|
263
|
+
#### On successful bundle completion (success path)
|
|
264
|
+
|
|
265
|
+
1. **Delete bundle manifest**: remove `project/queue/bundle-<E##_S##>.json`.
|
|
266
|
+
|
|
267
|
+
No patch file is written on success.
|
|
268
|
+
|
|
269
|
+
If `/do` is invoked with a task ID (`E##_S##_T##`) or a plain-text title, skip this section and use the normal task execution path (steps 2–8 below).
|
|
270
|
+
|
|
24
271
|
### 2. List tasks and let the user choose
|
|
25
272
|
Run `bash scripts/todo_manager.sh list` to display the queued tasks. Ask the user:
|
|
26
273
|
- Execute a specific task (by number or title)
|
|
@@ -52,6 +299,76 @@ Before starting:
|
|
|
52
299
|
2. If the file does not exist, warn the user and skip — do not proceed with a task that has no scrum board definition
|
|
53
300
|
3. Present a brief summary of the task: title, acceptance criteria, parent story, parent epic
|
|
54
301
|
|
|
302
|
+
### 4.1. Override validation
|
|
303
|
+
|
|
304
|
+
Before invoking the developer, check whether this task was manually scoped by a human operator.
|
|
305
|
+
|
|
306
|
+
1. Read `jenga_assigned` from the resolved task's frontmatter.
|
|
307
|
+
2. If `jenga_assigned` is `true` or the field is absent — proceed to step 4.2 without any further check.
|
|
308
|
+
3. If `jenga_assigned` is `false`:
|
|
309
|
+
a. Read `override_justification` from the task's frontmatter.
|
|
310
|
+
b. If `override_justification` is absent or its value is an empty string, **halt execution** and emit:
|
|
311
|
+
```
|
|
312
|
+
OVERRIDE VALIDATION ERROR [<task_id>]: jenga_assigned is false but override_justification is missing or empty. Add a justification before proceeding.
|
|
313
|
+
```
|
|
314
|
+
Do not invoke the developer. Do not remove the task from `project/todo.md`. Return control to the user.
|
|
315
|
+
c. If `override_justification` is present and non-empty, log:
|
|
316
|
+
```
|
|
317
|
+
Override acknowledged for <task_id>: <override_justification>
|
|
318
|
+
```
|
|
319
|
+
Then proceed to step 4.2.
|
|
320
|
+
|
|
321
|
+
### 4.2. Inline Execution Path (execution_scope: inline)
|
|
322
|
+
|
|
323
|
+
After resolving the task context (step 4) and passing override validation (step 4.1), read `execution_scope` from the task frontmatter.
|
|
324
|
+
|
|
325
|
+
**Locked-task dispatch guard (defense-in-depth).** Before branching on `execution_scope` below, read `crucial_level` from the task frontmatter (per `templates/SCRUM_BOARD_SCHEMA.md`'s Crucial Flag Fields). If `crucial_level: locked`:
|
|
326
|
+
|
|
327
|
+
- This task MUST be routed through the inline execution path below — no worktree, no developer subagent — regardless of what `execution_scope` currently reads. This guards against a locked task reaching dispatch with a non-`inline` `execution_scope` (a race, a manually edited file, or a task added to a story's `tasks:` list after `skills/jenga/SKILL.md` Phase 0.5's Rule 4 last ran).
|
|
328
|
+
- If `execution_scope` is already `inline`, proceed directly to the inline steps below — no correction needed.
|
|
329
|
+
- If `execution_scope` is anything other than `inline` (absent, `task`, `story`, or `epic`), auto-correct it to `inline` in the task frontmatter now, and record the correction using the **same logged-note convention** as `skills/jenga/SKILL.md` Phase 0.5 Rule 4 (do not invent a second, inconsistent logging mechanism):
|
|
330
|
+
- Append to the task's `override_justification` frontmatter field:
|
|
331
|
+
```
|
|
332
|
+
override_justification: "/do dispatch guard auto-correction <date>: execution_scope forced from '<previous_value>' to 'inline' because crucial_level: locked."
|
|
333
|
+
```
|
|
334
|
+
- Then emit (non-fatally — do not halt):
|
|
335
|
+
```
|
|
336
|
+
AUTO-CORRECTION [<task_id>]: crucial_level=locked requires execution_scope=inline; corrected from "<previous_value>" to "inline".
|
|
337
|
+
```
|
|
338
|
+
- Then proceed to the inline steps below with the now-corrected `execution_scope: inline`.
|
|
339
|
+
- **Under no circumstance does a `crucial_level: locked` task fall through to step 5** (developer agent invocation / worktree creation) — this applies whether the task was resolved individually or would otherwise have entered the normal per-task worktree-creation flow.
|
|
340
|
+
|
|
341
|
+
**If `execution_scope: inline`** (including tasks corrected above), execute the task directly in the current session without spawning a developer subagent:
|
|
342
|
+
|
|
343
|
+
1. Read the task file and load its full content (description, acceptance criteria). Do NOT create a worktree. Do NOT spawn a developer subagent.
|
|
344
|
+
2. Implement the task inline — make the required changes to files directly in the current session.
|
|
345
|
+
3. Run the smoke test harness before committing anything:
|
|
346
|
+
- Run `bash scripts/smoke-harness.sh <changed_file>...`, passing the paths changed in step 2. With no arguments the harness infers them from `git diff --name-only HEAD`. It exits `0` on pass and `1` on failure.
|
|
347
|
+
- If `scripts/smoke-harness.sh` does not exist, log a warning and treat the result as a pass:
|
|
348
|
+
```
|
|
349
|
+
WARNING [<task_id>]: scripts/smoke-harness.sh not found. Smoke test skipped (stub pass).
|
|
350
|
+
```
|
|
351
|
+
4. **If the smoke test exits non-zero**:
|
|
352
|
+
- Write `status: Failed` to the task's frontmatter.
|
|
353
|
+
- Emit:
|
|
354
|
+
```
|
|
355
|
+
INLINE TASK FAILED [<task_id>]: smoke test returned non-zero exit code. Task marked Failed. Halting.
|
|
356
|
+
```
|
|
357
|
+
- Do not commit. Do not proceed to the next task.
|
|
358
|
+
5. **If the smoke test passes**:
|
|
359
|
+
- Commit the changes using the standard commit convention (`task(<task_id>): <short description>`) via `/commit` in inline mode (E32_S04_T03).
|
|
360
|
+
- Run the **Intent-vs-Diff Check** (see `### 5.1. Intent-vs-Diff Check` below) for this task.
|
|
361
|
+
- Self-verify the implementation against the acceptance criteria.
|
|
362
|
+
- Write `status: Passed` and `date_completed: <today>` to the task's frontmatter if verification passes.
|
|
363
|
+
- Remove the task from `project/todo.md`.
|
|
364
|
+
6. `inline` tasks do not invoke the tester agent — the smoke test and self-verification are the only gates.
|
|
365
|
+
7. `inline` tasks always have `needs_docs: false` — skip plan and summary documentation for the implemented task.
|
|
366
|
+
8. Continue to `### 6. Verify documentation`, then `### 7. After successful completion`.
|
|
367
|
+
|
|
368
|
+
If the implementation cannot be completed inline (scope is larger than anticipated), abort and re-route to the normal developer path (step 5) — unless `crucial_level: locked`, in which case do not re-route; re-attempt inline or halt and report, per the locked-task dispatch guard above.
|
|
369
|
+
|
|
370
|
+
**If `execution_scope` is not `inline`** (or is absent / `task` / `story` / `epic`) **and `crucial_level` is not `locked`**, proceed to step 5 (invoke the developer agent) as normal.
|
|
371
|
+
|
|
55
372
|
### 5. Invoke the developer agent
|
|
56
373
|
Pass the following to the developer agent:
|
|
57
374
|
|
|
@@ -68,6 +385,40 @@ The developer agent will:
|
|
|
68
385
|
- Implement, commit at milestones, and invoke the tester agent
|
|
69
386
|
- Return when the tester has verified the work
|
|
70
387
|
|
|
388
|
+
### 5.1. Intent-vs-Diff Check (needs_docs: false only)
|
|
389
|
+
|
|
390
|
+
After the developer agent returns (or after inline execution completes), run the following check if the task has `needs_docs: false` in its frontmatter. If `needs_docs: true`, skip this check entirely — the full documentation lifecycle handles divergence detection for those tasks.
|
|
391
|
+
|
|
392
|
+
**Steps:**
|
|
393
|
+
|
|
394
|
+
1. Read `needs_docs` from the task's frontmatter. If `needs_docs: true` (or absent and defaulting to `true`), skip to step 6.
|
|
395
|
+
|
|
396
|
+
2. Run `git diff --name-only HEAD~1` to retrieve the list of changed file names (relative paths, one per line).
|
|
397
|
+
|
|
398
|
+
3. Read the prompt template from `skills/do/assets/intent-vs-diff-prompt.md`. Extract the prompt block (the content between the triple backticks under `## Prompt`).
|
|
399
|
+
|
|
400
|
+
4. Substitute the placeholders:
|
|
401
|
+
- `{description}` — full text of the task's `## Description` section
|
|
402
|
+
- `{acceptance_criteria}` — full text of the task's `## Acceptance Criteria` section
|
|
403
|
+
- `{changed_files}` — newline-separated output from step 2
|
|
404
|
+
|
|
405
|
+
5. Invoke the LLM with the constructed prompt (using the orchestrating agent's LLM access). Ask for a JSON array response only.
|
|
406
|
+
|
|
407
|
+
6. Parse the LLM response as a JSON array:
|
|
408
|
+
- If parsing fails (malformed JSON): treat as `[]`, emit: `[intent-vs-diff] LLM response was not valid JSON; treating as no divergence.`, and continue.
|
|
409
|
+
- If the array is empty (`[]`): no action — do not modify the task frontmatter.
|
|
410
|
+
- If the array is non-empty: write `divergence_flag: true` to the task's frontmatter, then emit:
|
|
411
|
+
```
|
|
412
|
+
[DIVERGENCE WARNING] Task <task_id>: the following files were changed but are not mentioned or inferable from the task description:
|
|
413
|
+
- <file1>
|
|
414
|
+
- <file2>
|
|
415
|
+
This is a non-blocking warning. Task outcome is not affected.
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**This check is non-blocking.** It does not change the task's Passed/Failed outcome. It only writes `divergence_flag: true` and emits a warning for human review. Execution continues regardless of the check result.
|
|
419
|
+
|
|
420
|
+
**Prompt calibration:** The prompt in `skills/do/assets/intent-vs-diff-prompt.md` is tuned to flag only files with zero plausible connection to the stated task. Test files, documentation files, lock files, and clearly implied files are excluded from flagging. See the `## False-Positive Tuning Rationale` section in the prompt template for full details.
|
|
421
|
+
|
|
71
422
|
### 6. Verify documentation
|
|
72
423
|
After the developer completes the task, confirm the following documentation was written:
|
|
73
424
|
- **Execution plan** — `project/documentation/plans/<E##_S##_T##>-plan.md` must exist (written by the developer before starting work)
|
|
@@ -78,7 +429,7 @@ If either file is missing, ask the developer to produce it before continuing.
|
|
|
78
429
|
Additionally, if the completed work introduces user-facing changes, update `README.md` and `WARP.md` accordingly.
|
|
79
430
|
|
|
80
431
|
### 7. After successful completion
|
|
81
|
-
- Check for any `_INSTRUCTIONS.md` files in
|
|
432
|
+
- Check for any `_INSTRUCTIONS.md` files in `project/instructions/` whose ID matches the completed task. If found, present them to the user and explain that these actions must be completed before the feature will work correctly.
|
|
82
433
|
- Invoke the `/commit` skill to commit the work (if not already committed by the developer)
|
|
83
434
|
- Run `bash scripts/todo_manager.sh remove '<task title>'` to remove the completed task from `project/todo.md`
|
|
84
435
|
- Run `bash scripts/todo_manager.sh teardown` to delete `project/todo.md` if it is now effectively empty
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Intent-vs-Diff LLM Prompt Template
|
|
2
|
+
|
|
3
|
+
This file contains the structured prompt used by `/do` to compare a completed task's stated intent against its actual diff. It is invoked **only** for tasks where `needs_docs: false`.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
After a `needs_docs: false` task completes, `/do` runs `git diff --name-only HEAD~1` to get the list of changed file names and passes them — along with the task description and acceptance criteria — to the LLM using the prompt below. The LLM identifies any files that fall outside the expected scope of the task, enabling early detection of unregistered scope expansion.
|
|
8
|
+
|
|
9
|
+
## False-Positive Tuning Rationale
|
|
10
|
+
|
|
11
|
+
The prompt is calibrated to minimize false positives:
|
|
12
|
+
|
|
13
|
+
1. **Test file exemption**: Test files that correspond to source files explicitly mentioned in the task description are NOT flagged. Adding tests is universally expected and implied by any implementation task.
|
|
14
|
+
2. **Documentation file exemption**: Files like `README.md`, `WARP.md`, `CHANGELOG.md`, and any `*.md` in a `docs/` directory are NOT flagged. Documentation updates are standard outputs of any change.
|
|
15
|
+
3. **Inferability threshold — both conditions required**: A file is only flagged when it is BOTH (a) not mentioned by name in the description, AND (b) not clearly inferable from what the description says. A task that says "update the login handler" implicitly covers the login handler's test file, its dependency injector, and related middleware — even if those are not named. Only files with zero connection to the stated task are flagged.
|
|
16
|
+
4. **JSON-only output**: The LLM is asked to return only a JSON array to eliminate ambiguity in parsing the response.
|
|
17
|
+
5. **Config/lock file exemption**: `package-lock.json`, `yarn.lock`, `*.lock`, and other machine-managed files are NOT flagged — they change as a side-effect of dependency changes and are never the primary intent of a task.
|
|
18
|
+
|
|
19
|
+
## Prompt
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
You are reviewing a completed task to check if the implementation stayed within scope.
|
|
23
|
+
|
|
24
|
+
Task description: {description}
|
|
25
|
+
|
|
26
|
+
Acceptance criteria:
|
|
27
|
+
{acceptance_criteria}
|
|
28
|
+
|
|
29
|
+
Changed files:
|
|
30
|
+
{changed_files}
|
|
31
|
+
|
|
32
|
+
Your job: identify any changed files that are NOT mentioned and NOT clearly inferable from the task description or acceptance criteria above.
|
|
33
|
+
|
|
34
|
+
Rules for what NOT to flag:
|
|
35
|
+
- Do not flag test files (*.test.*, *.spec.*, files in __tests__/ or test/ directories) for source files that are explicitly mentioned or clearly implied in the task.
|
|
36
|
+
- Do not flag documentation files (*.md, files in docs/ directories, README, WARP.md, CHANGELOG).
|
|
37
|
+
- Do not flag lock files (package-lock.json, yarn.lock, *.lock, *.sum) or generated files (*.generated.*, dist/, build/).
|
|
38
|
+
- Do not flag configuration files (*.config.*, .env.example, tsconfig.json) unless the task has zero connection to configuration.
|
|
39
|
+
- Only flag a file when it has zero plausible connection to the stated task description. If you can construct a reasonable sentence explaining why the file might be touched given the task description, do not flag it.
|
|
40
|
+
|
|
41
|
+
Return ONLY a JSON array of file paths that are unexpected scope expansions. If all files are expected or fall under the exemptions above, return an empty array.
|
|
42
|
+
|
|
43
|
+
Examples of correct output:
|
|
44
|
+
- All files expected: []
|
|
45
|
+
- Two unexpected files: ["src/billing/invoice.ts", "scripts/deploy.sh"]
|
|
46
|
+
|
|
47
|
+
Do not include any explanation, commentary, or text outside the JSON array.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Usage in `/do`
|
|
51
|
+
|
|
52
|
+
When the check runs, replace the template placeholders as follows:
|
|
53
|
+
|
|
54
|
+
- `{description}` — the full text of the task's `## Description` section from the task board file
|
|
55
|
+
- `{acceptance_criteria}` — the full text of the task's `## Acceptance Criteria` section (each criterion on its own line, including the `- [ ]` or `- [x]` prefix)
|
|
56
|
+
- `{changed_files}` — the newline-separated output of `git diff --name-only HEAD~1`, one file path per line
|
|
57
|
+
|
|
58
|
+
After receiving the LLM response:
|
|
59
|
+
|
|
60
|
+
1. Attempt to parse the response as a JSON array.
|
|
61
|
+
2. If parsing fails (malformed JSON), treat it as `[]` — do not flag divergence. Emit a debug note: `[intent-vs-diff] LLM response was not valid JSON; treating as no divergence.`
|
|
62
|
+
3. If the array is empty (`[]`), proceed without modifying the task frontmatter.
|
|
63
|
+
4. If the array is non-empty, write `divergence_flag: true` to the task's frontmatter and emit the warning:
|
|
64
|
+
```
|
|
65
|
+
[DIVERGENCE WARNING] Task <task_id>: the following files were changed but are not mentioned or inferable from the task description:
|
|
66
|
+
- <file1>
|
|
67
|
+
- <file2>
|
|
68
|
+
This is a non-blocking warning. Task outcome is not affected.
|
|
69
|
+
```
|
|
@@ -36,3 +36,16 @@ rules:
|
|
|
36
36
|
required_sections:
|
|
37
37
|
- Release Entries
|
|
38
38
|
- Notable Changes
|
|
39
|
+
- path: docs/STRATEGY.md
|
|
40
|
+
objective: strategy brief
|
|
41
|
+
summary: Produce a high-level strategy brief suitable for investors and strategic partners. Covers vision, value proposition, scope, and target audience. Does not include revenue model, pricing, or competitive analysis.
|
|
42
|
+
required_sections:
|
|
43
|
+
- Vision
|
|
44
|
+
- Value Proposition
|
|
45
|
+
- Scope
|
|
46
|
+
- Target Audience
|
|
47
|
+
generation_rules:
|
|
48
|
+
tone: Write for an investor or strategic partner audience. Use clear, confident language. Avoid jargon and internal shorthand. Do not use first-person plural ("we") excessively — prefer direct statements about the project.
|
|
49
|
+
sourcing: Draw content exclusively from PROJECT_SUMMARY.md and existing docs/. Do not invent facts, figures, or claims not present in the source material.
|
|
50
|
+
missing_fields: If the project has insufficient context to fill a section, produce a stub with the section header and a clearly marked note — e.g. "<!-- TODO: fill in once product direction is confirmed -->" — rather than erroring or hallucinating content.
|
|
51
|
+
exclusions: Do not include revenue model, pricing strategy, monetisation plans, competitive analysis, or financial projections. If any of these are present in source files, omit them silently.
|
package/skills/doc-sync/SKILL.md
CHANGED
|
@@ -87,6 +87,21 @@ For each update target and its resolved sources:
|
|
|
87
87
|
- Outdated examples, wrong flag names, stale code snippets.
|
|
88
88
|
- Incorrect or missing configuration keys/values.
|
|
89
89
|
|
|
90
|
+
#### 4a. Cross-reference `.publicignore` for "missing documentation" candidates
|
|
91
|
+
|
|
92
|
+
Every candidate identified above as "missing documentation for new things added in source" ships publicly by default unless this project has adopted `/mirror-public`. Before flagging any such candidate, check whether it's actually private-only:
|
|
93
|
+
|
|
94
|
+
1. **Check for `.publicignore` at the repo root.** Most projects using this framework will not have one (they haven't adopted `/mirror-public`) — if it's absent, **skip this entire sub-step**. Fall through to flagging every "missing documentation" candidate exactly as `3.` above already would, with no further filtering.
|
|
95
|
+
2. **If `.publicignore` exists**, for each "missing documentation" candidate, determine its source path (relative to the repo root) and classify it by running:
|
|
96
|
+
```
|
|
97
|
+
scripts/check-publicignore-match.sh <path> [<path> ...]
|
|
98
|
+
```
|
|
99
|
+
This reuses `/mirror-public`'s own `mirror.sh` matching logic (`rsync --exclude-from=.publicignore`) — a file this script reports `BLOCKED` is guaranteed to be a file `/mirror-public --dry-run` would also report as "would be blocked", and vice versa for `PUBLIC`. It needs no network access and does not require `/mirror-public` to be configured.
|
|
100
|
+
3. **`BLOCKED`** → do not flag this candidate as missing documentation. It's private-only and will never ship to the public mirror, so public docs coverage is not applicable.
|
|
101
|
+
4. **`PUBLIC`** → flag it as usual in step 5's report, and name `README.md` and `project/.wiki/documentation.md` (the confirmed canonical full-reference doc — see `assets/doc_targets.md`) as the target docs to check for coverage of this item.
|
|
102
|
+
|
|
103
|
+
This sub-step only changes what gets flagged as "missing documentation" in step 3's third bullet — it does not affect the other three drift categories (renamed/removed references, outdated examples, incorrect config keys), which are flagged regardless of `.publicignore` since they concern existing documentation content, not public-shipping coverage of new source additions.
|
|
104
|
+
|
|
90
105
|
### 5. Report findings before updating
|
|
91
106
|
|
|
92
107
|
Before making any writes, present a concise drift summary per file:
|
|
@@ -165,3 +180,4 @@ If minification could not reach the target, note: `⚠️ docs/API.md reduced to
|
|
|
165
180
|
|
|
166
181
|
- `assets/doc_targets.md` — Editable list of documentation files this skill checks by default.
|
|
167
182
|
- `assets/default_excludes.txt` — Paths always excluded from source analysis unless overridden.
|
|
183
|
+
- `scripts/check-publicignore-match.sh` (repo root) — Used in step 4a to classify "missing documentation" candidates as `PUBLIC`/`BLOCKED` per `.publicignore`, reusing `/mirror-public`'s exact matching semantics.
|
|
@@ -8,7 +8,18 @@ Add one path per line inside the list below. Blank lines and lines starting with
|
|
|
8
8
|
|
|
9
9
|
<!-- Add your project's documentation files here, one per line -->
|
|
10
10
|
README.md
|
|
11
|
+
project/.wiki/documentation.md
|
|
11
12
|
<!-- docs/API.md -->
|
|
12
13
|
<!-- docs/config.md -->
|
|
13
14
|
<!-- CHANGELOG.md -->
|
|
14
15
|
<!-- CONTRIBUTING.md -->
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
Note: project/.wiki/documentation.md is the confirmed-canonical full
|
|
19
|
+
skill-reference doc (README.md links to it directly as "Full reference").
|
|
20
|
+
A near-duplicate, project/documentation/documentation.md, has independently
|
|
21
|
+
diverged from this canonical copy — see E28_S03_T01's execution summary for
|
|
22
|
+
the investigation, and story E38_S01 for the planned consolidation. Do not
|
|
23
|
+
add project/documentation/documentation.md here until that consolidation
|
|
24
|
+
lands.
|
|
25
|
+
-->
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: idea
|
|
3
|
+
description: Capture a loosely-defined idea to project/ideas.md — a lightweight, "maybe someday" log with no board or promotion overhead.
|
|
4
|
+
keywords:
|
|
5
|
+
- idea
|
|
6
|
+
- capture idea
|
|
7
|
+
- log idea
|
|
8
|
+
- brain dump
|
|
9
|
+
- maybe someday
|
|
10
|
+
examples:
|
|
11
|
+
- "capture this as an idea"
|
|
12
|
+
- "log this idea for later"
|
|
13
|
+
- "I have a rough idea I want to jot down"
|
|
14
|
+
metadata:
|
|
15
|
+
prefered_agent: scrum-master
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Idea — Lightweight Idea Capture
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
1. **Ensure `project/ideas.md` exists** — If it doesn't exist, it will be auto-created by `idea_manager.sh` from `skills/idea/assets/idea_template.md` — no manual action needed.
|
|
23
|
+
|
|
24
|
+
2. **Ask the user about the idea:**
|
|
25
|
+
- What's the idea?
|
|
26
|
+
- Any known context worth noting (why it came up, what it might relate to)?
|
|
27
|
+
|
|
28
|
+
Keep this light — `/idea` is a low-overhead capture, not a structured mission intake like `/todo`.
|
|
29
|
+
|
|
30
|
+
3. **Add to `project/ideas.md`** by running:
|
|
31
|
+
```
|
|
32
|
+
bash scripts/idea_manager.sh add '<idea>'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
4. **Ask the user**: "Capture another idea, or done?"
|
|
36
|
+
- If **another** — go back to step 2.
|
|
37
|
+
- If **done** — exit.
|
|
38
|
+
|
|
39
|
+
Unlike `/todo`, `/idea` never offers to execute, refine, or promote the captured idea(s) at the end. There is no `/do`-style follow-up here — `/idea` has no refine or promotion logic of its own.
|
|
40
|
+
|
|
41
|
+
## For Reference Only — Promotion Convention (not implemented here)
|
|
42
|
+
|
|
43
|
+
`/idea` does not implement any refine or promotion mechanism. This section documents, for reference, how promotion is expected to work elsewhere so future flows stay consistent:
|
|
44
|
+
|
|
45
|
+
- **Promoting an idea** means re-running `/brainstorm` on it, which routes onward to `/btw` or `/todo` as normal. That routing behavior already exists and is out of scope for `/idea`.
|
|
46
|
+
- **Terminal idea states** are marked directly in `project/ideas.md` using the same HTML-comment tag convention `project/todo.md` uses for `RECONCILED`:
|
|
47
|
+
- `PROMOTED` — the idea was picked up via `/brainstorm` and turned into board work.
|
|
48
|
+
- `DISCARDED` — the idea was reviewed and dropped.
|
|
49
|
+
|
|
50
|
+
Example (mirroring `project/todo.md`'s tagging style):
|
|
51
|
+
```
|
|
52
|
+
Add dark mode toggle to settings page <!-- PROMOTED -->
|
|
53
|
+
Rewrite onboarding copy in a more casual tone <!-- DISCARDED -->
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
No agent invoked by `/idea` applies these tags or acts on them — that is reserved for a future promotion step (e.g. within `/brainstorm`).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Idea Handoff
|
|
2
|
+
|
|
3
|
+
<!-- PREAMBLE (for /idea): This template was pre-filled by a caller (e.g. /spinoff).
|
|
4
|
+
Skip any questions whose answers are already provided below. Only prompt the user
|
|
5
|
+
for fields that remain empty or marked as a placeholder. -->
|
|
6
|
+
|
|
7
|
+
<!-- Format: <mission title>: <E##_S##> (epic/story ref optional) -->
|
|
8
|
+
|
|
9
|
+
## Mission Title
|
|
10
|
+
<!-- PLACEHOLDER: short name for this idea, e.g. "Refactor auth middleware" -->
|
|
11
|
+
|
|
12
|
+
## Goal / Objective
|
|
13
|
+
<!-- PLACEHOLDER: what this idea is trying to achieve -->
|
|
14
|
+
|
|
15
|
+
## Affected Files or Scope
|
|
16
|
+
<!-- PLACEHOLDER: which files, modules, or areas are involved, e.g. src/auth/, skills/idea/ -->
|
|
17
|
+
|
|
18
|
+
## Intended Approach
|
|
19
|
+
<!-- PLACEHOLDER: step-by-step or high-level approach to the work -->
|
|
20
|
+
|
|
21
|
+
## Epic / Story Linkage
|
|
22
|
+
<!-- PLACEHOLDER: known Epic or Story ID this links to, e.g. E02_S03 — or "None" if not linked -->
|
|
23
|
+
|
|
24
|
+
## Origin
|
|
25
|
+
<!-- PLACEHOLDER: EST id (task/story/epic) in progress when the divergence happened, or "None" -->
|
|
26
|
+
<!-- PLACEHOLDER: one-line summary of what the user was doing at the time -->
|