@xenonbyte/da-vinci-workflow 0.2.3 → 0.2.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/CHANGELOG.md +13 -0
- package/README.md +32 -7
- package/README.zh-CN.md +151 -7
- package/commands/claude/dv/build.md +5 -0
- package/commands/claude/dv/continue.md +4 -0
- package/commands/claude/dv/tasks.md +6 -0
- package/commands/claude/dv/verify.md +2 -0
- package/commands/codex/prompts/dv-build.md +5 -0
- package/commands/codex/prompts/dv-continue.md +4 -0
- package/commands/codex/prompts/dv-tasks.md +6 -0
- package/commands/codex/prompts/dv-verify.md +2 -0
- package/commands/gemini/dv/build.toml +5 -0
- package/commands/gemini/dv/continue.toml +4 -0
- package/commands/gemini/dv/tasks.toml +6 -0
- package/commands/gemini/dv/verify.toml +2 -0
- package/commands/templates/dv-continue.shared.md +4 -0
- package/docs/discipline-and-orchestration-upgrade.md +83 -0
- package/docs/dv-command-reference.md +18 -2
- package/docs/execution-chain-migration.md +23 -0
- package/docs/prompt-entrypoints.md +5 -0
- package/docs/skill-usage.md +16 -0
- package/docs/workflow-overview.md +17 -0
- package/docs/zh-CN/dv-command-reference.md +16 -2
- package/docs/zh-CN/execution-chain-migration.md +23 -0
- package/docs/zh-CN/prompt-entrypoints.md +5 -0
- package/docs/zh-CN/skill-usage.md +16 -0
- package/docs/zh-CN/workflow-overview.md +17 -0
- package/lib/audit-parsers.js +148 -1
- package/lib/cli.js +106 -1
- package/lib/execution-profile.js +143 -0
- package/lib/execution-signals.js +19 -1
- package/lib/lint-tasks.js +86 -2
- package/lib/planning-parsers.js +255 -18
- package/lib/supervisor-review.js +2 -1
- package/lib/task-execution.js +160 -0
- package/lib/task-review.js +197 -0
- package/lib/verify.js +152 -1
- package/lib/workflow-state.js +452 -30
- package/lib/worktree-preflight.js +214 -0
- package/package.json +1 -1
- package/references/artifact-templates.md +56 -6
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { spawnSync } = require("child_process");
|
|
4
|
+
const { STATUS } = require("./workflow-contract");
|
|
5
|
+
|
|
6
|
+
function runGit(projectRoot, args) {
|
|
7
|
+
return spawnSync("git", args, {
|
|
8
|
+
cwd: projectRoot,
|
|
9
|
+
encoding: "utf8",
|
|
10
|
+
maxBuffer: 8 * 1024 * 1024
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function checkIgnoredDirectory(projectRoot, directoryPath) {
|
|
15
|
+
const relativePath = path.relative(projectRoot, directoryPath) || path.basename(directoryPath);
|
|
16
|
+
const result = runGit(projectRoot, ["check-ignore", relativePath]);
|
|
17
|
+
if (result.error) {
|
|
18
|
+
return {
|
|
19
|
+
directory: directoryPath,
|
|
20
|
+
relativePath,
|
|
21
|
+
ignored: false,
|
|
22
|
+
error: `failed to execute git check-ignore: ${result.error.message || "unknown error"}`
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (result.status === 0) {
|
|
26
|
+
return {
|
|
27
|
+
directory: directoryPath,
|
|
28
|
+
relativePath,
|
|
29
|
+
ignored: true,
|
|
30
|
+
error: null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (result.status === 1) {
|
|
34
|
+
return {
|
|
35
|
+
directory: directoryPath,
|
|
36
|
+
relativePath,
|
|
37
|
+
ignored: false,
|
|
38
|
+
error: null
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const statusText = Number.isFinite(result.status) ? `exit ${result.status}` : "unknown status";
|
|
42
|
+
const stderr = String(result.stderr || "").trim();
|
|
43
|
+
return {
|
|
44
|
+
directory: directoryPath,
|
|
45
|
+
relativePath,
|
|
46
|
+
ignored: false,
|
|
47
|
+
error: `git check-ignore failed (${statusText})${stderr ? `: ${stderr}` : ""}`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readPackageScripts(projectRoot) {
|
|
52
|
+
const packagePath = path.join(projectRoot, "package.json");
|
|
53
|
+
if (!fs.existsSync(packagePath)) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const payload = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
|
58
|
+
return payload && payload.scripts && typeof payload.scripts === "object" ? payload.scripts : {};
|
|
59
|
+
} catch (_error) {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function runWorktreePreflight(projectPathInput, options = {}) {
|
|
65
|
+
const projectRoot = path.resolve(projectPathInput || process.cwd());
|
|
66
|
+
const findings = {
|
|
67
|
+
failures: [],
|
|
68
|
+
warnings: [],
|
|
69
|
+
notes: []
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const candidateDirs = [".worktrees", "worktrees"]
|
|
73
|
+
.map((name) => path.join(projectRoot, name))
|
|
74
|
+
.filter((candidate) => fs.existsSync(candidate));
|
|
75
|
+
const gitStatus = runGit(projectRoot, ["status", "--porcelain"]);
|
|
76
|
+
const gitStatusSummary = {
|
|
77
|
+
healthy: false,
|
|
78
|
+
exitCode: Number.isFinite(gitStatus.status) ? gitStatus.status : null,
|
|
79
|
+
message: ""
|
|
80
|
+
};
|
|
81
|
+
const dirtyEntries = [];
|
|
82
|
+
if (gitStatus.error) {
|
|
83
|
+
gitStatusSummary.message = `failed to execute git status: ${gitStatus.error.message || "unknown error"}`;
|
|
84
|
+
findings.warnings.push(
|
|
85
|
+
"Unable to execute `git status`; worktree-isolation preflight cannot be trusted in the current environment."
|
|
86
|
+
);
|
|
87
|
+
} else if (gitStatus.status !== 0) {
|
|
88
|
+
const stderr = String(gitStatus.stderr || "").trim();
|
|
89
|
+
gitStatusSummary.message = stderr || "git status returned non-zero exit";
|
|
90
|
+
if (/not a git repository/i.test(stderr)) {
|
|
91
|
+
findings.warnings.push(
|
|
92
|
+
"Current project is not a git repository; worktree-isolation preflight is advisory-only and recommends isolation."
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
findings.warnings.push(
|
|
96
|
+
`git status failed (${gitStatusSummary.exitCode !== null ? gitStatusSummary.exitCode : "unknown exit"}); worktree-isolation checks may be unreliable.`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
gitStatusSummary.healthy = true;
|
|
101
|
+
const lines = String(gitStatus.stdout || "")
|
|
102
|
+
.split(/\r?\n/)
|
|
103
|
+
.map((line) => line.trim())
|
|
104
|
+
.filter(Boolean);
|
|
105
|
+
dirtyEntries.push(...lines);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const ignoreChecks = [];
|
|
109
|
+
if (candidateDirs.length > 0) {
|
|
110
|
+
if (!gitStatusSummary.healthy) {
|
|
111
|
+
findings.warnings.push(
|
|
112
|
+
"Skipped git-ignore safety checks for worktree directories because git status is unavailable."
|
|
113
|
+
);
|
|
114
|
+
} else {
|
|
115
|
+
for (const candidate of candidateDirs) {
|
|
116
|
+
const check = checkIgnoredDirectory(projectRoot, candidate);
|
|
117
|
+
ignoreChecks.push(check);
|
|
118
|
+
if (check.error) {
|
|
119
|
+
findings.warnings.push(
|
|
120
|
+
`Unable to verify git-ignore state for ${check.relativePath}: ${check.error}`
|
|
121
|
+
);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (!check.ignored) {
|
|
125
|
+
findings.failures.push(
|
|
126
|
+
`Worktree directory ${check.relativePath} is not git-ignored; isolation setup is unsafe.`
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
findings.notes.push(`Worktree directory ${check.relativePath} is git-ignored.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (dirtyEntries.length > 0) {
|
|
136
|
+
findings.warnings.push(
|
|
137
|
+
`Workspace is dirty (${dirtyEntries.length} change(s)); isolated execution is recommended before bounded parallel work.`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const scripts = readPackageScripts(projectRoot);
|
|
142
|
+
if (!scripts.test) {
|
|
143
|
+
findings.warnings.push("No `test` script found in package.json; baseline verification heuristics are weak.");
|
|
144
|
+
} else {
|
|
145
|
+
findings.notes.push("Detected package.json test script for baseline verification checks.");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (candidateDirs.length === 0) {
|
|
149
|
+
findings.notes.push("No project-local worktree directory found (.worktrees/ or worktrees/).");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const status =
|
|
153
|
+
findings.failures.length > 0
|
|
154
|
+
? STATUS.BLOCK
|
|
155
|
+
: findings.warnings.length > 0
|
|
156
|
+
? STATUS.WARN
|
|
157
|
+
: STATUS.PASS;
|
|
158
|
+
|
|
159
|
+
const recommendedIsolation =
|
|
160
|
+
dirtyEntries.length > 0 ||
|
|
161
|
+
options.parallelPreferred === true ||
|
|
162
|
+
findings.failures.length > 0 ||
|
|
163
|
+
!gitStatusSummary.healthy;
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
advisory: true,
|
|
168
|
+
projectRoot,
|
|
169
|
+
failures: findings.failures,
|
|
170
|
+
warnings: findings.warnings,
|
|
171
|
+
notes: findings.notes,
|
|
172
|
+
summary: {
|
|
173
|
+
worktreeDirectories: candidateDirs.map((candidate) => path.relative(projectRoot, candidate)),
|
|
174
|
+
ignoreChecks,
|
|
175
|
+
dirtyEntries: dirtyEntries.length,
|
|
176
|
+
gitStatus: gitStatusSummary,
|
|
177
|
+
recommendedIsolation
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function formatWorktreePreflightReport(result) {
|
|
183
|
+
const lines = [
|
|
184
|
+
"Worktree preflight",
|
|
185
|
+
`Project: ${result.projectRoot}`,
|
|
186
|
+
`Status: ${result.status}`,
|
|
187
|
+
`Advisory: ${result.advisory ? "yes" : "no"}`,
|
|
188
|
+
`Recommended isolation: ${result.summary.recommendedIsolation ? "yes" : "no"}`
|
|
189
|
+
];
|
|
190
|
+
if (result.failures.length > 0) {
|
|
191
|
+
lines.push("Failures:");
|
|
192
|
+
for (const failure of result.failures) {
|
|
193
|
+
lines.push(`- ${failure}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (result.warnings.length > 0) {
|
|
197
|
+
lines.push("Warnings:");
|
|
198
|
+
for (const warning of result.warnings) {
|
|
199
|
+
lines.push(`- ${warning}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (result.notes.length > 0) {
|
|
203
|
+
lines.push("Notes:");
|
|
204
|
+
for (const note of result.notes) {
|
|
205
|
+
lines.push(`- ${note}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return lines.join("\n");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
module.exports = {
|
|
212
|
+
runWorktreePreflight,
|
|
213
|
+
formatWorktreePreflightReport
|
|
214
|
+
};
|
package/package.json
CHANGED
|
@@ -662,21 +662,46 @@ Use this structure:
|
|
|
662
662
|
```md
|
|
663
663
|
# Tasks
|
|
664
664
|
|
|
665
|
+
## Discipline Markers (Machine-readable)
|
|
666
|
+
- design_approval: approved @ <ISO-8601 timestamp>
|
|
667
|
+
- plan_self_review: complete @ <ISO-8601 timestamp>
|
|
668
|
+
- operator_review_ack: accepted @ <ISO-8601 timestamp>
|
|
669
|
+
|
|
665
670
|
## 1. Setup
|
|
666
|
-
- [ ] Project or page setup
|
|
671
|
+
- [ ] 1.1 Project or page setup
|
|
672
|
+
- Target files: `<repo path>`
|
|
673
|
+
- Verification command: `<exact command>`
|
|
674
|
+
- Execution intent: `serial`
|
|
675
|
+
- Review intent: `true`
|
|
667
676
|
|
|
668
677
|
## 2. UI Structure
|
|
669
|
-
- [ ] Implement major sections from Pencil
|
|
678
|
+
- [ ] 2.1 Implement major sections from Pencil
|
|
679
|
+
- Target files: `<repo path>`
|
|
680
|
+
- Verification command: `<exact command>`
|
|
681
|
+
- Execution intent: `bounded_parallel`
|
|
682
|
+
- Review intent: `true`
|
|
670
683
|
|
|
671
684
|
## 3. Behavior
|
|
672
|
-
- [ ] Implement states and interactions from spec
|
|
685
|
+
- [ ] 3.1 Implement states and interactions from spec
|
|
686
|
+
- Target files: `<repo path>`
|
|
687
|
+
- Verification command: `<exact command>`
|
|
688
|
+
- Execution intent: `review_required`
|
|
689
|
+
- Review intent: `true`
|
|
673
690
|
|
|
674
691
|
## 4. Integration
|
|
675
|
-
- [ ] Wire required data or services
|
|
692
|
+
- [ ] 4.1 Wire required data or services
|
|
693
|
+
- Target files: `<repo path>`
|
|
694
|
+
- Verification command: `<exact command>`
|
|
695
|
+
- Execution intent: `serial`
|
|
696
|
+
- Review intent: `true`
|
|
676
697
|
|
|
677
698
|
## 5. Verification
|
|
678
|
-
- [ ] Check requirement coverage
|
|
679
|
-
- [ ] Check Pencil coverage
|
|
699
|
+
- [ ] 5.1 Check requirement coverage
|
|
700
|
+
- [ ] 5.2 Check Pencil coverage
|
|
701
|
+
- Verification command: `da-vinci verify-bindings --project <path> [--change <id>]`
|
|
702
|
+
- Verification command: `da-vinci verify-implementation --project <path> [--change <id>]`
|
|
703
|
+
- Verification command: `da-vinci verify-structure --project <path> [--change <id>]`
|
|
704
|
+
- Verification command: `da-vinci verify-coverage --project <path> [--change <id>]`
|
|
680
705
|
|
|
681
706
|
## Metadata Hints (Machine-readable)
|
|
682
707
|
- Spec slice: `<slice-id>`
|
|
@@ -699,8 +724,12 @@ Prefer top-level task groups. They are required for execution checkpoints.
|
|
|
699
724
|
Additional guidance:
|
|
700
725
|
|
|
701
726
|
- keep top-level task groups in `X. Title` form to support task-group execution metadata
|
|
727
|
+
- keep checklist numbering in `X.Y` form and avoid placeholder wording such as `TBD` or `TODO`
|
|
728
|
+
- keep discipline markers parseable and timestamped so stale approvals can be detected
|
|
702
729
|
- include explicit verification actions so `lint-tasks` and `verify-coverage` can consume intent deterministically
|
|
703
730
|
- keep task text concrete enough that coverage tools can map behavior and state work
|
|
731
|
+
- include explicit file targets or code-area references for each task group
|
|
732
|
+
- include execution intent (`serial`, `bounded_parallel`, or `review_required`) and review intent metadata per group
|
|
704
733
|
|
|
705
734
|
Recommended path:
|
|
706
735
|
|
|
@@ -780,6 +809,27 @@ Use this structure:
|
|
|
780
809
|
- explicit test evidence summary
|
|
781
810
|
- open gaps
|
|
782
811
|
|
|
812
|
+
## Task Review Evidence
|
|
813
|
+
### Task Review <task-group-id> (spec)
|
|
814
|
+
- Status: PASS / WARN / BLOCK
|
|
815
|
+
- Reviewer: `<name>`
|
|
816
|
+
- Summary: `<summary>`
|
|
817
|
+
- Issues: `<issue list>`
|
|
818
|
+
- Recorded at: `<ISO-8601 timestamp>`
|
|
819
|
+
|
|
820
|
+
### Task Review <task-group-id> (quality)
|
|
821
|
+
- Status: PASS / WARN / BLOCK
|
|
822
|
+
- Reviewer: `<name>`
|
|
823
|
+
- Summary: `<summary>`
|
|
824
|
+
- Issues: `<issue list>`
|
|
825
|
+
- Recorded at: `<ISO-8601 timestamp>`
|
|
826
|
+
|
|
827
|
+
## Verification Freshness
|
|
828
|
+
- verification baseline timestamp
|
|
829
|
+
- latest verify signal timestamps by surface
|
|
830
|
+
- freshness outcome: `fresh` / `stale`
|
|
831
|
+
- stale reasons when freshness is not satisfied
|
|
832
|
+
|
|
783
833
|
## Context Delta
|
|
784
834
|
- Add concise entries after each `execution checkpoint`
|
|
785
835
|
- Required fields: `time`, `checkpoint_type`, `goal`, `decision`, `constraints`, `impact`, `status`, `next_action`
|