@shahboura/harness 3.0.4
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/.opencode/agents/developer.md +60 -0
- package/.opencode/agents/planner.md +51 -0
- package/.opencode/agents/reviewer.md +53 -0
- package/.opencode/commands/add-repo.md +26 -0
- package/.opencode/commands/dev-workflow.md +40 -0
- package/.opencode/commands/init-workspace.md +22 -0
- package/.opencode/commands/migrate-workspace.md +28 -0
- package/.opencode/commands/repo-map-refresh.md +23 -0
- package/.opencode/commands/story-workflow.md +24 -0
- package/.opencode/commands/workflow-status.md +23 -0
- package/.opencode/commands/workspace-config.md +27 -0
- package/.opencode/package.json +9 -0
- package/.opencode/plugins/harness-guards.ts +290 -0
- package/.opencode/skills/add-repo/SKILL.md +96 -0
- package/.opencode/skills/dev-workflow/SKILL.md +105 -0
- package/.opencode/skills/dev-workflow/shared/diagram-styling.md +65 -0
- package/.opencode/skills/dev-workflow/shared/engineering.md +14 -0
- package/.opencode/skills/dev-workflow/shared/status-block.md +29 -0
- package/.opencode/skills/dev-workflow/steps/analyze-comments.md +32 -0
- package/.opencode/skills/dev-workflow/steps/apply-fixes.md +24 -0
- package/.opencode/skills/dev-workflow/steps/comment-analysis.md +11 -0
- package/.opencode/skills/dev-workflow/steps/create-pr.md +39 -0
- package/.opencode/skills/dev-workflow/steps/develop-task.md +54 -0
- package/.opencode/skills/dev-workflow/steps/develop.md +60 -0
- package/.opencode/skills/dev-workflow/steps/fetch.md +34 -0
- package/.opencode/skills/dev-workflow/steps/fixup-task.md +12 -0
- package/.opencode/skills/dev-workflow/steps/gate.md +53 -0
- package/.opencode/skills/dev-workflow/steps/harden-task.md +12 -0
- package/.opencode/skills/dev-workflow/steps/harden.md +30 -0
- package/.opencode/skills/dev-workflow/steps/intake.md +52 -0
- package/.opencode/skills/dev-workflow/steps/metrics.md +21 -0
- package/.opencode/skills/dev-workflow/steps/plan-task.md +108 -0
- package/.opencode/skills/dev-workflow/steps/plan.md +80 -0
- package/.opencode/skills/dev-workflow/steps/pre-pr-fixes.md +16 -0
- package/.opencode/skills/dev-workflow/steps/pre-pr-review.md +14 -0
- package/.opencode/skills/dev-workflow/steps/pre-pr.md +14 -0
- package/.opencode/skills/dev-workflow/steps/preflight.md +32 -0
- package/.opencode/skills/dev-workflow/steps/quick-recheck.md +14 -0
- package/.opencode/skills/dev-workflow/steps/reconcile.md +27 -0
- package/.opencode/skills/dev-workflow/steps/review-task.md +32 -0
- package/.opencode/skills/dev-workflow/steps/security.md +18 -0
- package/.opencode/skills/dev-workflow/steps/triage-request.md +15 -0
- package/.opencode/skills/init-workspace/SKILL.md +155 -0
- package/.opencode/skills/migrate-workspace/SKILL.md +122 -0
- package/.opencode/skills/repo-map-refresh/SKILL.md +43 -0
- package/.opencode/skills/story-workflow/SKILL.md +78 -0
- package/.opencode/skills/story-workflow/commands/analyze.md +40 -0
- package/.opencode/skills/story-workflow/commands/groom.md +58 -0
- package/.opencode/skills/story-workflow/commands/improve.md +47 -0
- package/.opencode/skills/story-workflow/commands/refine.md +44 -0
- package/.opencode/skills/story-workflow/shared/context.md +22 -0
- package/.opencode/skills/story-workflow/shared/provider-io.md +73 -0
- package/.opencode/skills/story-workflow/templates/readiness-report.md +57 -0
- package/.opencode/skills/story-workflow/templates/story-template.md +51 -0
- package/.opencode/skills/story-workflow/templates/technical-notes.md +48 -0
- package/.opencode/skills/workflow-status/SKILL.md +30 -0
- package/.opencode/skills/workspace-config/SKILL.md +97 -0
- package/.opencode/tsconfig.json +11 -0
- package/CHANGELOG.md +396 -0
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/package.json +32 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: init-workspace
|
|
3
|
+
version: "3.0.0"
|
|
4
|
+
author: "Mostafa Ashraf"
|
|
5
|
+
description: >
|
|
6
|
+
One-time workspace setup for the ai-sdlc-harness pipeline. USER-ENTRY and
|
|
7
|
+
HUMAN-ONLY — invoke only when the user explicitly runs /init-workspace;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# init-workspace — the interview (M7)
|
|
12
|
+
|
|
13
|
+
Human-only: the user's consent point for the whole workspace. Every command
|
|
14
|
+
below is `bin/harness <verb> …` — always the full
|
|
15
|
+
path; a bare `harness` is not on PATH, and shell variables set in one Bash
|
|
16
|
+
call do not persist to the next. Re-running refreshes **one section at a
|
|
17
|
+
time** (`init-section`), never a full-nuke.
|
|
18
|
+
|
|
19
|
+
## 0 · Environment bootstrap (do this FIRST)
|
|
20
|
+
|
|
21
|
+
The harness needs PyYAML; system pythons are often externally managed
|
|
22
|
+
(PEP 668), so the plugin owns a venv that `bin/harness` resolves
|
|
23
|
+
automatically on every future call:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
PY=".venv/bin/python"
|
|
27
|
+
[ -x "$PY" ] || PY=".venv/Scripts/python.exe"
|
|
28
|
+
"$PY" -c "import yaml" 2>/dev/null || {
|
|
29
|
+
SYS="$(command -v python3 || command -v python)" &&
|
|
30
|
+
"$SYS" -m venv ".venv" &&
|
|
31
|
+
PY=".venv/bin/python" &&
|
|
32
|
+
{ [ -x "$PY" ] || PY=".venv/Scripts/python.exe"; } &&
|
|
33
|
+
"$PY" -m pip install --quiet pyyaml; }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
One snippet for every OS: the Bash tool is Git Bash on Windows, so this
|
|
37
|
+
stays POSIX shell there too — the two `.venv` probes cover the `bin/` (POSIX)
|
|
38
|
+
vs `Scripts/` (Windows) venv layouts, and the `python3 || python` fallback
|
|
39
|
+
covers hosts where only one spelling exists. Until this step runs,
|
|
40
|
+
`bin/harness` itself still works (it falls back to the same system
|
|
41
|
+
interpreter probe, which is what fails on a PyYAML-less system — that's why
|
|
42
|
+
this step exists), and the spawn/skill guards degrade open with a one-line
|
|
43
|
+
notice rather than erroring — expected pre-setup behavior, not a bug to chase.
|
|
44
|
+
|
|
45
|
+
## 1 · Must-provide (no defaults — ask)
|
|
46
|
+
|
|
47
|
+
- **Work-item provider**: local-markdown / github / gitlab / ado (CLI) /
|
|
48
|
+
ado-mcp / jira / zoho (MCP — walk the user through the model-in-the-loop MCP
|
|
49
|
+
integration probe). ADO is available on either transport (`ado` = `az boards`,
|
|
50
|
+
`ado-mcp` = Azure DevOps MCP server). Plus its specifics (stories dir,
|
|
51
|
+
`github_repo`, `ado_org`, `ado_project`, …).
|
|
52
|
+
- **Git provider**: local / github / gitlab / ado (CLI) / ado-mcp (MCP).
|
|
53
|
+
If the user didn't state one, `local` is the sanctioned inference ONLY
|
|
54
|
+
when every registered repo has no remote (`git remote` empty) — say so
|
|
55
|
+
in one line rather than asking; any repo with a remote → ask.
|
|
56
|
+
- **Repos**: `name=path` per target repo.
|
|
57
|
+
|
|
58
|
+
Every `init-section` write is merged straight into the flat config by its
|
|
59
|
+
top-level keys, so `provider`, `repos`, and `language` payloads must be
|
|
60
|
+
**self-nested** under their own section key:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
bin/harness init-section --section provider --json \
|
|
64
|
+
'{"provider": {"work_item": "local-markdown", "git": "local", "stories_dir": "stories"}}'
|
|
65
|
+
bin/harness init-section --section repos --json \
|
|
66
|
+
'{"repos": {"backend": "/path/to/backend", "frontend": "/path/to/frontend"}}'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`overrides` is the one exception on both counts: it's a flat grab-bag of
|
|
70
|
+
top-level config keys (`status_mapping`, `subagent_models`, `quick_mode`,
|
|
71
|
+
…), never self-nested under an `"overrides"` key, and unlike
|
|
72
|
+
`provider`/`repos`/`language` (each write replaces the whole file — always
|
|
73
|
+
send the complete current set) its writes **merge**, so separate
|
|
74
|
+
`--section overrides` calls for different settings accumulate rather than
|
|
75
|
+
clobbering each other. See step 3.
|
|
76
|
+
|
|
77
|
+
## 2 · Discovered, then confirmed
|
|
78
|
+
|
|
79
|
+
Run `bin/harness discover --repo <path>` per repo. `discover` first
|
|
80
|
+
ensures the repo is clean and on its default branch (`ensure_default_branch`
|
|
81
|
+
— the same reusable precondition `preflight` uses later): a dirty repo, or
|
|
82
|
+
one mid-rebase/merge, refuses with a clear error — surface it to the user
|
|
83
|
+
(never auto-stash/discard/continue) — and a clean repo on a different
|
|
84
|
+
branch is switched, reported back in `branch_check` so the interview can
|
|
85
|
+
tell the user it happened. If the guessed default branch doesn't exist
|
|
86
|
+
locally (no resolvable `origin/HEAD`), pass `--branch <name>` explicitly —
|
|
87
|
+
note this only catches a *nonexistent* guess; a repo with no `origin` and
|
|
88
|
+
a stray local branch that happens to be named `main` cannot be told apart
|
|
89
|
+
from a genuine one, so confirm the branch name with the user for any repo
|
|
90
|
+
without a resolvable `origin/HEAD`.
|
|
91
|
+
**Known risk:** re-running this against a repo that already has an active
|
|
92
|
+
`/dev-workflow` run in progress can switch that run's feature-branch
|
|
93
|
+
checkout back to default — avoid re-running discovery for a repo with
|
|
94
|
+
in-flight work. Present the proposals (language, `test_cmd`, default
|
|
95
|
+
branch) as defaults-to-confirm. A `monorepo_split` proposal means this "one
|
|
96
|
+
repo" is actually several logical repos sharing one `.git` at the physical
|
|
97
|
+
root — **this isn't yet representable as separate registered repos**
|
|
98
|
+
(`init-verify`'s `repo:<name>` check requires a `.git` directly under the
|
|
99
|
+
registered path, which no subtree has, so registering subtrees separately
|
|
100
|
+
leaves every one of them permanently failing verification with no
|
|
101
|
+
available fix). Tell the user this is a known gap; register the repo once,
|
|
102
|
+
at its physical root.
|
|
103
|
+
**Language-config is per repo**, under `language.repos`, keyed by the same
|
|
104
|
+
names used in `--section repos` (a sub-key, not a sibling of the global
|
|
105
|
+
`test_paths`/`test_closure` settings, so a repo name can never collide with
|
|
106
|
+
those) — confirm each repo's own `test_cmd` by running it, never collapse
|
|
107
|
+
differing repos onto one command. **`coverage_cmd` gets the same
|
|
108
|
+
treatment**: discover proposes one only on repo evidence (a `coverage`
|
|
109
|
+
script, jest/vitest+provider, jacoco in the pom) — confirm it by running
|
|
110
|
+
it. No proposal → ask the user for one (the harden step consumes it and
|
|
111
|
+
never improvises); an explicit skip is a valid answer, recorded by simply
|
|
112
|
+
omitting the key — tell the user harden will re-ask at run time. Write the
|
|
113
|
+
whole set in one `--section language` call, e.g. `{"language": {"repos":
|
|
114
|
+
{"backend": {"test_cmd": "sh mvnw -q test", "coverage_cmd": "sh mvnw -q
|
|
115
|
+
test jacoco:report"}, "frontend": {"test_cmd": "npm test"}}}}`.
|
|
116
|
+
|
|
117
|
+
## 3 · Choose-or-default (offer "default" explicitly, every time)
|
|
118
|
+
|
|
119
|
+
Status-mapping override (provider defaults usually suffice), change-types +
|
|
120
|
+
naming templates, `subagent_models` (default all `inherit`), quick-mode
|
|
121
|
+
thresholds/keywords, repo-map staleness N, review-policy team rules,
|
|
122
|
+
`security.scan_cmd` (if a scanner is configured, it's per-repo-keyed the
|
|
123
|
+
same way `language` is — no scanner configured stays informational-only).
|
|
124
|
+
Only what the user changes goes in `--section overrides` — shipped
|
|
125
|
+
defaults cover the rest. Unlike `provider`/`repos`/`language`, this payload
|
|
126
|
+
is **flat, not self-nested** (these are top-level config keys in their own
|
|
127
|
+
right), e.g. `--section overrides --json '{"quick_mode": {"loc_max":
|
|
128
|
+
50}}'` — never `{"overrides": {...}}`. Each call deep-merges into whatever is
|
|
129
|
+
already there, so it's fine to write these one setting at a time as the
|
|
130
|
+
user decides them; there's no way to *unset* a previously-written override
|
|
131
|
+
through this verb though — that needs a direct edit to `overrides.yaml`.
|
|
132
|
+
|
|
133
|
+
## 4 · Verify (a real gate) + finish
|
|
134
|
+
|
|
135
|
+
1. `bin/harness init-verify` — every check must pass
|
|
136
|
+
(or be `manual` with the user's explicit acknowledgment for MCP
|
|
137
|
+
providers). Failures show remediation; fix and re-run. **Do not proceed
|
|
138
|
+
on failures.**
|
|
139
|
+
2. `bin/harness init-finalize` — writes the permissions
|
|
140
|
+
allowlist and the bootstrap marker (section writes alone do not write
|
|
141
|
+
either of these). It re-runs the same verify gate itself and refuses
|
|
142
|
+
(exit 1) if any check still fails, so it can't mark a half-configured
|
|
143
|
+
workspace bootstrapped even if step 1 above was skipped by mistake.
|
|
144
|
+
Confirm `.claude/settings.json` merged cleanly (non-destructive).
|
|
145
|
+
3. **Repo-map**: offer to generate one now per repo, following
|
|
146
|
+
`/repo-map-refresh`'s step 2 exactly (subagent_type-guessing warning,
|
|
147
|
+
`harness-mode: repo-map` header, and stamp-it-yourself rule all live
|
|
148
|
+
there — this file doesn't keep its own copy).
|
|
149
|
+
4. Tell the user: `/dev-workflow <work-item-id>` is ready.
|
|
150
|
+
|
|
151
|
+
## 5 · Adding a repo after the fact
|
|
152
|
+
|
|
153
|
+
Use the dedicated `/add-repo` skill — it's the one place this procedure
|
|
154
|
+
(discover → confirm → register → verify → finalize) is maintained; don't
|
|
155
|
+
hand-roll it here too.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-workspace
|
|
3
|
+
version: "3.0.0"
|
|
4
|
+
author: "Mostafa Ashraf"
|
|
5
|
+
description: >
|
|
6
|
+
Adopt a v2.x ai-sdlc-harness workspace into v3.0 — config carries over,
|
|
7
|
+
run history stays archived in place. USER-ENTRY and HUMAN-ONLY — invoke
|
|
8
|
+
only when the user explicitly runs /migrate-workspace; never autonomously,
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# migrate-workspace — adopt a v2.x workspace
|
|
13
|
+
|
|
14
|
+
**The fork seam:** this file and `harness/migrate.py` are the replaceable
|
|
15
|
+
unit — forks ship different adoption logic by swapping them and nothing
|
|
16
|
+
else. Everything that WRITES goes through the same owned path as
|
|
17
|
+
`/init-workspace` (`init-section` → `init-verify` → `init-finalize`);
|
|
18
|
+
migrate verbs are read-only proposals.
|
|
19
|
+
|
|
20
|
+
Human-only, same invocation rules as every skill here: always the full
|
|
21
|
+
`bin/harness <verb>` path. First run
|
|
22
|
+
`/init-workspace`'s **step 0 environment bootstrap** exactly as written
|
|
23
|
+
there (that file owns the procedure — don't re-derive it).
|
|
24
|
+
|
|
25
|
+
## 1 · Detect (stop conditions first)
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
bin/harness migrate-detect
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- Surface `warnings` verbatim whenever present — e.g. an unreadable
|
|
32
|
+
`overrides.yaml` reports as bootstrapped *fail-closed*, and the
|
|
33
|
+
remediation lives in the warning, not here.
|
|
34
|
+
- `already_bootstrapped: true` → this workspace already runs v3.0. If
|
|
35
|
+
`inventory.legacy_context_files` is non-empty, a prior migration stopped
|
|
36
|
+
before archiving — offer the **archive-only finish** (steps 5–6; the
|
|
37
|
+
report on this path records `inventory` only, since `migrate-extract`
|
|
38
|
+
rightly refuses post-bootstrap — the carried-config record lives in the
|
|
39
|
+
earlier attempt's confirmations); otherwise **stop** and point the user
|
|
40
|
+
at `/workspace-config`.
|
|
41
|
+
- `legacy: null` → **stop**: nothing to adopt; point at `/init-workspace`.
|
|
42
|
+
- Otherwise show the `evidence` list (why this looks like v2.x), then the
|
|
43
|
+
`inventory`:
|
|
44
|
+
- **`in_flight` runs get a hard boundary, stated plainly:** run history
|
|
45
|
+
is never converted — v3.0 state is sealed evidence (red-proofs,
|
|
46
|
+
ledgers) that v2.x never produced, so migrating a half-done run would
|
|
47
|
+
fabricate its audit trail. **Recommend finishing or abandoning those
|
|
48
|
+
stories on v2.x before migrating**: step 5 archives the very config
|
|
49
|
+
files v2.x resumes from, so proceeding now means a later v2.x session
|
|
50
|
+
must first hand-restore them from `legacy-2.1/`. Proceeding anyway is
|
|
51
|
+
the user's call — record the choice in the step-5 report.
|
|
52
|
+
- Old `ai/` run dirs and `aborted` leftovers stay exactly where they are
|
|
53
|
+
as readable archives; v3.0 run discovery ignores them.
|
|
54
|
+
|
|
55
|
+
## 2 · Extract & confirm (propose-only)
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
bin/harness migrate-extract
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Present the proposal per section — `provider`, `repos`, `language` — next
|
|
62
|
+
to every `notes` entry (missing repo paths, unverifiable stories_dir) and
|
|
63
|
+
the `unmapped` list (what v2.x config has no v3.0 home, and why). The user
|
|
64
|
+
confirms or corrects **each section**; anything extract could not fill
|
|
65
|
+
falls through to the matching `/init-workspace` interview question — never
|
|
66
|
+
guess a value extraction didn't find.
|
|
67
|
+
|
|
68
|
+
**Re-entry:** if a target section file already exists under
|
|
69
|
+
`.claude/context/` (a prior attempt got that far), read it and present its
|
|
70
|
+
current value next to the legacy-derived proposal — never silently
|
|
71
|
+
re-propose stale legacy data over a correction the user already confirmed.
|
|
72
|
+
|
|
73
|
+
`optional_overrides.naming` is **opt-in, default NO**: translated v2.1
|
|
74
|
+
naming templates are usually the v2.1 defaults the user never chose, and
|
|
75
|
+
v3.0's `{type}/{id}-{slug}` handles change-types better than a frozen
|
|
76
|
+
`feature/` prefix. Offer it only as "did you deliberately customize
|
|
77
|
+
naming in v2.x?".
|
|
78
|
+
|
|
79
|
+
## 3 · Apply through the owned init path
|
|
80
|
+
|
|
81
|
+
Write each confirmed section with `init-section` exactly as
|
|
82
|
+
`/init-workspace` step 1 documents (self-nested payloads; `overrides`
|
|
83
|
+
flat). Then fill the gaps the same way that interview does:
|
|
84
|
+
|
|
85
|
+
- No `language` proposal for a repo → `discover --repo <path>` and confirm
|
|
86
|
+
(its dirty-repo/default-branch cautions live in `/init-workspace` step 2).
|
|
87
|
+
**`discover` switches a clean repo back to its default branch** — if
|
|
88
|
+
`inventory.in_flight` names a story whose v2.x feature branch may be
|
|
89
|
+
checked out in that repo, say so and get explicit confirmation first.
|
|
90
|
+
- MCP-transport providers (`jira`, `zoho`, `ado-mcp`) → the
|
|
91
|
+
model-in-the-loop MCP checklist from the interview applies unchanged.
|
|
92
|
+
|
|
93
|
+
## 4 · Verify + finalize (the same real gate)
|
|
94
|
+
|
|
95
|
+
`/init-workspace` step 4, verbatim: `init-verify` must pass (fix failures,
|
|
96
|
+
re-run), then `init-finalize`. A migrated workspace ends in exactly the
|
|
97
|
+
state a freshly-interviewed one does — there is no "migrated" flavor to
|
|
98
|
+
special-case later.
|
|
99
|
+
|
|
100
|
+
## 5 · Archive the legacy config
|
|
101
|
+
|
|
102
|
+
List the v2.x context files (`inventory.legacy_context_files`), confirm
|
|
103
|
+
with the user, then move them aside so nobody mistakes them for live
|
|
104
|
+
config:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
mkdir -p .claude/context/legacy-2.1 && mv .claude/context/*.md .claude/context/legacy-2.1/
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Write `.claude/context/legacy-2.1/migration-report.md`: what carried over
|
|
111
|
+
(per section), the full `unmapped` and `notes` lists, and any in-flight
|
|
112
|
+
v2.x stories with the finish-on-v2.x guidance. The old `ai/` dirs are the
|
|
113
|
+
run archive; this report is the config-decision record.
|
|
114
|
+
|
|
115
|
+
## 6 · Hand over
|
|
116
|
+
|
|
117
|
+
- `local-markdown` users: existing story files work in place — v2.1
|
|
118
|
+
`> Status:` blockquotes are read tolerantly and upgrade to the v3.0
|
|
119
|
+
`Status:` form on first write-back.
|
|
120
|
+
- Remote-provider users: work items live server-side; nothing moved.
|
|
121
|
+
- Offer repo-map generation (`/repo-map-refresh` owns the procedure),
|
|
122
|
+
then: `/dev-workflow <work-item-id>` is ready.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: repo-map-refresh
|
|
3
|
+
version: "3.0.0"
|
|
4
|
+
author: "Mostafa Ashraf"
|
|
5
|
+
description: >
|
|
6
|
+
Regenerate the auto-generated repo map the planner grounds its plans in.
|
|
7
|
+
USER-ENTRY — invoke only when the user explicitly runs /repo-map-refresh;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# repo-map-refresh
|
|
12
|
+
|
|
13
|
+
The repo map is a navigation aid, never hand-maintained — corrections go
|
|
14
|
+
through regeneration (design.md piece 5B). `/init-workspace` and
|
|
15
|
+
`/add-repo` both point here for the identical generate-or-regenerate
|
|
16
|
+
procedure (step 2 below) — this is the one place it's maintained; don't
|
|
17
|
+
fork a second copy of it elsewhere.
|
|
18
|
+
|
|
19
|
+
1. `bin/harness repo-map-check --repo-name <n> --repo <path>` — report
|
|
20
|
+
missing / fresh / stale (+ commits behind) to the user.
|
|
21
|
+
2. To regenerate: spawn the planner shape with `harness-mode: repo-map` as
|
|
22
|
+
the prompt's FIRST line (the spawn guard regex-matches this exact
|
|
23
|
+
header — prose that merely mentions repo-map does not satisfy it; this
|
|
24
|
+
is a declared out-of-run spawn, `pipeline/surfaces.yaml`'s
|
|
25
|
+
`out_of_run_spawns`, legal regardless of whether other runs exist in the
|
|
26
|
+
workspace) and the repo path. Do not guess the planner's `subagent_type`
|
|
27
|
+
string: check your currently available subagent types for whichever one
|
|
28
|
+
corresponds to this plugin's planner (`agents/planner.md`'s frontmatter
|
|
29
|
+
`name: planner` is the identifying detail to match against) —
|
|
30
|
+
`hooks/guards.py`'s spawn guard matches on this shape by the LAST
|
|
31
|
+
`:`-segment of whatever string you pass, and a wrong guess doesn't
|
|
32
|
+
error, it just silently skips the guard's enforcement (fail-closed
|
|
33
|
+
spawn gating, planner's write-confinement to `ai/`/`.claude/context/`),
|
|
34
|
+
which is worse than the guess looking right. The planner can only write
|
|
35
|
+
under `ai/<run>/` and `.claude/context/` (guard-enforced — never repo
|
|
36
|
+
source), so point it at `.claude/context/repo-map/<name>/`. It writes
|
|
37
|
+
the tiered map there: a short top-level index (directories/modules by
|
|
38
|
+
purpose) plus per-area detail files, each loadable alone.
|
|
39
|
+
3. Stamp it yourself, not the planner:
|
|
40
|
+
`bin/harness repo-map-stamp --repo-name <n> --repo <path>`
|
|
41
|
+
— stamping is the orchestrator's job, never the planner's own.
|
|
42
|
+
4. Remind the user: the planner still reads real code for areas it plans to
|
|
43
|
+
touch — the map speeds targeting, it doesn't replace reading.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-workflow
|
|
3
|
+
version: "3.0.0"
|
|
4
|
+
author: "Mostafa Ashraf"
|
|
5
|
+
description: >
|
|
6
|
+
Refine, analyze, improve, and groom user stories / work items for quality —
|
|
7
|
+
readiness reports, template restructuring, adaptive gap-filling, and
|
|
8
|
+
codebase-aware technical grooming. USER-ENTRY and HUMAN-ONLY — invoke only
|
|
9
|
+
when the user explicitly runs /story-workflow <command>; never autonomously
|
|
10
|
+
from conversation, never from a subagent (guard-enforced). Distinct from the
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# story-workflow — story-quality refinement (PO-facing)
|
|
15
|
+
|
|
16
|
+
Improves work-item quality through four commands. Read-mostly: it fetches a
|
|
17
|
+
work item, helps shape it, and — only with the user's consent — posts the
|
|
18
|
+
result back as a comment. It never starts a dev run and never touches
|
|
19
|
+
`ai/<run>/` run state.
|
|
20
|
+
|
|
21
|
+
Every harness call is `bin/harness <verb> …` — the full
|
|
22
|
+
path, run by you via Bash (a bare `harness` is not on PATH, and shell variables
|
|
23
|
+
set in one Bash call do not persist to the next). Non-zero exit = refused; read
|
|
24
|
+
the JSON error and act on it.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/story-workflow <command> <work-item-id> [session-notes…]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`<command>` is one of `analyze`, `refine`, `improve`, `groom`. `<work-item-id>`
|
|
33
|
+
is whatever the configured provider uses — a number (ADO / GitHub / GitLab), a
|
|
34
|
+
key (`PROJ-123`, Jira), or, for `local-markdown`, the story's **id** (the file
|
|
35
|
+
stem inside `provider.stories_dir`, e.g. `WORK-7` for `WORK-7.md` — not a
|
|
36
|
+
path). Any trailing tokens are session notes, passed through to `improve` and
|
|
37
|
+
`refine`.
|
|
38
|
+
|
|
39
|
+
## Routing
|
|
40
|
+
|
|
41
|
+
| command | file | one-line |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `improve` | `commands/improve.md` | adaptive single-pass: assess → gap-fill → draft (the recommended default) |
|
|
44
|
+
| `analyze` | `commands/analyze.md` | standalone readiness report with flags |
|
|
45
|
+
| `refine` | `commands/refine.md` | slow, section-by-section interactive restructure |
|
|
46
|
+
| `groom` | `commands/groom.md` | codebase-aware per-repo technical notes |
|
|
47
|
+
|
|
48
|
+
Parse `$ARGUMENTS`: the first token is the command, the second is the work-item
|
|
49
|
+
id, the rest are notes. If the command is missing or unknown, print the usage
|
|
50
|
+
line plus the table above and stop — do not guess. If the id is missing, ask
|
|
51
|
+
for it — never proceed without one. Then read the one matching command file and
|
|
52
|
+
follow it (context economy: load a single command file, not all four).
|
|
53
|
+
|
|
54
|
+
## Before routing
|
|
55
|
+
|
|
56
|
+
1. Confirm the workspace is bootstrapped: `.claude/context/provider.yaml` must
|
|
57
|
+
exist. If it doesn't, `/init-workspace` never ran — send the user there and
|
|
58
|
+
stop. The active provider is resolved from config by the harness; you never
|
|
59
|
+
hand-pick it.
|
|
60
|
+
2. The recipe for fetching a work item and posting a result back — for every
|
|
61
|
+
provider and both transports — lives once in `shared/provider-io.md`. Read
|
|
62
|
+
it; the commands cite it instead of repeating it.
|
|
63
|
+
3. Domain and convention context (for `improve` and `groom`) lives once in
|
|
64
|
+
`shared/context.md`.
|
|
65
|
+
|
|
66
|
+
## Guardrails (all four commands)
|
|
67
|
+
|
|
68
|
+
- On a remote provider, never edit the item's Description or Acceptance-Criteria
|
|
69
|
+
fields — post back as a **comment** only. The single exception is a
|
|
70
|
+
`local-markdown` story the user explicitly asks you to rewrite in place; see
|
|
71
|
+
`shared/provider-io.md`.
|
|
72
|
+
- Never invent business requirements. A gap is a question for the human, not an
|
|
73
|
+
assertion of what "should" be there.
|
|
74
|
+
- Mirror the user's domain language; don't rename their "platform" to "system".
|
|
75
|
+
- Files in `templates/` are read-only references — don't modify them while a
|
|
76
|
+
command runs.
|
|
77
|
+
- If a story is already well-formed, say so. "This looks ready" is a valid,
|
|
78
|
+
valuable outcome — don't manufacture flags or questions to look busy.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# /story-workflow analyze
|
|
2
|
+
|
|
3
|
+
Pre-refinement readiness check. Evaluates a work item against quality criteria
|
|
4
|
+
and produces a readiness report with actionable flags. Standalone and
|
|
5
|
+
non-destructive — it never rewrites the story.
|
|
6
|
+
|
|
7
|
+
> For most sessions `improve` is the better choice — it folds readiness analysis
|
|
8
|
+
> into refinement in one adaptive pass. Reach for `analyze` when you want a
|
|
9
|
+
> standalone report to share with the PO *before* touching the story.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. **Fetch** the work item per `shared/provider-io.md`. Extract title, type,
|
|
14
|
+
state, description, and acceptance criteria. If it isn't found, stop.
|
|
15
|
+
2. **Domain context (optional)**: skim `shared/context.md` only if you need the
|
|
16
|
+
repo landscape to judge whether the story's scope is realistic.
|
|
17
|
+
3. **Evaluate** the story against every dimension in
|
|
18
|
+
`templates/readiness-report.md`. For each, assign a 🔴/🟡/🟢 flag with a
|
|
19
|
+
*specific* explanation. Rules:
|
|
20
|
+
- **Be specific, not generic.** Not "ACs could be improved" but "AC #2 says
|
|
21
|
+
'handles errors gracefully' — untestable; suggest 'Given an invalid token,
|
|
22
|
+
When login is attempted, Then a 401 with code `AUTH_INVALID_TOKEN` is
|
|
23
|
+
returned'."
|
|
24
|
+
- **Suggest, don't only critique.** Every 🔴/🟡 carries a concrete fix —
|
|
25
|
+
draft the replacement text where you can.
|
|
26
|
+
- **Constructive tone.** The PO and team will read this.
|
|
27
|
+
4. **Write the report** in the `templates/readiness-report.md` format: flags
|
|
28
|
+
with explanations, suggested improvements (draft Given/When/Then ACs where
|
|
29
|
+
ACs are missing or vague), and a 2–3 sentence summary assessment.
|
|
30
|
+
5. **Present** the full report in the conversation, then ask whether to post it
|
|
31
|
+
as a comment on the item. On yes, post it per `shared/provider-io.md`. For
|
|
32
|
+
`local-markdown` (or any provider), the report is a **comment** — never
|
|
33
|
+
overwrite the story with it; if the user wants it persisted separately,
|
|
34
|
+
offer a sibling file (e.g. `<id>-readiness.md`) via the `Write` tool.
|
|
35
|
+
|
|
36
|
+
## Notes
|
|
37
|
+
|
|
38
|
+
- Never modify the item's Description or AC fields — comments only.
|
|
39
|
+
- Don't force flags. A report that says "this story is ready" is a good result.
|
|
40
|
+
- Flag missing pieces as **questions**, not assertions about what should exist.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# /story-workflow groom
|
|
2
|
+
|
|
3
|
+
Technical enrichment pass. Analyzes the relevant repos to identify affected
|
|
4
|
+
components, migration concerns, testing strategy, and risks, and produces
|
|
5
|
+
per-repo technical notes. This is where Claude Code's native codebase awareness
|
|
6
|
+
is the main tool.
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Fetch** the work item per `shared/provider-io.md`. If it has no clear ACs
|
|
11
|
+
yet, offer to run `improve` first — grooming is more effective on a refined
|
|
12
|
+
story — but proceed if the user wants to.
|
|
13
|
+
2. **Identify relevant repos.** Read the repo landscape per `shared/context.md`
|
|
14
|
+
(`repos.yaml` + each `repo-map/<name>/`). From the story, propose which repos
|
|
15
|
+
are affected, each with a one-line reason, and **wait for the user to confirm**
|
|
16
|
+
before scanning anything. Don't scan repos they didn't approve.
|
|
17
|
+
3. **Refresh remote knowledge, then check position (never mutate the tree).**
|
|
18
|
+
For each confirmed repo, using its path from `repos.yaml`:
|
|
19
|
+
- `git -C "<path>" fetch origin` — allowed, and updates remote refs without
|
|
20
|
+
touching the working tree. If it fails (no network/remote), report and skip
|
|
21
|
+
that repo — don't scan a repo you couldn't refresh.
|
|
22
|
+
- `git -C "<path>" rev-list HEAD..origin/<default-branch> --count` — a read;
|
|
23
|
+
how far behind the checkout is.
|
|
24
|
+
- **The harness blocks raw `git pull` / `merge` inside any workspace that has
|
|
25
|
+
completed `/init-workspace`** (owned-entry-point rule; this skill only ever
|
|
26
|
+
runs inside one), so this command does **not** update the working
|
|
27
|
+
tree. If a repo is behind, say so and offer two choices: **(a)** analyze the
|
|
28
|
+
current checkout as-is — and stamp the staleness into the notes so the
|
|
29
|
+
reader knows the analysis reflects commit `<short-sha>`, N commits behind
|
|
30
|
+
`origin/<default>`; or **(b)** stop for that repo so the user can update it
|
|
31
|
+
themselves (outside the harness) and re-run `groom`. Never switch branches
|
|
32
|
+
or discard changes to "help".
|
|
33
|
+
4. **Analyze each confirmed, fetched repo** against the story. Use `Grep` for
|
|
34
|
+
content, `Glob` for file patterns, `Read` for inspection — not `Bash` for
|
|
35
|
+
searches. Look for: affected files/classes/methods; database & migration
|
|
36
|
+
impact; API surface (controllers, routes, DTOs); configuration & DI; existing
|
|
37
|
+
test coverage for the touched areas; and cross-service dependencies. Align
|
|
38
|
+
with the team's real patterns from the repo-map (repository pattern, MediatR,
|
|
39
|
+
etc.). **Be concrete** — name the file and method, e.g. "`AuthService.cs`
|
|
40
|
+
`ValidateToken` (~line 45) is what this story changes; tests live in
|
|
41
|
+
`AuthServiceTests.cs`", not "the auth module might be affected."
|
|
42
|
+
5. **Produce technical notes** in `templates/technical-notes.md` — a section per
|
|
43
|
+
repo, plus Cross-Repo Considerations when more than one repo is involved.
|
|
44
|
+
6. **Present** the notes and ask whether to post them as a comment. Iterate on
|
|
45
|
+
the user's input (they know planned refactors and constraints the code
|
|
46
|
+
doesn't show), then post per `shared/provider-io.md`. For `local-markdown`,
|
|
47
|
+
notes are a **comment** by default; do not overwrite the story — if the user
|
|
48
|
+
wants them persisted separately, offer a sibling `<id>-technical-notes.md`.
|
|
49
|
+
|
|
50
|
+
## Notes
|
|
51
|
+
|
|
52
|
+
- Comments only — never edit the item's Description or AC fields.
|
|
53
|
+
- Frame findings as "here's what I see in the code," not "here's how to build
|
|
54
|
+
it." The goal is a head start on scope, not a prescribed implementation.
|
|
55
|
+
- If you can't determine the impact with confidence, say so — "I couldn't tell
|
|
56
|
+
how X is handled; discuss at grooming" is a valid, useful finding.
|
|
57
|
+
- Note unrelated concerns (a bug, tech debt) in one line, but don't derail the
|
|
58
|
+
grooming with them.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# /story-workflow improve
|
|
2
|
+
|
|
3
|
+
Single-pass story improvement — assess readiness internally, fill gaps
|
|
4
|
+
conversationally, and produce a refined story, all in one adaptive flow. This
|
|
5
|
+
is the recommended default: it replaces the separate analyze-then-refine dance.
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
1. **Fetch** the work item per `shared/provider-io.md` (title, description,
|
|
10
|
+
acceptance criteria, state, links). If it isn't found, stop.
|
|
11
|
+
2. **Load** `templates/story-template.md` (target format),
|
|
12
|
+
`templates/readiness-report.md` (used only as an internal rubric — do *not*
|
|
13
|
+
present a standalone report), and `shared/context.md` for domain language.
|
|
14
|
+
3. **Assess readiness internally** against the rubric, then classify into a tier:
|
|
15
|
+
- **Tier 1 — Solid**: ≤1–2 yellow flags, no red. Draft immediately.
|
|
16
|
+
- **Tier 2 — Some gaps**: 1–3 issues. Specific areas need clarification.
|
|
17
|
+
- **Tier 3 — Rough**: 4+ issues, or a whole section missing (no ACs, no
|
|
18
|
+
description). Needs substantial input.
|
|
19
|
+
4. **Fill gaps conversationally**, adapted to the tier:
|
|
20
|
+
- **Tier 1**: skip questions, acknowledge what's good, draft.
|
|
21
|
+
- **Tier 2**: ask 2–5 targeted questions — each references the specific gap
|
|
22
|
+
and *proposes an answer to confirm or correct* (the user validates, not
|
|
23
|
+
drafts). Present them all at once.
|
|
24
|
+
- **Tier 3**: say so honestly, ask up to 5 questions, then (if critical gaps
|
|
25
|
+
remain) one more round of up to 3, then draft.
|
|
26
|
+
- **Session notes** (passed after the id) are gold: mine them before asking
|
|
27
|
+
anything, and don't ask what they already answer. If none and the story is
|
|
28
|
+
Tier 2/3, ask once whether any exist.
|
|
29
|
+
5. **Draft the whole story at once** in `templates/story-template.md`: Context,
|
|
30
|
+
Description, Acceptance Criteria (happy path then error/edge), Out of Scope,
|
|
31
|
+
Open Questions (`[PO]`/`[Tech]`/`[Team]`), and an empty Technical Notes
|
|
32
|
+
(that's `groom`'s). For Tier 2/3, prepend a short "What was improved" list;
|
|
33
|
+
skip it for Tier 1.
|
|
34
|
+
6. **Review and iterate** — present the full draft, adjust any section the user
|
|
35
|
+
flags. If it's grown too large (>7 ACs, multiple capabilities), suggest a
|
|
36
|
+
split. After minor edits, just confirm the change; don't re-dump the story.
|
|
37
|
+
7. **Post** on approval per `shared/provider-io.md` — one comment carrying the
|
|
38
|
+
"What was improved" summary (if any) plus the full story. For
|
|
39
|
+
`local-markdown`, offer the in-place overwrite of the source file (this
|
|
40
|
+
command is one of the two that may rewrite a story in place).
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- **Adapt, don't interrogate.** If the story is good, say so and draft fast.
|
|
45
|
+
- **Suggest answers.** The user should be confirming, not drafting from scratch.
|
|
46
|
+
- **One comment, one artifact** — the whole output in a single comment, not one
|
|
47
|
+
per section.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# /story-workflow refine
|
|
2
|
+
|
|
3
|
+
Interactive, section-by-section restructuring of a story into the canonical
|
|
4
|
+
template through a collaborative conversation. Slower than `improve` on purpose.
|
|
5
|
+
|
|
6
|
+
> For most sessions `improve` is the better choice. Reach for `refine` when a
|
|
7
|
+
> story is complex or contentious and you want to work through it one section at
|
|
8
|
+
> a time, confirming each before moving on.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Fetch** the work item per `shared/provider-io.md` (title, description,
|
|
13
|
+
acceptance criteria, state, links).
|
|
14
|
+
2. **Session notes**: if the user passed notes after the id, use them. If not,
|
|
15
|
+
ask once: "Any notes from the refinement session — bullet points, rough
|
|
16
|
+
notes, decisions? If not, I'll work from the work item." Notes capture PO
|
|
17
|
+
clarifications and scope calls that never made it into the item.
|
|
18
|
+
3. **Load** `templates/story-template.md` (the target format) and, for
|
|
19
|
+
terminology, `shared/context.md`.
|
|
20
|
+
4. **Work the template one section at a time**, proposing content and getting
|
|
21
|
+
approval before moving on:
|
|
22
|
+
- **Context** — draft the business "why"; ask if it's captured correctly.
|
|
23
|
+
- **Description** — one `As a … I want … so that …`. If it spans multiple
|
|
24
|
+
capabilities, flag a possible split before continuing.
|
|
25
|
+
- **Acceptance Criteria** — draft Given/When/Then, happy path first then
|
|
26
|
+
error/edge cases; present them together and ask what's missing.
|
|
27
|
+
- **Out of Scope** — propose explicit exclusions from the notes and context;
|
|
28
|
+
ask what else to exclude.
|
|
29
|
+
- **Open Questions** — collect unresolved items, tag each `[PO]` / `[Tech]` /
|
|
30
|
+
`[Team]`, ask if any remain.
|
|
31
|
+
- **Technical Notes** — leave empty; it's populated by `groom`. If the user
|
|
32
|
+
volunteers technical context, note it but say the full analysis is `groom`.
|
|
33
|
+
5. **Assemble** the complete story and present it whole for a final review.
|
|
34
|
+
6. **Post** on approval per `shared/provider-io.md` — a comment on remote
|
|
35
|
+
providers; for `local-markdown`, offer the in-place overwrite of the source
|
|
36
|
+
file (this command is one of the two that may rewrite a story in place).
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
- The interactivity is the value — don't rush sections; give the user room to
|
|
41
|
+
correct. Be transparent about inferences: "I'm inferring X from the
|
|
42
|
+
description — right?"
|
|
43
|
+
- If the story looks too large mid-refinement (many ACs, broad scope), suggest
|
|
44
|
+
splitting rather than pushing a bloated story through.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# shared/context.md — domain + convention context
|
|
2
|
+
|
|
3
|
+
`improve` and `groom` are stronger when grounded in the team's actual repos and
|
|
4
|
+
patterns. v3.0 keeps that context in two places (there are no `repos-metadata`
|
|
5
|
+
or `conventions` markdown files — those were v2.x, and are gone):
|
|
6
|
+
|
|
7
|
+
- **`.claude/context/repos.yaml`** — the registered repos and their local
|
|
8
|
+
paths. This is the map of what exists and where it lives on disk.
|
|
9
|
+
- **`.claude/context/repo-map/<repo-name>/`** — the auto-generated, tiered
|
|
10
|
+
codebase map (purpose by directory, key abstractions, notable patterns),
|
|
11
|
+
stamped with the SHA it was generated at. This is where "the team uses the
|
|
12
|
+
repository pattern / MediatR / …" comes from; read it rather than re-deriving
|
|
13
|
+
the codebase from scratch.
|
|
14
|
+
|
|
15
|
+
Read both with the `Read` tool. Treat them as **context, not gospel**: the
|
|
16
|
+
repo-map may be stale (it records its own generation SHA) and the user knows
|
|
17
|
+
things the code doesn't. If a repo-map is absent for a repo, say so — `groom`
|
|
18
|
+
can still scan the repository directly (see `commands/groom.md`), and `improve`
|
|
19
|
+
proceeds on the work item alone.
|
|
20
|
+
|
|
21
|
+
Never write anything under `.claude/context/` from this skill — that tree is
|
|
22
|
+
owned by `/init-workspace`, `/add-repo`, and `/repo-map-refresh`.
|