@cyning/harness 1.0.1 → 1.0.2
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 +7 -0
- package/lib/cli.js +8 -5
- package/lib/verify.js +58 -9
- package/ontology.yaml +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/lib/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ import { auditTarget } from './audit.js';
|
|
|
14
14
|
import { mergePackageScripts } from './package-scripts.js';
|
|
15
15
|
|
|
16
16
|
function usage() {
|
|
17
|
-
console.log(`@cyning/harness · cyning-harness CLI (v1.0.
|
|
17
|
+
console.log(`@cyning/harness · cyning-harness CLI (v1.0.2)
|
|
18
18
|
|
|
19
19
|
用法:
|
|
20
20
|
npx @cyning/harness --version | -V
|
|
@@ -348,7 +348,11 @@ async function cmdVerify(args) {
|
|
|
348
348
|
// D3 · implemented in lib/verify.js
|
|
349
349
|
const { verifyTarget } = await import('./verify.js');
|
|
350
350
|
if (args.includes('--help') || args.includes('-h')) {
|
|
351
|
-
console.log(`用法: npx @cyning/harness verify [--target PATH] [--task FILE] [--graph]
|
|
351
|
+
console.log(`用法: npx @cyning/harness verify [--target PATH] [--task FILE] [--graph]
|
|
352
|
+
|
|
353
|
+
无 --task 时:扫描 docs/tasks/active/task_*.md 并逐项列出闸表(同 gate-check)。
|
|
354
|
+
任一 task 阻塞则 VERIFY: BLOCKED · exit 2;全部可 30 则 VERIFY: PASS。
|
|
355
|
+
`);
|
|
352
356
|
return;
|
|
353
357
|
}
|
|
354
358
|
|
|
@@ -380,9 +384,8 @@ async function cmdVerify(args) {
|
|
|
380
384
|
console.log(summary);
|
|
381
385
|
|
|
382
386
|
if (!result.ok) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
throw err;
|
|
387
|
+
process.exitCode = result.exitCode ?? 2;
|
|
388
|
+
return;
|
|
386
389
|
}
|
|
387
390
|
}
|
|
388
391
|
|
package/lib/verify.js
CHANGED
|
@@ -77,19 +77,68 @@ function runGateCheck(target, taskFile, graph, harnessRoot) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function extractBlockReason(stdout) {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
function extractBlockReason(stdout, taskFile) {
|
|
81
|
+
const taskBasename = taskFile ? path.basename(taskFile) : undefined;
|
|
82
|
+
const sections = splitGateCheckTaskSections(stdout);
|
|
83
|
+
|
|
84
|
+
if (taskBasename) {
|
|
85
|
+
const section = sections.get(taskBasename) ?? stdout;
|
|
86
|
+
const arrows = extractArrowBlockLines(section);
|
|
87
|
+
if (arrows.length > 0) return arrows[0];
|
|
88
|
+
return 'gate-check blocked';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const blocked = [];
|
|
92
|
+
for (const [name, section] of sections) {
|
|
93
|
+
const arrows = extractArrowBlockLines(section);
|
|
94
|
+
if (arrows.length > 0) {
|
|
95
|
+
blocked.push({ name, reason: arrows[0] });
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
|
|
99
|
+
if (blocked.length === 0) return 'gate-check blocked';
|
|
100
|
+
|
|
101
|
+
const total = sections.size;
|
|
102
|
+
if (blocked.length === 1) {
|
|
103
|
+
const { name, reason } = blocked[0];
|
|
104
|
+
return total === 1 ? reason : `${name} · ${reason}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const names = blocked.map((b) => b.name).join(', ');
|
|
108
|
+
return `${blocked.length}/${total} tasks blocked · ${names}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** 按 gate-check 输出的 `task: xxx.md` 切段 */
|
|
112
|
+
function splitGateCheckTaskSections(stdout) {
|
|
113
|
+
const map = new Map();
|
|
114
|
+
let current = null;
|
|
115
|
+
const lines = [];
|
|
116
|
+
|
|
117
|
+
const flush = () => {
|
|
118
|
+
if (current) map.set(current, lines.join('\n'));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
for (const line of stdout.split('\n')) {
|
|
122
|
+
const match = line.match(/^task: (.+\.md)\s*$/);
|
|
123
|
+
if (match) {
|
|
124
|
+
flush();
|
|
125
|
+
current = match[1];
|
|
126
|
+
lines.length = 0;
|
|
127
|
+
lines.push(line);
|
|
128
|
+
} else if (current) {
|
|
129
|
+
lines.push(line);
|
|
90
130
|
}
|
|
91
131
|
}
|
|
92
|
-
|
|
132
|
+
flush();
|
|
133
|
+
return map;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** 只认 gate-check 的 `→ 30 不可开工` 行,避免误匹配表格里的 `❌ 拒 30` */
|
|
137
|
+
function extractArrowBlockLines(section) {
|
|
138
|
+
return section
|
|
139
|
+
.split('\n')
|
|
140
|
+
.filter((line) => line.trimStart().startsWith('→ 30 不可开工'))
|
|
141
|
+
.map((line) => line.trim().replace(/^→\s*/, ''));
|
|
93
142
|
}
|
|
94
143
|
|
|
95
144
|
function runGitCleanCheck(target) {
|
package/ontology.yaml
CHANGED