work-kit-cli 0.2.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -13
- package/cli/src/commands/bootstrap.test.ts +40 -0
- package/cli/src/commands/bootstrap.ts +77 -13
- package/cli/src/commands/cancel.ts +1 -16
- package/cli/src/commands/complete.ts +92 -98
- package/cli/src/commands/completions.ts +2 -2
- package/cli/src/commands/doctor.ts +1 -1
- package/cli/src/commands/extract.ts +217 -0
- package/cli/src/commands/init.test.ts +50 -0
- package/cli/src/commands/init.ts +70 -35
- package/cli/src/commands/learn.test.ts +217 -0
- package/cli/src/commands/learn.ts +104 -0
- package/cli/src/commands/loopback.ts +8 -11
- package/cli/src/commands/next.ts +93 -60
- package/cli/src/commands/observe.ts +16 -21
- package/cli/src/commands/pause-resume.test.ts +142 -0
- package/cli/src/commands/pause.ts +34 -0
- package/cli/src/commands/report.ts +217 -0
- package/cli/src/commands/resume.ts +126 -0
- package/cli/src/commands/setup.ts +280 -0
- package/cli/src/commands/status.ts +8 -6
- package/cli/src/commands/uninstall.ts +8 -3
- package/cli/src/commands/workflow.ts +43 -33
- package/cli/src/config/agent-map.ts +9 -9
- package/cli/src/config/constants.ts +54 -0
- package/cli/src/config/loopback-routes.ts +13 -13
- package/cli/src/config/model-routing.test.ts +190 -0
- package/cli/src/config/model-routing.ts +208 -0
- package/cli/src/config/project-config.test.ts +127 -0
- package/cli/src/config/project-config.ts +106 -0
- package/cli/src/config/{phases.ts → workflow.ts} +40 -23
- package/cli/src/context/prompt-builder.ts +10 -9
- package/cli/src/index.ts +130 -9
- package/cli/src/observer/data.ts +196 -65
- package/cli/src/observer/renderer.ts +127 -107
- package/cli/src/observer/watcher.ts +28 -16
- package/cli/src/state/helpers.test.ts +28 -28
- package/cli/src/state/helpers.ts +37 -25
- package/cli/src/state/schema.ts +135 -45
- package/cli/src/state/store.ts +127 -7
- package/cli/src/state/validators.test.ts +13 -13
- package/cli/src/state/validators.ts +3 -4
- package/cli/src/utils/colors.ts +2 -0
- package/cli/src/utils/fs.ts +13 -0
- package/cli/src/utils/json.ts +20 -0
- package/cli/src/utils/knowledge.ts +471 -0
- package/cli/src/utils/time.ts +27 -0
- package/cli/src/{engine → workflow}/loopbacks.test.ts +2 -2
- package/cli/src/workflow/loopbacks.ts +42 -0
- package/cli/src/workflow/parallel.ts +64 -0
- package/cli/src/workflow/transitions.test.ts +129 -0
- package/cli/src/{engine → workflow}/transitions.ts +18 -22
- package/package.json +2 -2
- package/skills/auto-kit/SKILL.md +44 -27
- package/skills/cancel-kit/SKILL.md +4 -4
- package/skills/full-kit/SKILL.md +45 -28
- package/skills/pause-kit/SKILL.md +25 -0
- package/skills/resume-kit/SKILL.md +64 -0
- package/skills/wk-bootstrap/SKILL.md +11 -5
- package/skills/wk-build/SKILL.md +12 -11
- package/skills/wk-build/{stages → steps}/commit.md +1 -1
- package/skills/wk-build/{stages → steps}/core.md +3 -3
- package/skills/wk-build/{stages → steps}/integration.md +2 -2
- package/skills/wk-build/{stages → steps}/migration.md +1 -1
- package/skills/wk-build/{stages → steps}/red.md +1 -1
- package/skills/wk-build/{stages → steps}/refactor.md +1 -1
- package/skills/wk-build/{stages → steps}/setup.md +1 -1
- package/skills/wk-build/{stages → steps}/ui.md +1 -1
- package/skills/wk-deploy/SKILL.md +7 -6
- package/skills/wk-deploy/{stages → steps}/merge.md +1 -1
- package/skills/wk-deploy/{stages → steps}/monitor.md +1 -1
- package/skills/wk-deploy/{stages → steps}/remediate.md +1 -1
- package/skills/wk-plan/SKILL.md +15 -14
- package/skills/wk-plan/{stages → steps}/architecture.md +1 -1
- package/skills/wk-plan/{stages → steps}/audit.md +2 -2
- package/skills/wk-plan/{stages → steps}/blueprint.md +2 -2
- package/skills/wk-plan/{stages → steps}/clarify.md +1 -1
- package/skills/wk-plan/{stages → steps}/investigate.md +1 -1
- package/skills/wk-plan/{stages → steps}/scope.md +1 -1
- package/skills/wk-plan/{stages → steps}/sketch.md +1 -1
- package/skills/wk-plan/{stages → steps}/ux-flow.md +1 -1
- package/skills/wk-review/SKILL.md +11 -10
- package/skills/wk-review/{stages → steps}/compliance.md +1 -1
- package/skills/wk-review/{stages → steps}/handoff.md +2 -2
- package/skills/wk-review/{stages → steps}/performance.md +1 -1
- package/skills/wk-review/{stages → steps}/security.md +1 -1
- package/skills/wk-review/{stages → steps}/self-review.md +1 -1
- package/skills/wk-test/SKILL.md +9 -8
- package/skills/wk-test/steps/e2e.md +56 -0
- package/skills/wk-test/{stages → steps}/validate.md +1 -1
- package/skills/wk-test/{stages → steps}/verify.md +1 -1
- package/skills/wk-wrap-up/SKILL.md +19 -5
- package/skills/wk-wrap-up/steps/knowledge.md +76 -0
- package/skills/wk-wrap-up/steps/summary.md +86 -0
- package/cli/src/engine/loopbacks.ts +0 -32
- package/cli/src/engine/parallel.ts +0 -60
- package/cli/src/engine/transitions.test.ts +0 -129
- package/skills/wk-test/stages/e2e.md +0 -53
- /package/cli/src/{engine/phases.ts → workflow/gates.ts} +0 -0
package/skills/wk-test/SKILL.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test
|
|
3
|
-
description: "Run the Test phase — 3
|
|
3
|
+
description: "Run the Test phase — 3 steps: Verify, E2E, Validate."
|
|
4
4
|
user-invocable: false
|
|
5
5
|
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
You are the **QA Lead**. Validate the implementation against the Blueprint and acceptance criteria.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Steps (in order)
|
|
11
11
|
|
|
12
12
|
1. **Verify** — Run existing test suite, check for regressions
|
|
13
13
|
2. **E2E** — Test user flows end-to-end
|
|
@@ -15,11 +15,11 @@ You are the **QA Lead**. Validate the implementation against the Blueprint and a
|
|
|
15
15
|
|
|
16
16
|
## Execution
|
|
17
17
|
|
|
18
|
-
For each
|
|
19
|
-
1. Read the
|
|
18
|
+
For each step:
|
|
19
|
+
1. Read the step file (e.g., `.claude/skills/wk-test/steps/verify.md`)
|
|
20
20
|
2. Follow its instructions
|
|
21
21
|
3. Update `.work-kit/state.md` with outputs
|
|
22
|
-
4. Proceed to next
|
|
22
|
+
4. Proceed to next step
|
|
23
23
|
|
|
24
24
|
## Key Principle
|
|
25
25
|
|
|
@@ -27,10 +27,11 @@ For each sub-stage:
|
|
|
27
27
|
|
|
28
28
|
## Recording
|
|
29
29
|
|
|
30
|
-
Throughout every
|
|
30
|
+
Throughout every step, update the shared state.md sections:
|
|
31
31
|
|
|
32
32
|
- **`## Criteria`** — Check off criteria as they're verified. Add evidence inline: `- [x] <criterion> — verified by <test name / screenshot / manual check>`.
|
|
33
33
|
- **`## Decisions`** — If you discover a criterion is untestable or needs reinterpretation, record the decision and why.
|
|
34
|
+
- **`## Observations`** — Whenever you notice a fragile area, a missing test pattern, or feedback about the test phase itself, append: `- [lesson|convention|risk|workflow] text` (workflow tag may include `:phase/step`). At `wrap-up/knowledge` these are routed to `.work-kit-knowledge/` so future sessions benefit.
|
|
34
35
|
|
|
35
36
|
The criteria checklist is copied directly into the final work-kit log. Make it accurate.
|
|
36
37
|
|
|
@@ -51,7 +52,7 @@ Agent: Verify ──┐
|
|
|
51
52
|
Agent: E2E ──┘
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
Each sub-agent reads the same Context Input sections and writes its own `### Test: <
|
|
55
|
+
Each sub-agent reads the same Context Input sections and writes its own `### Test: <step>` section to state.md.
|
|
55
56
|
|
|
56
57
|
## Boundaries
|
|
57
58
|
|
|
@@ -74,7 +75,7 @@ Each sub-agent reads the same Context Input sections and writes its own `### Tes
|
|
|
74
75
|
|
|
75
76
|
## Final Output
|
|
76
77
|
|
|
77
|
-
After all
|
|
78
|
+
After all steps are done, append a `### Test: Final` section to state.md. This is what **Review agents read**.
|
|
78
79
|
|
|
79
80
|
```markdown
|
|
80
81
|
### Test: Final
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Test step: Test user flows end-to-end."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# E2E
|
|
6
|
+
|
|
7
|
+
**Role:** End-to-End Tester
|
|
8
|
+
**Goal:** Test the feature as a user would experience it.
|
|
9
|
+
|
|
10
|
+
## Instructions
|
|
11
|
+
|
|
12
|
+
1. **Verify Playwright is installed.** Run `npx playwright --version`. If it fails or `@playwright/test` is missing from `package.json`, STOP and tell the user to run `work-kit setup` (which installs Playwright + Chromium and scaffolds a config).
|
|
13
|
+
2. Review the UX Flow from the Plan phase.
|
|
14
|
+
3. For each user flow defined:
|
|
15
|
+
- Write a Playwright test under the project's configured `testDir` (see `playwright.config.*`).
|
|
16
|
+
- Test the happy path.
|
|
17
|
+
- Test key edge cases (empty state, error state, boundary values).
|
|
18
|
+
4. Run the tests with `npx playwright test`. All flows must pass before marking this step done.
|
|
19
|
+
5. Capture screenshots at key states using Playwright's `page.screenshot()` or the `--trace on` flag.
|
|
20
|
+
6. Focus on the most important flows — don't test every permutation.
|
|
21
|
+
|
|
22
|
+
## Output (append to state.md)
|
|
23
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
### Test: E2E
|
|
26
|
+
|
|
27
|
+
**Verdict:** pass | fail
|
|
28
|
+
**Tests Written:**
|
|
29
|
+
- `<test file>`: <flow description>
|
|
30
|
+
|
|
31
|
+
**Flows Verified:**
|
|
32
|
+
- <flow 1>: pass | fail (<details>)
|
|
33
|
+
- <flow 2>: pass | fail (<details>)
|
|
34
|
+
|
|
35
|
+
**Screenshots:**
|
|
36
|
+
- <description>: <path or "not applicable">
|
|
37
|
+
|
|
38
|
+
**Notes:**
|
|
39
|
+
- <edge cases tested, issues found>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- Playwright is the required E2E framework. Manual verification does NOT satisfy this step.
|
|
45
|
+
- If Playwright is missing, halt and direct the user to `work-kit setup` — do not fall back to curl, manual steps, or another framework.
|
|
46
|
+
- Focus on user-visible behavior, not internal implementation.
|
|
47
|
+
- Screenshots are evidence — capture them for key states.
|
|
48
|
+
- If a flow fails, fix the implementation (not the test) unless the test expectation is wrong.
|
|
49
|
+
|
|
50
|
+
## Anti-Rationalization
|
|
51
|
+
|
|
52
|
+
| Excuse | Reality |
|
|
53
|
+
|--------|---------|
|
|
54
|
+
| "Manual verification counts as E2E testing" | It does not. The E2E step requires automated Playwright tests. If Playwright is unavailable, halt and ask the user to run `work-kit setup`. |
|
|
55
|
+
| "Unit tests already cover this flow" | Unit tests mock boundaries. E2E tests verify the real flow across boundaries — database, API, UI. A function can pass its unit test and still fail in the real pipeline. |
|
|
56
|
+
| "E2E tests are slow and fragile, not worth the effort" | Slow tests that catch real bugs are more valuable than fast tests that miss them. Write focused E2E tests for critical paths, not exhaustive ones for every edge case. |
|
|
@@ -10,18 +10,32 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
|
10
10
|
**Role:** Work Historian
|
|
11
11
|
**Goal:** Produce a concise, useful summary of what was built and why — then clean up.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
This phase has **two steps** (in order):
|
|
14
|
+
|
|
15
|
+
1. **`wrap-up/summary`** — distill state.md into a useful summary for future developers. See `.claude/skills/wk-wrap-up/steps/summary.md`.
|
|
16
|
+
2. **`wrap-up/knowledge`** — harvest learnings from this session into the project's `.work-kit-knowledge/` files so the next session benefits. See `.claude/skills/wk-wrap-up/steps/knowledge.md`.
|
|
17
|
+
|
|
18
|
+
The summary you write goes into `.work-kit/summary.md`; the CLI archives it into `.work-kit-tracker/archive/<slug>-<date>/` when you call `work-kit complete wrap-up/summary --outcome done`. After summary completes, the `knowledge` step runs `work-kit extract` and (optionally) one or more `work-kit learn` calls.
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
## Instructions
|
|
16
21
|
|
|
22
|
+
### Step 1: summary
|
|
17
23
|
1. **Read the full `.work-kit/state.md`** — every phase output from Plan through the last completed phase
|
|
18
24
|
2. **Synthesize the summary** — not a copy-paste of state, but a distilled record that a future developer (or agent) would find useful
|
|
19
|
-
3. **
|
|
20
|
-
4. **
|
|
25
|
+
3. **Write `.work-kit/summary.md`** in the format described in the step file
|
|
26
|
+
4. **Run** `work-kit complete wrap-up/summary --outcome done`
|
|
27
|
+
|
|
28
|
+
### Step 2: knowledge
|
|
29
|
+
5. **Run `work-kit extract`** — mechanically routes Observations / Decisions / Deviations / loopbacks into `.work-kit-knowledge/` files
|
|
30
|
+
6. **Review the summary you just wrote** for subjective additions the parser would miss. For each, call `work-kit learn --type <lesson|convention|risk|workflow> --text "..."`.
|
|
31
|
+
7. **Run** `work-kit complete wrap-up/knowledge --outcome done`
|
|
32
|
+
|
|
33
|
+
### Cleanup
|
|
34
|
+
8. **Ask the user** if they want the worktree and branch removed
|
|
21
35
|
|
|
22
36
|
## Summary File Format
|
|
23
37
|
|
|
24
|
-
Overwrite `.work-kit
|
|
38
|
+
Overwrite `.work-kit/summary.md`:
|
|
25
39
|
|
|
26
40
|
```markdown
|
|
27
41
|
---
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Step: Knowledge
|
|
2
|
+
|
|
3
|
+
**Phase:** Wrap-up
|
|
4
|
+
**Role:** Knowledge Harvester
|
|
5
|
+
**Goal:** Route this session's learnings into the project's `.work-kit-knowledge/` files so the next session — and the next developer — starts smarter.
|
|
6
|
+
|
|
7
|
+
## When this step runs
|
|
8
|
+
|
|
9
|
+
After `wrap-up/summary`. By now you've just re-read the full `state.md` and distilled it into a summary, so your working memory of this session is at its peak. This is the right moment to capture observations the parser would miss.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
1. **Run mechanical extraction:**
|
|
14
|
+
```bash
|
|
15
|
+
work-kit extract
|
|
16
|
+
```
|
|
17
|
+
This parses `.work-kit/state.md` and `.work-kit/tracker.json` and routes entries to `.work-kit-knowledge/{lessons,conventions,risks,workflow}.md`. It pulls from:
|
|
18
|
+
- `## Observations` typed bullets (`- [lesson|convention|risk|workflow] text`)
|
|
19
|
+
- `## Decisions` → conventions
|
|
20
|
+
- `## Deviations` → workflow feedback
|
|
21
|
+
- `tracker.json.loopbacks[]` → workflow feedback
|
|
22
|
+
- Skipped/failed steps → workflow feedback
|
|
23
|
+
|
|
24
|
+
The output JSON tells you how many entries were `written` vs `duplicates`. Re-running is idempotent.
|
|
25
|
+
|
|
26
|
+
2. **Read your `.work-kit/summary.md`** (the one you just wrote). For each non-obvious thing in it that the parser would NOT have captured automatically, call `work-kit learn`:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
work-kit learn --type lesson --text "Discovered that the test fixtures must be reset between Playwright suites, otherwise auth state leaks."
|
|
30
|
+
work-kit learn --type risk --text "src/payment/webhook.ts has no integration test coverage for retries."
|
|
31
|
+
work-kit learn --type convention --text "All new API endpoints must register a Zod schema in src/schemas/."
|
|
32
|
+
work-kit learn --type workflow --text "The wk-test/e2e step doesn't tell agents to start the dev server before running Playwright."
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Each call appends one entry to the appropriate `.md` file under a lockfile, with secret redaction applied automatically.
|
|
36
|
+
|
|
37
|
+
3. **Mark the step complete:**
|
|
38
|
+
```bash
|
|
39
|
+
work-kit complete wrap-up/knowledge --outcome done
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## What goes where
|
|
43
|
+
|
|
44
|
+
| Type | File | What belongs here |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `lesson` | lessons.md | Project-specific learnings — facts about *this* codebase. |
|
|
47
|
+
| `convention` | conventions.md | Codified rules this project follows. Future sessions should respect these. |
|
|
48
|
+
| `risk` | risks.md | Fragile or dangerous areas. Touch with care. |
|
|
49
|
+
| `workflow` | workflow.md | Feedback about the work-kit kit itself — skill quality, step skips, loopbacks, failure modes. **Mined manually across projects to improve work-kit upstream.** |
|
|
50
|
+
|
|
51
|
+
## Boundaries
|
|
52
|
+
|
|
53
|
+
### Always
|
|
54
|
+
- Run `work-kit extract` first, then add manual `learn` calls.
|
|
55
|
+
- Keep `learn --text` entries to one sentence — they're for humans skimming a list.
|
|
56
|
+
- Use `workflow` type only for feedback about the work-kit *itself*, not for project facts.
|
|
57
|
+
|
|
58
|
+
### Never
|
|
59
|
+
- Edit the `## Manual` section of any knowledge file. That's human-curated and tooling never touches it.
|
|
60
|
+
- Use `workflow.md` for project-specific facts. Use `lessons.md` instead.
|
|
61
|
+
- Paste large code blocks, file contents, or stack traces into `--text`. Distill into one sentence.
|
|
62
|
+
- Skip extraction. Even if you have nothing to add manually, `work-kit extract` still routes loopbacks and deviations.
|
|
63
|
+
|
|
64
|
+
### Failure mode
|
|
65
|
+
- Non-fatal. If extract or learn fails, the summary step has already succeeded — the session isn't lost. Report the error to the user; they can retry manually or run `work-kit complete wrap-up/knowledge --outcome done` anyway.
|
|
66
|
+
|
|
67
|
+
## Output
|
|
68
|
+
|
|
69
|
+
No file output for this step — entries land in `.work-kit-knowledge/*.md`. Optionally append a one-line note to `.work-kit/state.md` describing what you captured, e.g.:
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
### Wrap-up: Knowledge
|
|
73
|
+
|
|
74
|
+
**Extracted:** 4 entries (2 conventions, 1 risk, 1 workflow)
|
|
75
|
+
**Manual additions:** 2 lessons, 1 workflow feedback
|
|
76
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Step: Summary
|
|
2
|
+
|
|
3
|
+
**Phase:** Wrap-up
|
|
4
|
+
**Role:** Work Historian
|
|
5
|
+
**Goal:** Distill the full state.md into a useful summary for future developers, then clean up.
|
|
6
|
+
|
|
7
|
+
## Workflow
|
|
8
|
+
|
|
9
|
+
The CLI archives `state.md`, `tracker.json`, and (if you wrote one) `summary.md` into
|
|
10
|
+
`.work-kit-tracker/archive/<slug>-<date>/` automatically when the wrap-up step completes.
|
|
11
|
+
It also appends a row to `.work-kit-tracker/index.md`.
|
|
12
|
+
|
|
13
|
+
**Your job:** write a real `summary.md` to `.work-kit/summary.md` *before* calling
|
|
14
|
+
`work-kit complete wrap-up/summary`. The CLI will pick it up and place it in the archive.
|
|
15
|
+
|
|
16
|
+
## Instructions
|
|
17
|
+
|
|
18
|
+
1. **Read the full `.work-kit/state.md`** — every phase output from Plan through Deploy.
|
|
19
|
+
2. **Synthesize the summary** — not a copy-paste; a distillation a future developer can use.
|
|
20
|
+
3. **Write `.work-kit/summary.md`** with the format below.
|
|
21
|
+
4. **Run** `work-kit complete wrap-up/summary --outcome done`.
|
|
22
|
+
5. **Ask the user** if they want the worktree and feature branch removed (use `work-kit cancel` only if no merge happened; otherwise prefer `git worktree remove`).
|
|
23
|
+
|
|
24
|
+
## Summary File Format
|
|
25
|
+
|
|
26
|
+
Write to `.work-kit/summary.md`:
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
---
|
|
30
|
+
slug: <slug>
|
|
31
|
+
branch: feature/<slug>
|
|
32
|
+
pr: <#number or n/a>
|
|
33
|
+
started: <YYYY-MM-DD>
|
|
34
|
+
completed: <YYYY-MM-DD>
|
|
35
|
+
status: <completed | partial | rolled-back>
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Summary
|
|
39
|
+
<2-3 sentences: what was built, why it was needed, and the end state>
|
|
40
|
+
|
|
41
|
+
## Criteria
|
|
42
|
+
<copy the final criteria checklist from state.md — checked and unchecked>
|
|
43
|
+
|
|
44
|
+
## Key Decisions
|
|
45
|
+
<only the non-obvious ones — decisions where the alternative was reasonable>
|
|
46
|
+
- <decision>: <what was chosen> — <why, in one line>
|
|
47
|
+
|
|
48
|
+
## Deviations from Plan
|
|
49
|
+
<anything that changed between Blueprint and final implementation — skip if none>
|
|
50
|
+
- <what changed and why>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Include vs. Exclude
|
|
54
|
+
|
|
55
|
+
**Include:**
|
|
56
|
+
- Decisions where you chose between real alternatives
|
|
57
|
+
- Deviations from the Blueprint (and why)
|
|
58
|
+
- Anything a future developer would need to understand the "why" behind the code
|
|
59
|
+
- Criteria status — what was met, what wasn't
|
|
60
|
+
|
|
61
|
+
**Exclude:**
|
|
62
|
+
- Artifact lists (files, PRs, migrations) — derivable from git
|
|
63
|
+
- Routine implementation details ("created file X, modified file Y")
|
|
64
|
+
- Full phase outputs — distill, don't dump
|
|
65
|
+
- Internal process notes ("ran tests 3 times before they passed")
|
|
66
|
+
|
|
67
|
+
## Boundaries
|
|
68
|
+
|
|
69
|
+
### Always
|
|
70
|
+
- Read the full state.md before writing the summary
|
|
71
|
+
- Include every non-obvious decision in Key Decisions
|
|
72
|
+
- Include every deviation from the Blueprint in Deviations
|
|
73
|
+
|
|
74
|
+
### Never
|
|
75
|
+
- Copy-paste full phase outputs into the summary
|
|
76
|
+
- Skip the criteria checklist
|
|
77
|
+
|
|
78
|
+
## After Completion
|
|
79
|
+
|
|
80
|
+
When you call `work-kit complete wrap-up/summary --outcome done`, the CLI:
|
|
81
|
+
|
|
82
|
+
1. Creates `.work-kit-tracker/archive/<slug>-<date>/`
|
|
83
|
+
2. Copies `state.md`, `tracker.json`, and `summary.md` into it
|
|
84
|
+
3. Appends a row to `.work-kit-tracker/index.md`
|
|
85
|
+
|
|
86
|
+
You may then commit the archive to the main branch and remove the worktree.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { PhaseName, Location } from "../state/schema.js";
|
|
2
|
-
import { LOOPBACK_ROUTES } from "../config/loopback-routes.js";
|
|
3
|
-
|
|
4
|
-
interface LoopbackResult {
|
|
5
|
-
to: Location;
|
|
6
|
-
reason: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Check if completing a sub-stage with a given outcome should trigger a loop-back.
|
|
11
|
-
*/
|
|
12
|
-
export function checkLoopback(
|
|
13
|
-
phase: PhaseName,
|
|
14
|
-
subStage: string,
|
|
15
|
-
outcome?: string
|
|
16
|
-
): LoopbackResult | null {
|
|
17
|
-
if (!outcome) return null;
|
|
18
|
-
|
|
19
|
-
const route = LOOPBACK_ROUTES.find(
|
|
20
|
-
(r) =>
|
|
21
|
-
r.from.phase === phase &&
|
|
22
|
-
r.from.subStage === subStage &&
|
|
23
|
-
r.triggerOutcome === outcome
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
if (!route) return null;
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
to: route.to,
|
|
30
|
-
reason: route.reason,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { PhaseName, WorkKitState } from "../state/schema.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Defines which sub-stages run in parallel and which runs sequentially after.
|
|
5
|
-
*/
|
|
6
|
-
export interface ParallelGroup {
|
|
7
|
-
parallel: string[]; // sub-stages that run concurrently
|
|
8
|
-
thenSequential?: string; // sub-stage that runs after all parallel complete
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Parallel group definitions per phase.
|
|
13
|
-
*/
|
|
14
|
-
const PARALLEL_GROUPS: Record<string, ParallelGroup> = {
|
|
15
|
-
test: {
|
|
16
|
-
parallel: ["verify", "e2e"],
|
|
17
|
-
thenSequential: "validate",
|
|
18
|
-
},
|
|
19
|
-
review: {
|
|
20
|
-
parallel: ["self-review", "security", "performance", "compliance"],
|
|
21
|
-
thenSequential: "handoff",
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Check if a sub-stage triggers a parallel group.
|
|
27
|
-
* Triggers on any parallel member that is the first non-skipped one in the group.
|
|
28
|
-
* Returns null if the sub-stage is not a parallel trigger or the group doesn't apply.
|
|
29
|
-
*/
|
|
30
|
-
export function getParallelGroup(phase: PhaseName, subStage: string, state?: WorkKitState): ParallelGroup | null {
|
|
31
|
-
const group = PARALLEL_GROUPS[phase];
|
|
32
|
-
if (!group) return null;
|
|
33
|
-
|
|
34
|
-
if (!group.parallel.includes(subStage)) return null;
|
|
35
|
-
|
|
36
|
-
// Find the first non-skipped parallel member
|
|
37
|
-
if (state) {
|
|
38
|
-
const phaseState = state.phases[phase];
|
|
39
|
-
const firstActive = group.parallel.find((ss) => {
|
|
40
|
-
const ssState = phaseState?.subStages[ss];
|
|
41
|
-
return ssState && ssState.status !== "skipped" && ssState.status !== "completed";
|
|
42
|
-
});
|
|
43
|
-
// Only trigger if this sub-stage is the first active parallel member
|
|
44
|
-
if (firstActive !== subStage) return null;
|
|
45
|
-
} else {
|
|
46
|
-
// No state provided — fall back to first-member trigger
|
|
47
|
-
if (group.parallel[0] !== subStage) return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return group;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Check if a sub-stage is a parallel member (part of a group, not necessarily trigger).
|
|
55
|
-
*/
|
|
56
|
-
export function isParallelMember(phase: PhaseName, subStage: string): boolean {
|
|
57
|
-
const group = PARALLEL_GROUPS[phase];
|
|
58
|
-
if (!group) return false;
|
|
59
|
-
return group.parallel.includes(subStage);
|
|
60
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "node:test";
|
|
2
|
-
import * as assert from "node:assert/strict";
|
|
3
|
-
import { nextSubStageInPhase, isPhaseComplete, determineNextStep } from "./transitions.js";
|
|
4
|
-
import type { WorkKitState, PhaseName, PhaseState, SubStageState } from "../state/schema.js";
|
|
5
|
-
import { PHASE_NAMES, SUBSTAGES_BY_PHASE } from "../state/schema.js";
|
|
6
|
-
|
|
7
|
-
function makeState(): WorkKitState {
|
|
8
|
-
const phases = {} as Record<PhaseName, PhaseState>;
|
|
9
|
-
for (const phase of PHASE_NAMES) {
|
|
10
|
-
const subStages: Record<string, SubStageState> = {};
|
|
11
|
-
for (const ss of SUBSTAGES_BY_PHASE[phase]) {
|
|
12
|
-
subStages[ss] = { status: "pending" };
|
|
13
|
-
}
|
|
14
|
-
phases[phase] = { status: "pending", subStages };
|
|
15
|
-
}
|
|
16
|
-
return {
|
|
17
|
-
version: 1,
|
|
18
|
-
slug: "test",
|
|
19
|
-
branch: "feature/test",
|
|
20
|
-
started: "2026-01-01",
|
|
21
|
-
mode: "full-kit",
|
|
22
|
-
status: "in-progress",
|
|
23
|
-
currentPhase: "plan",
|
|
24
|
-
currentSubStage: "clarify",
|
|
25
|
-
phases,
|
|
26
|
-
loopbacks: [],
|
|
27
|
-
metadata: { worktreeRoot: "/tmp/test", mainRepoRoot: "/tmp/test" },
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
describe("nextSubStageInPhase", () => {
|
|
32
|
-
it("returns first pending sub-stage", () => {
|
|
33
|
-
const state = makeState();
|
|
34
|
-
const result = nextSubStageInPhase(state, "plan");
|
|
35
|
-
assert.equal(result, "clarify");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("returns null when all complete or skipped", () => {
|
|
39
|
-
const state = makeState();
|
|
40
|
-
for (const ss of Object.values(state.phases.plan.subStages)) {
|
|
41
|
-
ss.status = "completed";
|
|
42
|
-
}
|
|
43
|
-
const result = nextSubStageInPhase(state, "plan");
|
|
44
|
-
assert.equal(result, null);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("skips completed sub-stages and returns next pending", () => {
|
|
48
|
-
const state = makeState();
|
|
49
|
-
state.phases.plan.subStages.clarify.status = "completed";
|
|
50
|
-
state.phases.plan.subStages.investigate.status = "completed";
|
|
51
|
-
const result = nextSubStageInPhase(state, "plan");
|
|
52
|
-
assert.equal(result, "sketch");
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe("isPhaseComplete", () => {
|
|
57
|
-
it("returns true when all complete or skipped", () => {
|
|
58
|
-
const state = makeState();
|
|
59
|
-
for (const ss of Object.values(state.phases.plan.subStages)) {
|
|
60
|
-
ss.status = "completed";
|
|
61
|
-
}
|
|
62
|
-
assert.equal(isPhaseComplete(state, "plan"), true);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("returns true with mix of completed and skipped", () => {
|
|
66
|
-
const state = makeState();
|
|
67
|
-
let first = true;
|
|
68
|
-
for (const ss of Object.values(state.phases.plan.subStages)) {
|
|
69
|
-
ss.status = first ? "skipped" : "completed";
|
|
70
|
-
first = false;
|
|
71
|
-
}
|
|
72
|
-
assert.equal(isPhaseComplete(state, "plan"), true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("returns false when some sub-stages are pending", () => {
|
|
76
|
-
const state = makeState();
|
|
77
|
-
assert.equal(isPhaseComplete(state, "plan"), false);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
describe("determineNextStep", () => {
|
|
82
|
-
it("returns complete when state is completed", () => {
|
|
83
|
-
const state = makeState();
|
|
84
|
-
state.status = "completed";
|
|
85
|
-
const step = determineNextStep(state);
|
|
86
|
-
assert.equal(step.type, "complete");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("returns phase-boundary when no current phase", () => {
|
|
90
|
-
const state = makeState();
|
|
91
|
-
state.currentPhase = null;
|
|
92
|
-
const step = determineNextStep(state);
|
|
93
|
-
assert.equal(step.type, "phase-boundary");
|
|
94
|
-
assert.equal(step.phase, "plan");
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it("returns sub-stage for current phase with pending work", () => {
|
|
98
|
-
const state = makeState();
|
|
99
|
-
state.currentPhase = "plan";
|
|
100
|
-
state.phases.plan.status = "in-progress";
|
|
101
|
-
const step = determineNextStep(state);
|
|
102
|
-
assert.equal(step.type, "sub-stage");
|
|
103
|
-
assert.equal(step.phase, "plan");
|
|
104
|
-
assert.equal(step.subStage, "clarify");
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("auto-proceeds to next phase by default when current phase is complete", () => {
|
|
108
|
-
const state = makeState();
|
|
109
|
-
state.currentPhase = "plan";
|
|
110
|
-
for (const ss of Object.values(state.phases.plan.subStages)) {
|
|
111
|
-
ss.status = "completed";
|
|
112
|
-
}
|
|
113
|
-
const step = determineNextStep(state);
|
|
114
|
-
assert.equal(step.type, "phase-boundary");
|
|
115
|
-
assert.equal(step.phase, "build");
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("returns wait-for-user when gated and current phase is complete", () => {
|
|
119
|
-
const state = makeState();
|
|
120
|
-
state.gated = true;
|
|
121
|
-
state.currentPhase = "plan";
|
|
122
|
-
for (const ss of Object.values(state.phases.plan.subStages)) {
|
|
123
|
-
ss.status = "completed";
|
|
124
|
-
}
|
|
125
|
-
const step = determineNextStep(state);
|
|
126
|
-
assert.equal(step.type, "wait-for-user");
|
|
127
|
-
assert.equal(step.phase, "build");
|
|
128
|
-
});
|
|
129
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Test sub-stage: Test user flows end-to-end."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# E2E
|
|
6
|
-
|
|
7
|
-
**Role:** End-to-End Tester
|
|
8
|
-
**Goal:** Test the feature as a user would experience it.
|
|
9
|
-
|
|
10
|
-
## Instructions
|
|
11
|
-
|
|
12
|
-
1. Review the UX Flow from the Plan phase
|
|
13
|
-
2. For each user flow defined:
|
|
14
|
-
- Write an E2E test (Playwright, Cypress, or manual verification)
|
|
15
|
-
- Test the happy path
|
|
16
|
-
- Test key edge cases (empty state, error state, boundary values)
|
|
17
|
-
3. Take screenshots at key states if the test framework supports it
|
|
18
|
-
4. Focus on the most important flows — don't test every permutation
|
|
19
|
-
|
|
20
|
-
## Output (append to state.md)
|
|
21
|
-
|
|
22
|
-
```markdown
|
|
23
|
-
### Test: E2E
|
|
24
|
-
|
|
25
|
-
**Verdict:** pass | fail
|
|
26
|
-
**Tests Written:**
|
|
27
|
-
- `<test file>`: <flow description>
|
|
28
|
-
|
|
29
|
-
**Flows Verified:**
|
|
30
|
-
- <flow 1>: pass | fail (<details>)
|
|
31
|
-
- <flow 2>: pass | fail (<details>)
|
|
32
|
-
|
|
33
|
-
**Screenshots:**
|
|
34
|
-
- <description>: <path or "not applicable">
|
|
35
|
-
|
|
36
|
-
**Notes:**
|
|
37
|
-
- <edge cases tested, issues found>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Rules
|
|
41
|
-
|
|
42
|
-
- If the project has no E2E framework, test manually and document the steps
|
|
43
|
-
- Focus on user-visible behavior, not internal implementation
|
|
44
|
-
- Screenshots are evidence — capture them for key states
|
|
45
|
-
- If a flow fails, fix the implementation (not the test) unless the test expectation is wrong
|
|
46
|
-
|
|
47
|
-
## Anti-Rationalization
|
|
48
|
-
|
|
49
|
-
| Excuse | Reality |
|
|
50
|
-
|--------|---------|
|
|
51
|
-
| "Manual verification counts as E2E testing" | Manual verification is not repeatable, not documented, and not run in CI. If you cannot automate it, at minimum document the exact manual steps with expected results. |
|
|
52
|
-
| "Unit tests already cover this flow" | Unit tests mock boundaries. E2E tests verify the real flow across boundaries — database, API, UI. A function can pass its unit test and still fail in the real pipeline. |
|
|
53
|
-
| "E2E tests are slow and fragile, not worth the effort" | Slow tests that catch real bugs are more valuable than fast tests that miss them. Write focused E2E tests for critical paths, not exhaustive ones for every edge case. |
|
|
File without changes
|