@cyning/harness 1.0.2 → 1.1.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/CHANGELOG.md +22 -0
- package/README.md +2 -1
- package/docs/USER_GUIDE_v1.0_zh.md +58 -5
- package/docs/methodology/graph/INFORM_YAML_MIGRATION_v1_zh.md +81 -0
- package/docs/methodology/graph/PROMPT_ontology_inventory_scan_G0_v1_zh.md +313 -0
- package/docs/methodology/graph/README.md +2 -0
- package/docs/methodology/graph/inventory/ONTOLOGY_INVENTORY_ai_ink_brain_api_python_v1.yaml +283 -0
- package/docs/methodology/graph/inventory/ONTOLOGY_INVENTORY_cyning_harness_v1.yaml +233 -0
- package/examples/demo_checkout/00_main.graph.yaml +42 -0
- package/examples/demo_checkout/00_main.md +66 -0
- package/examples/demo_checkout/README.md +3 -0
- package/examples/demo_checkout/graph.json +111 -0
- package/lib/cli.js +146 -3
- package/lib/graph-yaml.js +547 -0
- package/ontology.yaml +1 -1
- package/package.json +4 -1
- package/schema/inform_graph.v3.schema.json +134 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "graph_v2",
|
|
3
|
+
"freeze_id": "TECH_GRAPH_S2_FREEZE_20260519_V2_3",
|
|
4
|
+
"generated_at": "2026-06-17T00:00:00Z",
|
|
5
|
+
"graphs": [
|
|
6
|
+
{
|
|
7
|
+
"id": "00_main",
|
|
8
|
+
"title": "Harness P0 金样流程",
|
|
9
|
+
"source_yaml_path": "00_main.graph.yaml"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"nodes": [
|
|
13
|
+
{
|
|
14
|
+
"graph_id": "00_main",
|
|
15
|
+
"id": "DONE",
|
|
16
|
+
"label": "P0 通过"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"graph_id": "00_main",
|
|
20
|
+
"id": "EXEC",
|
|
21
|
+
"label": "30 执行帽"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"graph_id": "00_main",
|
|
25
|
+
"id": "GATE",
|
|
26
|
+
"label": "gate-check"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"graph_id": "00_main",
|
|
30
|
+
"id": "INIT",
|
|
31
|
+
"label": "harness init"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"graph_id": "00_main",
|
|
35
|
+
"id": "R1",
|
|
36
|
+
"label": "22 审核帽"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"graph_id": "00_main",
|
|
40
|
+
"id": "START",
|
|
41
|
+
"label": "空 Git 仓"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"graph_id": "00_main",
|
|
45
|
+
"id": "TASK",
|
|
46
|
+
"label": "task_demo_p0_golden"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"edges": [
|
|
50
|
+
{
|
|
51
|
+
"anchors": [],
|
|
52
|
+
"from": "EXEC",
|
|
53
|
+
"graph_id": "00_main",
|
|
54
|
+
"label": "40 自检",
|
|
55
|
+
"mark": "->",
|
|
56
|
+
"sync": true,
|
|
57
|
+
"to": "DONE",
|
|
58
|
+
"type": "depends_on"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"anchors": [],
|
|
62
|
+
"from": "GATE",
|
|
63
|
+
"graph_id": "00_main",
|
|
64
|
+
"label": "exit 0",
|
|
65
|
+
"mark": "->",
|
|
66
|
+
"sync": true,
|
|
67
|
+
"to": "EXEC",
|
|
68
|
+
"type": "depends_on"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"anchors": [],
|
|
72
|
+
"from": "INIT",
|
|
73
|
+
"graph_id": "00_main",
|
|
74
|
+
"label": "复制金样 task",
|
|
75
|
+
"mark": "->",
|
|
76
|
+
"sync": true,
|
|
77
|
+
"to": "TASK",
|
|
78
|
+
"type": "depends_on"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"anchors": [],
|
|
82
|
+
"from": "R1",
|
|
83
|
+
"graph_id": "00_main",
|
|
84
|
+
"label": "HG-AUDIT-R1 approved",
|
|
85
|
+
"mark": "->",
|
|
86
|
+
"sync": true,
|
|
87
|
+
"to": "GATE",
|
|
88
|
+
"type": "depends_on"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"anchors": [],
|
|
92
|
+
"from": "START",
|
|
93
|
+
"graph_id": "00_main",
|
|
94
|
+
"label": "install.sh",
|
|
95
|
+
"mark": "->",
|
|
96
|
+
"sync": true,
|
|
97
|
+
"to": "INIT",
|
|
98
|
+
"type": "depends_on"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"anchors": [],
|
|
102
|
+
"from": "TASK",
|
|
103
|
+
"graph_id": "00_main",
|
|
104
|
+
"label": "10 → 22",
|
|
105
|
+
"mark": "->",
|
|
106
|
+
"sync": true,
|
|
107
|
+
"to": "R1",
|
|
108
|
+
"type": "depends_on"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
package/lib/cli.js
CHANGED
|
@@ -12,9 +12,16 @@ import { runBash } from './run.js';
|
|
|
12
12
|
import { checkTaskFile } from './task.js';
|
|
13
13
|
import { auditTarget } from './audit.js';
|
|
14
14
|
import { mergePackageScripts } from './package-scripts.js';
|
|
15
|
+
import {
|
|
16
|
+
allGraphIds,
|
|
17
|
+
checkGraph,
|
|
18
|
+
compileGraph,
|
|
19
|
+
GraphYamlError,
|
|
20
|
+
yamlPathFor,
|
|
21
|
+
} from './graph-yaml.js';
|
|
15
22
|
|
|
16
|
-
function usage() {
|
|
17
|
-
console.log(`@cyning/harness · cyning-harness CLI (
|
|
23
|
+
function usage(version = 'unknown') {
|
|
24
|
+
console.log(`@cyning/harness · cyning-harness CLI (v${version})
|
|
18
25
|
|
|
19
26
|
用法:
|
|
20
27
|
npx @cyning/harness --version | -V
|
|
@@ -27,6 +34,10 @@ function usage() {
|
|
|
27
34
|
npx @cyning/harness verify [--target PATH] [--task FILE] [--graph]
|
|
28
35
|
npx @cyning/harness sync index [--target PATH]
|
|
29
36
|
npx @cyning/harness task check --file PATH [--no-circular] [--registry DIR]...
|
|
37
|
+
npx @cyning/harness graph yaml compile --graph-id ID [--input DIR] [--output FILE]
|
|
38
|
+
npx @cyning/harness graph yaml check --graph-id ID [--input DIR] [--graph-json FILE]
|
|
39
|
+
npx @cyning/harness graph yaml compile --all [--input DIR]
|
|
40
|
+
npx @cyning/harness graph yaml check --all [--input DIR] [--graph-json FILE]
|
|
30
41
|
|
|
31
42
|
说明:
|
|
32
43
|
init 首次接入 · 内部调用 wizard/install.sh + harness-sync.sh apply
|
|
@@ -37,6 +48,7 @@ function usage() {
|
|
|
37
48
|
verify 30 前聚合:gate-check + audit D5 + S5 warn + 可选 --graph
|
|
38
49
|
sync index 生成 .cyning-harness/invoke_index.json
|
|
39
50
|
task check 校验 task.harness.v1.json sidecar · --no-circular 检测 depends_on 环
|
|
51
|
+
graph yaml Inform 图谱 YAML 编译 / 校验(v1.1+)
|
|
40
52
|
|
|
41
53
|
环境:
|
|
42
54
|
CYNING_HARNESS 覆盖产品包根(维护者本地 clone 开发)
|
|
@@ -59,7 +71,7 @@ export async function runCli(argv) {
|
|
|
59
71
|
const pkgVersion = resolvePackageVersion(harnessRoot);
|
|
60
72
|
|
|
61
73
|
if (argv.length === 0 || argv.includes('-h') || argv.includes('--help')) {
|
|
62
|
-
usage();
|
|
74
|
+
usage(pkgVersion);
|
|
63
75
|
return;
|
|
64
76
|
}
|
|
65
77
|
|
|
@@ -102,6 +114,10 @@ export async function runCli(argv) {
|
|
|
102
114
|
await cmdTask(rest);
|
|
103
115
|
return;
|
|
104
116
|
}
|
|
117
|
+
if (cmd === 'graph') {
|
|
118
|
+
await cmdGraph(rest);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
105
121
|
|
|
106
122
|
const err = new Error(`未知命令: ${cmd}\n`);
|
|
107
123
|
err.exitCode = 1;
|
|
@@ -495,3 +511,130 @@ async function cmdTask(args) {
|
|
|
495
511
|
console.log('depends_on: acyclic');
|
|
496
512
|
}
|
|
497
513
|
}
|
|
514
|
+
|
|
515
|
+
async function cmdGraph(args) {
|
|
516
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
517
|
+
console.log(`用法: npx @cyning/harness graph yaml compile|check [选项]
|
|
518
|
+
|
|
519
|
+
子命令:
|
|
520
|
+
graph yaml compile --graph-id ID [--input DIR] [--output FILE]
|
|
521
|
+
graph yaml compile --all [--input DIR]
|
|
522
|
+
graph yaml check --graph-id ID [--input DIR] [--graph-json FILE]
|
|
523
|
+
graph yaml check --all [--input DIR] [--graph-json FILE]
|
|
524
|
+
|
|
525
|
+
选项:
|
|
526
|
+
--input DIR 输入目录(默认 target/docs/_tech_graph)
|
|
527
|
+
--output FILE 输出 MD 路径(仅单图 compile)
|
|
528
|
+
--graph-json FILE 对比的 graph.json 路径(默认 input/graph.json)
|
|
529
|
+
--all 处理目录下所有 *.graph.yaml
|
|
530
|
+
`);
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const [sub, ...subRest] = args;
|
|
535
|
+
if (sub !== 'yaml') {
|
|
536
|
+
const err = new Error(`graph 子命令未知: ${sub ?? '(空)'}`);
|
|
537
|
+
err.exitCode = 1;
|
|
538
|
+
throw err;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const [action, ...actionRest] = subRest;
|
|
542
|
+
if (action !== 'compile' && action !== 'check') {
|
|
543
|
+
const err = new Error(`graph yaml 动作未知: ${action ?? '(空)'}`);
|
|
544
|
+
err.exitCode = 1;
|
|
545
|
+
throw err;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const all = actionRest.includes('--all');
|
|
549
|
+
let rest = actionRest.filter((a) => a !== '--all');
|
|
550
|
+
|
|
551
|
+
const { value: graphId, rest: r1 } = takeOption(rest, '--graph-id');
|
|
552
|
+
rest = r1;
|
|
553
|
+
const { value: inputArg, rest: r2 } = takeOption(rest, '--input');
|
|
554
|
+
rest = r2;
|
|
555
|
+
const { value: outputArg, rest: r3 } = takeOption(rest, '--output');
|
|
556
|
+
rest = r3;
|
|
557
|
+
const { value: graphJsonArg, rest: r4 } = takeOption(rest, '--graph-json');
|
|
558
|
+
rest = r4;
|
|
559
|
+
|
|
560
|
+
if (rest.length > 0) {
|
|
561
|
+
const err = new Error(`graph yaml ${action} 未知参数: ${rest.join(' ')}`);
|
|
562
|
+
err.exitCode = 1;
|
|
563
|
+
throw err;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (!all && !graphId) {
|
|
567
|
+
const err = new Error('须指定 --graph-id ID 或 --all');
|
|
568
|
+
err.exitCode = 1;
|
|
569
|
+
throw err;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const cwd = process.cwd();
|
|
573
|
+
const inputRoot = inputArg ? path.resolve(cwd, inputArg) : path.resolve(cwd, 'docs', '_tech_graph');
|
|
574
|
+
const graphJsonPath = graphJsonArg
|
|
575
|
+
? path.resolve(cwd, graphJsonArg)
|
|
576
|
+
: path.join(inputRoot, 'graph.json');
|
|
577
|
+
|
|
578
|
+
try {
|
|
579
|
+
if (action === 'compile') {
|
|
580
|
+
if (all) {
|
|
581
|
+
const ids = allGraphIds(inputRoot);
|
|
582
|
+
if (ids.length === 0) {
|
|
583
|
+
console.log('未找到 *.graph.yaml');
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
for (const id of ids) {
|
|
587
|
+
const out = compileGraph(id, inputRoot);
|
|
588
|
+
console.log(`Generated: ${out}`);
|
|
589
|
+
}
|
|
590
|
+
} else {
|
|
591
|
+
const out = compileGraph(graphId, inputRoot, outputArg ? path.resolve(cwd, outputArg) : null);
|
|
592
|
+
console.log(`Generated: ${out}`);
|
|
593
|
+
}
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// action === 'check'
|
|
598
|
+
if (all) {
|
|
599
|
+
const ids = allGraphIds(inputRoot);
|
|
600
|
+
if (ids.length === 0) {
|
|
601
|
+
console.log('未找到 *.graph.yaml');
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
let failed = false;
|
|
605
|
+
for (const id of ids) {
|
|
606
|
+
const result = checkGraph(id, inputRoot, graphJsonPath);
|
|
607
|
+
if (result.ok) {
|
|
608
|
+
console.log(`OK: ${id}`);
|
|
609
|
+
} else {
|
|
610
|
+
failed = true;
|
|
611
|
+
console.error(`ERROR: ${id}\n${result.diff}`);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (failed) {
|
|
615
|
+
const err = new Error('graph yaml check 发现差异');
|
|
616
|
+
err.exitCode = 1;
|
|
617
|
+
throw err;
|
|
618
|
+
}
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const result = checkGraph(graphId, inputRoot, graphJsonPath);
|
|
623
|
+
if (result.ok) {
|
|
624
|
+
console.log(`OK: YAML matches graph.json ${graphId} slice`);
|
|
625
|
+
} else {
|
|
626
|
+
console.error(`ERROR: Diff detected for ${graphId}:\n${result.diff}`);
|
|
627
|
+
const err = new Error('graph yaml check 发现差异');
|
|
628
|
+
err.exitCode = 1;
|
|
629
|
+
throw err;
|
|
630
|
+
}
|
|
631
|
+
} catch (err) {
|
|
632
|
+
if (err instanceof GraphYamlError) {
|
|
633
|
+
console.error(err.message);
|
|
634
|
+
const exitErr = new Error('');
|
|
635
|
+
exitErr.exitCode = 1;
|
|
636
|
+
throw exitErr;
|
|
637
|
+
}
|
|
638
|
+
throw err;
|
|
639
|
+
}
|
|
640
|
+
}
|