@shenlee/devcrew 0.1.4 → 0.1.5
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/packages/adapters/src/index.js +41 -1
- package/dist/packages/core/src/version.js +1 -1
- package/docs/claude-code.md +1 -1
- package/docs/codex.md +2 -2
- package/docs/quickstart.md +1 -1
- package/package.json +2 -2
- package/packages/adapters/src/index.ts +52 -3
- package/packages/core/src/version.ts +1 -1
- package/plugins/devcrew-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/devcrew-codex/.mcp.json +1 -1
- package/scripts/smoke-codex-plugin.mjs +1 -1
- package/docs/superpowers/plans/2026-07-10-p0-foundation-repair.md +0 -939
- package/docs/superpowers/plans/2026-07-13-safety-semantics.md +0 -313
- package/docs/superpowers/plans/2026-07-14-p0-remediation.md +0 -213
- package/docs/superpowers/plans/2026-07-14-reliability-recovery.md +0 -208
- package/docs/superpowers/plans/2026-07-14-structured-role-results.md +0 -231
- package/docs/superpowers/specs/2026-07-10-p0-foundation-repair-design.md +0 -182
- package/docs/superpowers/specs/2026-07-13-execution-boundaries-design.md +0 -126
- package/docs/superpowers/specs/2026-07-14-p0-remediation-design.md +0 -52
- package/docs/superpowers/specs/2026-07-14-reliability-recovery-design.md +0 -92
- package/docs/superpowers/specs/2026-07-14-structured-role-results-design.md +0 -96
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
# Configuration Integrity and Run Recovery Implementation Plan
|
|
2
|
-
|
|
3
|
-
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
-
|
|
5
|
-
**Goal:** Reject unsafe configuration, prevent concurrent MCP mutations from overwriting one another, and make interrupted runs explicitly abortable and recoverable.
|
|
6
|
-
|
|
7
|
-
**Architecture:** A strict version-1 parser validates `.devcrew/config.json` and keeps artifact paths inside the requester repository. A repository-wide atomic directory lock wraps MCP mutations while read-only calls remain available. Aborting is a persisted terminal state that preserves audit data; recovery only clears a confirmed stale lock and retries cleanup of a terminal run's residual worktree.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** TypeScript, Node.js `fs/promises`, Node test runner, Git worktrees, MCP tool registry.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### Task 1: Validate configuration and artifact paths
|
|
14
|
-
|
|
15
|
-
**Files:**
|
|
16
|
-
- Modify: `packages/core/src/config.ts`
|
|
17
|
-
- Modify: `tests/core.test.ts`
|
|
18
|
-
|
|
19
|
-
- [ ] **Step 1: Write failing configuration tests**
|
|
20
|
-
|
|
21
|
-
Add table-driven tests that write `.devcrew/config.json`, then call
|
|
22
|
-
`startWorkflow`. Cover an unknown top-level key, an unknown workflow key, an
|
|
23
|
-
unknown gate, a duplicate gate, an empty command, an absolute
|
|
24
|
-
`artifactDirectory`, and `../outside`. Each test asserts the error identifies
|
|
25
|
-
the invalid field. Add a valid custom artifact directory assertion so the
|
|
26
|
-
existing supported path remains accepted.
|
|
27
|
-
|
|
28
|
-
- [ ] **Step 2: Verify RED**
|
|
29
|
-
|
|
30
|
-
Run:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
node --import tsx --test tests/core.test.ts
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Expected: new invalid-config cases fail because `readConfig` currently merges
|
|
37
|
-
untyped JSON and `artifactDirectory` is only joined to `cwd`.
|
|
38
|
-
|
|
39
|
-
- [ ] **Step 3: Implement a strict version-1 parser**
|
|
40
|
-
|
|
41
|
-
In `config.ts`, parse JSON as `unknown`, require plain objects, reject keys
|
|
42
|
-
outside the documented schema, validate enum values from exported type
|
|
43
|
-
constants, and validate arrays as non-empty trimmed strings with no invalid
|
|
44
|
-
gate entries or duplicates. Resolve `workflow.artifactDirectory` against
|
|
45
|
-
`cwd`; reject absolute values and any resolved path whose relative path leaves
|
|
46
|
-
the repository. Return the normalized validated `DevCrewConfig`.
|
|
47
|
-
|
|
48
|
-
- [ ] **Step 4: Verify GREEN and commit**
|
|
49
|
-
|
|
50
|
-
Run:
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
node --import tsx --test tests/core.test.ts
|
|
54
|
-
git add packages/core/src/config.ts tests/core.test.ts
|
|
55
|
-
git commit -m "fix: validate DevCrew configuration strictly"
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Expected: all core tests pass and invalid configuration fails before a run is
|
|
59
|
-
created.
|
|
60
|
-
|
|
61
|
-
### Task 2: Add explicit repository mutation locks
|
|
62
|
-
|
|
63
|
-
**Files:**
|
|
64
|
-
- Create: `packages/core/src/lock.ts`
|
|
65
|
-
- Modify: `packages/core/src/paths.ts`
|
|
66
|
-
- Modify: `packages/core/src/index.ts`
|
|
67
|
-
- Modify: `packages/service/src/tools.ts`
|
|
68
|
-
- Modify: `tests/core.test.ts`
|
|
69
|
-
- Modify: `tests/service.test.ts`
|
|
70
|
-
|
|
71
|
-
- [ ] **Step 1: Write failing lock tests**
|
|
72
|
-
|
|
73
|
-
Add core tests that hold a repository lock while a second acquisition rejects
|
|
74
|
-
with a busy error, then release the first lock and acquire again. Create a
|
|
75
|
-
lock directory with metadata containing a non-running pid and assert normal
|
|
76
|
-
acquisition still refuses it while explicit stale-lock recovery removes it.
|
|
77
|
-
Add a service test that holds the lock, verifies `devcrew_status` still works,
|
|
78
|
-
and verifies a mutating `devcrew_approve` returns a structured busy error.
|
|
79
|
-
|
|
80
|
-
- [ ] **Step 2: Verify RED**
|
|
81
|
-
|
|
82
|
-
Run:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
node --import tsx --test tests/core.test.ts tests/service.test.ts
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Expected: imports fail because no repository lock API exists and MCP calls do
|
|
89
|
-
not serialize mutations.
|
|
90
|
-
|
|
91
|
-
- [ ] **Step 3: Implement lock primitives**
|
|
92
|
-
|
|
93
|
-
Add `repositoryLockPath`, then implement `withRepositoryLock(cwd, action)`
|
|
94
|
-
using atomic `mkdir`. Store `{ ownerId, pid, createdAt }` in `lock.json`,
|
|
95
|
-
remove only the held owner directory in `finally`, and reject existing locks
|
|
96
|
-
without waiting. Implement `recoverRepositoryLock(cwd)` to remove only a
|
|
97
|
-
missing/invalid/dead-local-process lock; it must reject a live owner and must
|
|
98
|
-
never run automatically.
|
|
99
|
-
|
|
100
|
-
- [ ] **Step 4: Wrap MCP mutation dispatch**
|
|
101
|
-
|
|
102
|
-
In `callDevCrewTool`, route start, answer, approve, reject, continue,
|
|
103
|
-
complete-execution, waive-verification, abort, and recovery cleanup through a
|
|
104
|
-
single lock wrapper. Resolve an omitted run id inside the lock. Keep status and
|
|
105
|
-
artifact calls unlocked. Ensure start creates its run and sets `active-run`
|
|
106
|
-
under one lock.
|
|
107
|
-
|
|
108
|
-
- [ ] **Step 5: Verify GREEN and commit**
|
|
109
|
-
|
|
110
|
-
Run:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
node --import tsx --test tests/core.test.ts tests/service.test.ts
|
|
114
|
-
git add packages/core/src/lock.ts packages/core/src/paths.ts packages/core/src/index.ts packages/service/src/tools.ts tests/core.test.ts tests/service.test.ts
|
|
115
|
-
git commit -m "fix: serialize DevCrew MCP mutations"
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Expected: concurrent writes return a structured busy error and reads remain
|
|
119
|
-
available.
|
|
120
|
-
|
|
121
|
-
### Task 3: Persist terminal aborts and recover residual worktrees
|
|
122
|
-
|
|
123
|
-
**Files:**
|
|
124
|
-
- Modify: `packages/core/src/types.ts`
|
|
125
|
-
- Modify: `packages/core/src/active-run.ts`
|
|
126
|
-
- Modify: `packages/core/src/workflow.ts`
|
|
127
|
-
- Modify: `packages/orchestrator/src/index.ts`
|
|
128
|
-
- Modify: `packages/service/src/tools.ts`
|
|
129
|
-
- Modify: `docs/workflow.md`
|
|
130
|
-
- Modify: `tests/core.test.ts`
|
|
131
|
-
- Modify: `tests/orchestrator.test.ts`
|
|
132
|
-
- Modify: `tests/service.test.ts`
|
|
133
|
-
|
|
134
|
-
- [ ] **Step 1: Write failing abort and recovery tests**
|
|
135
|
-
|
|
136
|
-
Add a workflow test that aborts a nonterminal state with a reason, asserts
|
|
137
|
-
`status: "aborted"`, persisted reason/timestamp, and that continue/answer/
|
|
138
|
-
complete cannot resume it. Add an apply-worktree test that aborts after
|
|
139
|
-
execution, confirms the requester checkout is unchanged and the isolated
|
|
140
|
-
worktree is removed. Add a service test that `devcrew_abort` clears its active
|
|
141
|
-
run and that a repeated abort is idempotent. Add a recovery test for an
|
|
142
|
-
aborted state retaining a workspace reference: recovery cleans that worktree
|
|
143
|
-
and clears the reference without running a role.
|
|
144
|
-
|
|
145
|
-
- [ ] **Step 2: Verify RED**
|
|
146
|
-
|
|
147
|
-
Run:
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
node --import tsx --test tests/core.test.ts tests/orchestrator.test.ts tests/service.test.ts
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Expected: tests fail because `aborted` is not a run status and no abort or
|
|
154
|
-
recovery tool exists.
|
|
155
|
-
|
|
156
|
-
- [ ] **Step 3: Implement terminal abort state**
|
|
157
|
-
|
|
158
|
-
Add `RunAbort` plus `RunStatus: "aborted"`; persist the first non-empty abort
|
|
159
|
-
reason and timestamp. Add `abortWorkflow` with terminal idempotency, and make
|
|
160
|
-
continuation return aborted runs unchanged. Add
|
|
161
|
-
`clearActiveRunIfMatches(cwd, runId)` so an abort never clears another run's
|
|
162
|
-
active pointer.
|
|
163
|
-
|
|
164
|
-
- [ ] **Step 4: Implement orchestration and MCP lifecycle tools**
|
|
165
|
-
|
|
166
|
-
Add `abortOrchestratedWorkflow` to persist abort audit state before attempting
|
|
167
|
-
worktree cleanup. On cleanup success clear `executionWorkspace`; on failure
|
|
168
|
-
leave it for recovery. Add `recoverOrchestratedWorkflow` that accepts only
|
|
169
|
-
terminal runs and retries this cleanup. Register `devcrew_abort` and
|
|
170
|
-
`devcrew_recover`, with schemas and structured errors, and apply the lock
|
|
171
|
-
rules from Task 2. Update `docs/workflow.md` with abort/recover semantics.
|
|
172
|
-
|
|
173
|
-
- [ ] **Step 5: Verify GREEN and commit**
|
|
174
|
-
|
|
175
|
-
Run:
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
node --import tsx --test tests/core.test.ts tests/orchestrator.test.ts tests/service.test.ts
|
|
179
|
-
git add packages/core/src/types.ts packages/core/src/active-run.ts packages/core/src/workflow.ts packages/orchestrator/src/index.ts packages/service/src/tools.ts docs/workflow.md tests/core.test.ts tests/orchestrator.test.ts tests/service.test.ts
|
|
180
|
-
git commit -m "feat: add DevCrew abort and recovery controls"
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Expected: aborted runs retain audit evidence, cannot resume, clean their
|
|
184
|
-
worktrees when possible, and can explicitly retry residual cleanup.
|
|
185
|
-
|
|
186
|
-
### Task 4: Full verification
|
|
187
|
-
|
|
188
|
-
**Files:**
|
|
189
|
-
- Verify: all modified files
|
|
190
|
-
|
|
191
|
-
- [ ] **Step 1: Run repository validation**
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
npm run validate
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
Expected: TypeScript build succeeds and every test passes.
|
|
198
|
-
|
|
199
|
-
- [ ] **Step 2: Inspect final state**
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
git diff main...HEAD --check
|
|
203
|
-
git status --short
|
|
204
|
-
git log --oneline main..HEAD
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Expected: no whitespace errors, clean worktree, and only the design, plan,
|
|
208
|
-
and implementation commits on the branch.
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# Structured Role Results Implementation Plan
|
|
2
|
-
|
|
3
|
-
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
-
|
|
5
|
-
**Goal:** Accept validated, versioned role-result envelopes while preserving Markdown-only SDK outputs and expose structured evidence through run state, artifacts, and MCP.
|
|
6
|
-
|
|
7
|
-
**Architecture:** The core package owns envelope types and state migration. The adapter recognizes one explicitly marked JSON block, validates role-specific data, and returns Markdown with the protocol block removed. The orchestrator uses the normalized result without changing gates; artifacts render a human-readable appendix, and MCP continues returning the persisted state.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** TypeScript strict mode, Node.js built-in test runner, `tsx`.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### Task 1: Define normalized envelope types and old-state migration
|
|
14
|
-
|
|
15
|
-
**Files:**
|
|
16
|
-
- Modify: `packages/core/src/types.ts:91-100`
|
|
17
|
-
- Modify: `packages/core/src/store.ts:24-70`
|
|
18
|
-
- Test: `tests/core.test.ts`
|
|
19
|
-
|
|
20
|
-
- [ ] **Step 1: Write the failing migration test**
|
|
21
|
-
|
|
22
|
-
Append this test to `tests/core.test.ts`:
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
test("loadState marks pre-envelope role results as legacy", async () => {
|
|
26
|
-
const cwd = await tempProject();
|
|
27
|
-
const started = await startWorkflow({ cwd, host: "codex", mode: "feature", request: "Migrate roles" });
|
|
28
|
-
const path = runDir(cwd, started.runId);
|
|
29
|
-
const raw = JSON.parse(await readFile(join(path, "state.json"), "utf8")) as Record<string, unknown>;
|
|
30
|
-
raw.roles = [{ role: "pm", backend: "codex", summary: "old", markdown: "# Old", usedFallback: false }];
|
|
31
|
-
await writeFile(join(path, "state.json"), JSON.stringify(raw));
|
|
32
|
-
|
|
33
|
-
const role = (await loadState(cwd, started.runId)).roles[0] as unknown as { format?: string };
|
|
34
|
-
assert.equal(role.format, "legacy");
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
- [ ] **Step 2: Verify it fails**
|
|
39
|
-
|
|
40
|
-
Run: `npm test -- --test-name-pattern="pre-envelope role"`
|
|
41
|
-
|
|
42
|
-
Expected: FAIL because `RoleResult.format` does not exist.
|
|
43
|
-
|
|
44
|
-
- [ ] **Step 3: Add the smallest normalized types and migration**
|
|
45
|
-
|
|
46
|
-
Add these exports in `packages/core/src/types.ts` and make `format` mandatory on `RoleResult`:
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
export interface CommandEvidence {
|
|
50
|
-
command: string;
|
|
51
|
-
exitCode: number;
|
|
52
|
-
output?: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface RoleQuestion {
|
|
56
|
-
id: string;
|
|
57
|
-
prompt: string;
|
|
58
|
-
context?: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface StructuredRoleData {
|
|
62
|
-
schemaVersion: 1;
|
|
63
|
-
role: Exclude<RoleResult["role"], "conductor">;
|
|
64
|
-
summary: string;
|
|
65
|
-
risks: string[];
|
|
66
|
-
evidence: CommandEvidence[];
|
|
67
|
-
questions?: RoleQuestion[];
|
|
68
|
-
decisions?: string[];
|
|
69
|
-
reviewDecision?: ArchitectureReviewDecision;
|
|
70
|
-
changedFiles?: string[];
|
|
71
|
-
testCases?: Array<{ id: string; scenario: string; type: "happy" | "edge" | "failure" | "regression"; expected: string }>;
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
In `loadState`, map each persisted role missing a valid `format` to `{ ...role, format: "legacy" }`, leaving all prior persisted fields intact.
|
|
76
|
-
|
|
77
|
-
- [ ] **Step 4: Verify it passes**
|
|
78
|
-
|
|
79
|
-
Run: `npm test -- --test-name-pattern="pre-envelope role"`
|
|
80
|
-
|
|
81
|
-
Expected: PASS.
|
|
82
|
-
|
|
83
|
-
- [ ] **Step 5: Commit**
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
git add packages/core/src/types.ts packages/core/src/store.ts tests/core.test.ts
|
|
87
|
-
git commit -m "feat: normalize persisted role results"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Task 2: Parse and validate the marked envelope in adapters
|
|
91
|
-
|
|
92
|
-
**Files:**
|
|
93
|
-
- Modify: `packages/adapters/src/index.ts:69-102,143-162,424-459`
|
|
94
|
-
- Test: `tests/adapters.test.ts`
|
|
95
|
-
|
|
96
|
-
- [ ] **Step 1: Write failing parser tests**
|
|
97
|
-
|
|
98
|
-
Export `parseRoleResultOutput` and add tests that call it with this valid PM output and each invalid variation:
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
const output = `<!-- devcrew-role-result -->
|
|
102
|
-
\`\`\`json
|
|
103
|
-
{"schemaVersion":1,"role":"pm","summary":"Need scope","risks":[],"evidence":[],"questions":[{"id":"format","prompt":"Which formats?"}]}
|
|
104
|
-
\`\`\`
|
|
105
|
-
# Requirements
|
|
106
|
-
|
|
107
|
-
## Functional Scope
|
|
108
|
-
`;
|
|
109
|
-
const result = parseRoleResultOutput("pm", "requirements", output);
|
|
110
|
-
assert.equal(result.format, "structured");
|
|
111
|
-
assert.deepEqual(result.questions, ["Which formats?"]);
|
|
112
|
-
assert.doesNotMatch(result.markdown, /devcrew-role-result/);
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Add separate `assert.throws` tests for malformed marked JSON, two marked blocks, `schemaVersion: 2`, role mismatch, duplicate/blank PM question IDs, and a non-integer command exit code. Add a Markdown-only test proving `format === "legacy"` and existing PM/review parsing remain unchanged.
|
|
116
|
-
|
|
117
|
-
- [ ] **Step 2: Verify they fail**
|
|
118
|
-
|
|
119
|
-
Run: `npm test -- --test-name-pattern="role result output"`
|
|
120
|
-
|
|
121
|
-
Expected: FAIL because `parseRoleResultOutput` is not exported.
|
|
122
|
-
|
|
123
|
-
- [ ] **Step 3: Implement the protocol parser and prompt contract**
|
|
124
|
-
|
|
125
|
-
Implement a parser that finds exactly one `<!-- devcrew-role-result -->` followed by a `json` fenced block. When no marker exists, return the original Markdown and `format: "legacy"`; when a marker exists, reject malformed or invalid data. Require all common fields, role-matching field sets, unique PM question IDs, nonempty strings, and integer command exit codes. Return the Markdown with only the marked block removed.
|
|
126
|
-
|
|
127
|
-
Add this exact prompt guidance before `Required Sections`:
|
|
128
|
-
|
|
129
|
-
```ts
|
|
130
|
-
"Return this protocol block first:",
|
|
131
|
-
"<!-- devcrew-role-result -->",
|
|
132
|
-
"```json",
|
|
133
|
-
"{\"schemaVersion\":1,\"role\":\"<current role>\",\"summary\":\"...\",\"risks\":[],\"evidence\":[]}",
|
|
134
|
-
"```",
|
|
135
|
-
"Then return the required Markdown H2 sections. Do not include a second marked result block.",
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Replace direct Markdown extraction in `runRole` with the parser's normalized result. For legacy output, keep `extractOpenQuestions` and `extractArchitectureReviewDecision`; for structured output, derive those compatibility fields from validated structured data.
|
|
139
|
-
|
|
140
|
-
- [ ] **Step 4: Verify adapter tests pass**
|
|
141
|
-
|
|
142
|
-
Run: `npm test -- tests/adapters.test.ts`
|
|
143
|
-
|
|
144
|
-
Expected: PASS.
|
|
145
|
-
|
|
146
|
-
- [ ] **Step 5: Commit**
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
git add packages/adapters/src/index.ts tests/adapters.test.ts
|
|
150
|
-
git commit -m "feat: parse structured role result envelopes"
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Task 3: Persist and render structured implementation and test evidence
|
|
154
|
-
|
|
155
|
-
**Files:**
|
|
156
|
-
- Modify: `packages/orchestrator/src/index.ts:317-344,456-481`
|
|
157
|
-
- Test: `tests/orchestrator.test.ts`
|
|
158
|
-
|
|
159
|
-
- [ ] **Step 1: Write failing workflow tests**
|
|
160
|
-
|
|
161
|
-
Add a structured PM runner result with a question and assert `awaiting_input`. Add an implementation result with `format: "structured"` and `structured.changedFiles` plus command evidence, then assert the persisted role retains them and `implementation-review.md` contains `## Structured Role Result` and the command/exit code. Add an analogous tester assertion for `test-report.md` risks and evidence.
|
|
162
|
-
|
|
163
|
-
- [ ] **Step 2: Verify they fail**
|
|
164
|
-
|
|
165
|
-
Run: `npm test -- --test-name-pattern="structured (PM|implementation|tester)"`
|
|
166
|
-
|
|
167
|
-
Expected: FAIL because artifacts do not render structured role data.
|
|
168
|
-
|
|
169
|
-
- [ ] **Step 3: Render the structured appendix without changing workflow evidence sources**
|
|
170
|
-
|
|
171
|
-
Add an orchestrator artifact helper used by `appendExecutionSections` that renders `state.roles.at(-1)?.structured` only when `format === "structured"`. It must show schema version, summary, changed files, command evidence, test cases, risks, and questions when present, escaping no data and preserving the role's Markdown body as the primary artifact.
|
|
172
|
-
|
|
173
|
-
Keep the existing captured Git diff and configured verification as authoritative promotion evidence. Structured implementation `changedFiles` and tester commands are supplemental role assertions, not a way to overwrite `state.changedFiles`, `state.implementationDiff`, or `state.verification`.
|
|
174
|
-
|
|
175
|
-
In the orchestrator, use structured PM question prompts for `pendingQuestions` and structured review decisions for `architectureReview`; preserve the existing compatibility fields so legacy runners and callers continue to work.
|
|
176
|
-
|
|
177
|
-
- [ ] **Step 4: Verify workflow tests pass**
|
|
178
|
-
|
|
179
|
-
Run: `npm test -- tests/orchestrator.test.ts`
|
|
180
|
-
|
|
181
|
-
Expected: PASS.
|
|
182
|
-
|
|
183
|
-
- [ ] **Step 5: Commit**
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
git add packages/orchestrator/src/index.ts tests/orchestrator.test.ts
|
|
187
|
-
git commit -m "feat: render structured role evidence"
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Task 4: Surface format and results through MCP and complete regression checks
|
|
191
|
-
|
|
192
|
-
**Files:**
|
|
193
|
-
- Modify: `packages/service/src/tools.ts:215-320`
|
|
194
|
-
- Test: `tests/service.test.ts`
|
|
195
|
-
- Modify: `docs/codex.md`
|
|
196
|
-
- Modify: `docs/claude-code.md`
|
|
197
|
-
|
|
198
|
-
- [ ] **Step 1: Write the failing MCP test**
|
|
199
|
-
|
|
200
|
-
Start a workflow with a structured PM runner, invoke `devcrew_status`, and assert its text includes `role_format=structured` plus `structuredContent.state.roles.at(-1).structured.questions[0].id === "format"`. The test must use `callDevCrewTool`, not inspect the state file directly.
|
|
201
|
-
|
|
202
|
-
- [ ] **Step 2: Verify it fails**
|
|
203
|
-
|
|
204
|
-
Run: `npm test -- --test-name-pattern="MCP.*structured role"`
|
|
205
|
-
|
|
206
|
-
Expected: FAIL until the state summary exposes the normalized role format.
|
|
207
|
-
|
|
208
|
-
- [ ] **Step 3: Keep MCP state safe and document the migration**
|
|
209
|
-
|
|
210
|
-
Return the existing state object unchanged except for its newly persisted normalized role fields; do not create a second incompatible tool response shape. Extend `summarizeState` with `role_format=<legacy|structured|none>`.
|
|
211
|
-
|
|
212
|
-
Document the marker, schema version, legacy fallback rule, and the rule that malformed marked output is rejected rather than downgraded in both host guides.
|
|
213
|
-
|
|
214
|
-
- [ ] **Step 4: Verify the focused service test passes**
|
|
215
|
-
|
|
216
|
-
Run: `npm test -- tests/service.test.ts`
|
|
217
|
-
|
|
218
|
-
Expected: PASS.
|
|
219
|
-
|
|
220
|
-
- [ ] **Step 5: Run complete validation and inspect the patch**
|
|
221
|
-
|
|
222
|
-
Run: `npm run validate && npm test && git diff main...HEAD --check`
|
|
223
|
-
|
|
224
|
-
Expected: validation and all tests pass; whitespace check prints no output.
|
|
225
|
-
|
|
226
|
-
- [ ] **Step 6: Commit**
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
git add packages/service/src/tools.ts tests/service.test.ts docs/codex.md docs/claude-code.md
|
|
230
|
-
git commit -m "docs: describe structured role result migration"
|
|
231
|
-
```
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
# DevCrew P0 Foundation Repair Design
|
|
2
|
-
|
|
3
|
-
## Objective
|
|
4
|
-
|
|
5
|
-
Repair the P0 workflow and execution-safety defects identified in the 0.1.1 review without expanding into the P1 role-model, semantic architecture review, or configurable workflow work.
|
|
6
|
-
|
|
7
|
-
The repaired workflow must guarantee that requester approval happens before code changes, apply-mode changes remain isolated until final approval, malformed MCP input cannot poison the server, gate mutations are valid and idempotent, local fallback cannot impersonate apply execution, and the checked-in plugin cannot drift from the package version.
|
|
8
|
-
|
|
9
|
-
## Scope
|
|
10
|
-
|
|
11
|
-
This design includes:
|
|
12
|
-
|
|
13
|
-
- Move real implementation after the existing `implementation` gate.
|
|
14
|
-
- Execute apply-mode implementation and verification in a run-owned Git worktree.
|
|
15
|
-
- Capture committed, staged, unstaged, renamed, deleted, binary, and new-file changes as one reviewable patch.
|
|
16
|
-
- Apply the reviewed patch to the requester's repository only after the `testing` gate is approved.
|
|
17
|
-
- Keep rejected testing work isolated and allow the implementer to revise it.
|
|
18
|
-
- Enforce legal, idempotent `approve`, `reject`, and `answer` transitions.
|
|
19
|
-
- Validate JSON-RPC request shape and recover the stdio queue after handler failures.
|
|
20
|
-
- Reject `executionMode=apply` with the `local` backend.
|
|
21
|
-
- Synchronize package, generated plugin, checked-in plugin, and MCP runtime versions.
|
|
22
|
-
|
|
23
|
-
This design does not include:
|
|
24
|
-
|
|
25
|
-
- Real architect-driven semantic diff review.
|
|
26
|
-
- Structured PM questions and machine-readable role verdicts.
|
|
27
|
-
- Host-native role/subagent integration.
|
|
28
|
-
- Configurable gates or artifact directories.
|
|
29
|
-
- Claude marketplace packaging or smoke coverage.
|
|
30
|
-
- Cross-process run locking or HTTP transport.
|
|
31
|
-
|
|
32
|
-
## Workflow Model
|
|
33
|
-
|
|
34
|
-
The public gate names remain unchanged for MCP compatibility:
|
|
35
|
-
|
|
36
|
-
1. `requirements`
|
|
37
|
-
2. `architecture`
|
|
38
|
-
3. `implementation`
|
|
39
|
-
4. `testing`
|
|
40
|
-
|
|
41
|
-
The internal phase sequence becomes:
|
|
42
|
-
|
|
43
|
-
```text
|
|
44
|
-
requirements
|
|
45
|
-
-> architecture
|
|
46
|
-
-> implementation
|
|
47
|
-
-> execution (apply only)
|
|
48
|
-
-> testing
|
|
49
|
-
-> acceptance
|
|
50
|
-
-> complete
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The existing `implementation` phase becomes plan-only in both execution modes. The implementer receives a read-only role prompt and writes `implementation-plan.md`. Approving the `implementation` gate advances plan mode directly to `testing`, while apply mode advances to the new nongated `execution` phase.
|
|
54
|
-
|
|
55
|
-
The `execution` phase runs the implementer in an isolated worktree, writes `implementation-review.md`, and advances to `testing` with status `ready`. The next `continue` runs the tester and verification commands in the same worktree, then opens the `testing` gate.
|
|
56
|
-
|
|
57
|
-
Approving the `testing` gate applies the captured patch to the original repository, removes the worktree, and advances to acceptance. Rejecting the testing gate leaves the worktree isolated. The rejection feedback can be answered, after which the run returns to `execution` so the implementer can revise the existing isolated changes.
|
|
58
|
-
|
|
59
|
-
## Apply Isolation
|
|
60
|
-
|
|
61
|
-
### Workspace creation
|
|
62
|
-
|
|
63
|
-
Before the first execution attempt DevCrew must:
|
|
64
|
-
|
|
65
|
-
1. Confirm the requester repository is a Git repository with a clean working tree, excluding DevCrew runtime and artifact paths.
|
|
66
|
-
2. Record the current `HEAD` as `baseCommit`.
|
|
67
|
-
3. Create a detached worktree under `.devcrew/worktrees/<run-id>`.
|
|
68
|
-
4. Persist the worktree path and base commit before invoking the SDK role.
|
|
69
|
-
|
|
70
|
-
All implementation, lint, test, and coverage commands run with the worktree as their working directory. Artifacts and state remain in the original repository.
|
|
71
|
-
|
|
72
|
-
### Capturing all changes
|
|
73
|
-
|
|
74
|
-
After the implementer returns DevCrew must normalize any commits created by the role back into worktree changes relative to `baseCommit`. This is safe because the worktree is owned by the run and has not been promoted.
|
|
75
|
-
|
|
76
|
-
DevCrew then marks untracked files as intent-to-add inside the worktree and captures:
|
|
77
|
-
|
|
78
|
-
- `git status --porcelain=v1 -z -uall` for changed paths.
|
|
79
|
-
- `git diff --binary --no-ext-diff <baseCommit> --` for the complete patch.
|
|
80
|
-
|
|
81
|
-
Using the base commit includes staged and unstaged changes. Intent-to-add makes new files visible in the patch. NUL-delimited status parsing avoids filename quoting and rename parsing bugs.
|
|
82
|
-
|
|
83
|
-
### Promotion
|
|
84
|
-
|
|
85
|
-
Before applying an approved patch DevCrew must re-check that the requester repository is clean and still points at `baseCommit`. If either condition changed, approval fails without deleting the worktree or mutating the requester repository.
|
|
86
|
-
|
|
87
|
-
Promotion writes the captured patch under the run directory, applies it to the requester repository with `git apply --binary`, verifies the resulting requester diff matches the reviewed patch, and then removes the worktree. The promoted files remain uncommitted so the requester retains normal review and commit control.
|
|
88
|
-
|
|
89
|
-
An empty apply patch is an error. Apply mode must never report successful implementation when no repository change was produced.
|
|
90
|
-
|
|
91
|
-
## State Changes
|
|
92
|
-
|
|
93
|
-
`RunState` gains optional execution workspace metadata:
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
interface ExecutionWorkspace {
|
|
97
|
-
path: string;
|
|
98
|
-
baseCommit: string;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
The `execution` phase is added to `PHASES`. Older state files without execution workspace metadata continue to load.
|
|
103
|
-
|
|
104
|
-
Gate mutations use these rules:
|
|
105
|
-
|
|
106
|
-
- Approving an already approved gate returns the unchanged state and does not append another approval.
|
|
107
|
-
- Rejecting an already rejected gate returns the unchanged state and does not append duplicate feedback.
|
|
108
|
-
- A pending gate can only be approved or rejected when it is the current phase gate and status is `awaiting_approval`.
|
|
109
|
-
- `answer` is only legal while status is `awaiting_input` and the current gate is rejected.
|
|
110
|
-
- Calls against `acceptance` or `complete` cannot move the run backwards.
|
|
111
|
-
|
|
112
|
-
The service uses a new orchestrated approval entry point so testing approval can promote the patch before the core state advances.
|
|
113
|
-
|
|
114
|
-
## Backend Rules
|
|
115
|
-
|
|
116
|
-
After host/config backend resolution, workflow creation rejects this combination:
|
|
117
|
-
|
|
118
|
-
```text
|
|
119
|
-
executionMode=apply, backend=local
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Plan mode keeps deterministic local fallback. Apply mode requires a real Codex or Claude SDK backend at every role phase.
|
|
123
|
-
|
|
124
|
-
The implementation-plan role is forced to read-only behavior even when the run execution mode is apply. Only the new execution phase and apply-mode tester receive write/Bash capabilities.
|
|
125
|
-
|
|
126
|
-
## Stdio Reliability
|
|
127
|
-
|
|
128
|
-
The line processor validates that parsed JSON is a non-array object with `jsonrpc: "2.0"` and a string `method`. Invalid request objects receive JSON-RPC error `-32600` with `id: null` and do not enter the request queue.
|
|
129
|
-
|
|
130
|
-
For queued requests, each returned task may reject to its caller, but the internal queue stores a recovered promise. One handler failure therefore cannot prevent later requests from executing.
|
|
131
|
-
|
|
132
|
-
Existing parse error behavior remains `-32700`. Notifications without an ID remain response-free.
|
|
133
|
-
|
|
134
|
-
## Version Discipline
|
|
135
|
-
|
|
136
|
-
The next implementation version is `0.1.2`. The following must agree:
|
|
137
|
-
|
|
138
|
-
- `package.json`
|
|
139
|
-
- `package-lock.json`
|
|
140
|
-
- `DEVCREW_VERSION`
|
|
141
|
-
- generated Codex and Claude manifests
|
|
142
|
-
- checked-in Codex manifest
|
|
143
|
-
- checked-in Codex MCP npm package specifier
|
|
144
|
-
- smoke client metadata and version assertions
|
|
145
|
-
|
|
146
|
-
CI adds a checked-in plugin drift test that generates a fresh Codex plugin in a temporary directory and compares all generated text files with the checked-in bundle. Binary assets are checked by hash. Publication order is npm `0.1.2` first, then marketplace push, so the public plugin never references an unavailable npm version.
|
|
147
|
-
|
|
148
|
-
## Error Handling
|
|
149
|
-
|
|
150
|
-
- Worktree creation failure leaves the run in `execution/ready` with no role result recorded.
|
|
151
|
-
- SDK failure leaves the isolated worktree available for diagnosis and retry.
|
|
152
|
-
- Empty implementation patch fails before testing.
|
|
153
|
-
- Verification failures remain visible in the testing artifact; automatic test verdict blocking remains P1.
|
|
154
|
-
- Promotion precondition failure leaves the worktree and state intact for manual resolution.
|
|
155
|
-
- Worktree cleanup runs only after successful promotion or explicit run rejection cleanup added in a later lifecycle feature.
|
|
156
|
-
|
|
157
|
-
## Testing Strategy
|
|
158
|
-
|
|
159
|
-
Tests are added before implementation and must demonstrate the original failures:
|
|
160
|
-
|
|
161
|
-
- Implementation-plan approval occurs before the first writable role invocation.
|
|
162
|
-
- Local apply start is rejected.
|
|
163
|
-
- An implementer-created commit is converted into a complete reviewed patch.
|
|
164
|
-
- Staged, unstaged, renamed, deleted, binary, and untracked files appear in review evidence.
|
|
165
|
-
- Rejecting testing keeps changes outside the requester repository and supports revision.
|
|
166
|
-
- Approving testing promotes exactly the reviewed patch.
|
|
167
|
-
- Changed requester `HEAD` or dirty requester worktree blocks promotion.
|
|
168
|
-
- Empty apply output fails.
|
|
169
|
-
- Duplicate approvals/rejections are idempotent.
|
|
170
|
-
- Complete runs cannot be reopened.
|
|
171
|
-
- Answer outside `awaiting_input` fails.
|
|
172
|
-
- JSON `null`, arrays, missing methods, and wrong JSON-RPC versions return `-32600`.
|
|
173
|
-
- A rejected request handler does not block the next stdio request.
|
|
174
|
-
- Checked-in plugin version and generated bundle match `DEVCREW_VERSION`.
|
|
175
|
-
|
|
176
|
-
The final verification command remains `npm run validate`, followed by the isolated Codex marketplace smoke after `@shenlee/devcrew@0.1.2` is published.
|
|
177
|
-
|
|
178
|
-
## Compatibility
|
|
179
|
-
|
|
180
|
-
MCP tool names and gate names remain stable. Existing plan-mode callers continue using the same approve/continue sequence. Apply-mode sequencing gains one additional `continue` call for the execution phase before testing.
|
|
181
|
-
|
|
182
|
-
Existing 0.1.1 run files remain loadable. Runs already in the old `implementation` phase are treated as implementation planning and cannot write code until their implementation gate is approved under the new state transition.
|