@namewta/speculo 0.7.3 → 0.7.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 +2 -2
- package/dist/src/migrations.js +190 -39
- package/dist/src/migrations.js.map +1 -1
- package/package.json +1 -1
- package/template/canonical/README.md +208 -63
- package/template/canonical/canonical-person-steelman-deliberation.md +518 -0
- package/template/canonical/canonical-specdev-engineering-cognitive-mentor.md +51 -15
- package/template/canonical/canonical-specdev-goal-plan.md +183 -116
- package/template/canonical/canonical-specdev-grill-with-docs.md +51 -15
- package/template/canonical/canonical-specdev-spec.md +61 -21
- package/template/canonical/canonical-specdev-tickets.md +83 -43
- package/template/canonical/canonical-specdev-wayfinder.md +51 -15
- package/template/skills/engineering-standards-builder/README.md +43 -0
- package/template/skills/engineering-standards-builder/SKILL.md +233 -0
- package/template/skills/engineering-standards-builder/examples/README.md +15 -0
- package/template/skills/engineering-standards-builder/examples/fallback/kotlin-gradle/build.gradle.kts +5 -0
- package/template/skills/engineering-standards-builder/examples/fallback/kotlin-gradle/expected.json +12 -0
- package/template/skills/engineering-standards-builder/examples/fallback/kotlin-gradle/src/main/kotlin/example/App.kt +2 -0
- package/template/skills/engineering-standards-builder/examples/go/service/.golangci.yml +3 -0
- package/template/skills/engineering-standards-builder/examples/go/service/cmd/api/main.go +3 -0
- package/template/skills/engineering-standards-builder/examples/go/service/expected.json +23 -0
- package/template/skills/engineering-standards-builder/examples/go/service/go.mod +3 -0
- package/template/skills/engineering-standards-builder/examples/go/service/internal/service/service.go +2 -0
- package/template/skills/engineering-standards-builder/examples/go/service/internal/service/service_test.go +3 -0
- package/template/skills/engineering-standards-builder/examples/java/spring-boot-maven/expected.json +22 -0
- package/template/skills/engineering-standards-builder/examples/java/spring-boot-maven/pom.xml +12 -0
- package/template/skills/engineering-standards-builder/examples/java/spring-boot-maven/src/main/java/dev/speculo/orders/OrdersApplication.java +7 -0
- package/template/skills/engineering-standards-builder/examples/java/spring-boot-maven/src/test/java/dev/speculo/orders/OrdersApplicationTest.java +3 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/.github/workflows/ci.yml +11 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/apps/web/package.json +11 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/apps/web/src/App.vue +2 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/apps/web/tsconfig.json +8 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/expected.json +22 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/package.json +11 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/pnpm-workspace.yaml +2 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/services/orders/pom.xml +12 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/services/orders/src/main/java/dev/speculo/orders/OrdersApplication.java +7 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/services/worker/go.mod +3 -0
- package/template/skills/engineering-standards-builder/examples/polyglot/monorepo/services/worker/main.go +2 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/Cargo.toml +7 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/crates/cli/Cargo.toml +8 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/crates/cli/src/main.rs +1 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/crates/core/Cargo.toml +5 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/crates/core/src/lib.rs +3 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/expected.json +14 -0
- package/template/skills/engineering-standards-builder/examples/rust/workspace/rust-toolchain.toml +3 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/expected.json +21 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/package.json +20 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/src/App.test.tsx +2 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/src/App.tsx +1 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/src/main.tsx +3 -0
- package/template/skills/engineering-standards-builder/examples/typescript/react-vite/tsconfig.json +10 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/expected.json +22 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/package.json +21 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/src/App.test.ts +2 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/src/App.vue +7 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/src/main.ts +4 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/tsconfig.json +11 -0
- package/template/skills/engineering-standards-builder/examples/typescript/vue-vite/vite.config.ts +2 -0
- package/template/skills/engineering-standards-builder/manifest.txt +112 -0
- package/template/skills/engineering-standards-builder/references/go/00-detection-and-scope.md +37 -0
- package/template/skills/engineering-standards-builder/references/go/01-language-and-idioms.md +34 -0
- package/template/skills/engineering-standards-builder/references/go/02-modules-packages-and-layout.md +34 -0
- package/template/skills/engineering-standards-builder/references/go/03-errors-context-and-concurrency.md +38 -0
- package/template/skills/engineering-standards-builder/references/go/04-testing-tooling-quality-gates.md +46 -0
- package/template/skills/engineering-standards-builder/references/go/README.md +9 -0
- package/template/skills/engineering-standards-builder/references/java/00-detection-and-scope.md +40 -0
- package/template/skills/engineering-standards-builder/references/java/01-language-packages-and-api.md +35 -0
- package/template/skills/engineering-standards-builder/references/java/02-build-modules-and-dependencies.md +39 -0
- package/template/skills/engineering-standards-builder/references/java/03-errors-nullability-resources-concurrency.md +36 -0
- package/template/skills/engineering-standards-builder/references/java/04-testing-tooling-quality-gates.md +36 -0
- package/template/skills/engineering-standards-builder/references/java/README.md +10 -0
- package/template/skills/engineering-standards-builder/references/java/frameworks/spring-boot.md +74 -0
- package/template/skills/engineering-standards-builder/references/rules/00-governance-and-precedence.md +52 -0
- package/template/skills/engineering-standards-builder/references/rules/01-project-discovery.md +79 -0
- package/template/skills/engineering-standards-builder/references/rules/02-evidence-topology-and-scope.md +87 -0
- package/template/skills/engineering-standards-builder/references/rules/03-interview-and-decisions.md +77 -0
- package/template/skills/engineering-standards-builder/references/rules/04-architecture-and-dependency-boundaries.md +58 -0
- package/template/skills/engineering-standards-builder/references/rules/05-files-directories-and-naming.md +53 -0
- package/template/skills/engineering-standards-builder/references/rules/06-apis-errors-resources-and-concurrency.md +53 -0
- package/template/skills/engineering-standards-builder/references/rules/07-documentation-and-comments.md +46 -0
- package/template/skills/engineering-standards-builder/references/rules/08-testing-strategy.md +45 -0
- package/template/skills/engineering-standards-builder/references/rules/09-security-configuration-and-data.md +44 -0
- package/template/skills/engineering-standards-builder/references/rules/10-performance-observability-and-i18n.md +36 -0
- package/template/skills/engineering-standards-builder/references/rules/11-tooling-quality-gates-and-ci.md +69 -0
- package/template/skills/engineering-standards-builder/references/rules/12-git-review-and-delivery.md +46 -0
- package/template/skills/engineering-standards-builder/references/rules/13-adoption-exceptions-and-ratchets.md +60 -0
- package/template/skills/engineering-standards-builder/references/rules/14-generation-contract.md +105 -0
- package/template/skills/engineering-standards-builder/references/rules/15-validation-contract.md +65 -0
- package/template/skills/engineering-standards-builder/references/rules/16-language-adapter-contract.md +55 -0
- package/template/skills/engineering-standards-builder/references/rules/README.md +23 -0
- package/template/skills/engineering-standards-builder/references/rust/00-detection-and-scope.md +38 -0
- package/template/skills/engineering-standards-builder/references/rust/01-language-api-and-safety.md +35 -0
- package/template/skills/engineering-standards-builder/references/rust/02-crates-workspaces-and-layout.md +36 -0
- package/template/skills/engineering-standards-builder/references/rust/03-errors-ownership-and-concurrency.md +37 -0
- package/template/skills/engineering-standards-builder/references/rust/04-testing-tooling-quality-gates.md +44 -0
- package/template/skills/engineering-standards-builder/references/rust/README.md +9 -0
- package/template/skills/engineering-standards-builder/references/typescript/00-detection-and-scope.md +58 -0
- package/template/skills/engineering-standards-builder/references/typescript/01-language-and-type-system.md +49 -0
- package/template/skills/engineering-standards-builder/references/typescript/02-modules-packages-and-runtime-boundaries.md +49 -0
- package/template/skills/engineering-standards-builder/references/typescript/03-functions-async-errors-resources.md +42 -0
- package/template/skills/engineering-standards-builder/references/typescript/04-testing-tooling-quality-gates.md +51 -0
- package/template/skills/engineering-standards-builder/references/typescript/README.md +27 -0
- package/template/skills/engineering-standards-builder/references/typescript/app-types/cli.md +11 -0
- package/template/skills/engineering-standards-builder/references/typescript/app-types/library.md +11 -0
- package/template/skills/engineering-standards-builder/references/typescript/frameworks/react.md +71 -0
- package/template/skills/engineering-standards-builder/references/typescript/frameworks/vue.md +131 -0
- package/template/skills/engineering-standards-builder/references/typescript/runtimes/browser.md +15 -0
- package/template/skills/engineering-standards-builder/references/typescript/runtimes/electron.md +25 -0
- package/template/skills/engineering-standards-builder/references/typescript/runtimes/node.md +13 -0
- package/template/skills/engineering-standards-builder/scripts/discover-project.mjs +957 -0
- package/template/skills/engineering-standards-builder/scripts/self-test.mjs +203 -0
- package/template/skills/engineering-standards-builder/scripts/sync-manifest.mjs +105 -0
- package/template/skills/engineering-standards-builder/scripts/validate-builder.mjs +255 -0
- package/template/skills/engineering-standards-builder/scripts/validate-generated-skill.mjs +286 -0
- package/template/skills/engineering-standards-builder/templates/README.md +18 -0
- package/template/skills/engineering-standards-builder/templates/compatibility/agents-typescript--standards.md +6 -0
- package/template/skills/engineering-standards-builder/templates/compatibility/agents-typescript-standards.md +6 -0
- package/template/skills/engineering-standards-builder/templates/compatibility/claude-engineering-standards.md +6 -0
- package/template/skills/engineering-standards-builder/templates/compatibility/claude-typescript-standards.md +6 -0
- package/template/skills/engineering-standards-builder/templates/project-skill/SKILL.md.template +26 -0
- package/template/skills/engineering-standards-builder/templates/project-skill/references/project/00-project-profile.md.template +26 -0
- package/template/skills/engineering-standards-builder/templates/project-skill/references/project/01-module-map.md.template +27 -0
- package/template/skills/engineering-standards-builder/templates/project-skill/references/project/02-decisions-and-exceptions.md.template +31 -0
- package/template/skills/engineering-standards-builder/templates/project-skill/references/project/review-checklist.md.template +14 -0
- package/template/skills/migrate-runtime-state/references/migration-contract.md +3 -3
- package/template/skills/migrate-runtime-state/scripts/migrate-runtime-state.mjs +94 -12
- package/template/skills/source-code-zip-skill/SKILL.md +343 -0
- package/template/skills/source-code-zip-skill/scripts/zip_source_code.py +638 -0
- package/template/workflows/person/INDEX.md +1 -0
- package/template/workflows/person/S-steelman-deliberation/S-steelman-deliberation.md +218 -0
- package/template/workflows/person/S-steelman-deliberation/_templates/decision-template.md +51 -0
- package/template/workflows/person/S-steelman-deliberation/_templates/steelman-dossier-template.md +96 -0
- package/template/workflows/person/S-steelman-deliberation/deliberate.md +127 -0
- package/template/workflows/person/S-steelman-deliberation/evidence-gate.md +37 -0
- package/template/workflows/person/S-steelman-deliberation/judge.md +69 -0
- package/template/workflows/person/S-steelman-deliberation/tools/validate-steelman-change.mjs +697 -0
- package/template/workflows/specdev/I-implement/I-implement.md +27 -26
- package/template/workflows/specdev/I-implement/evidence-template.md +18 -12
- package/template/workflows/specdev/I-implement/execution-preflight.md +11 -9
- package/template/workflows/specdev/I-init-setup/I-init-setup.md +2 -2
- package/template/workflows/specdev/I-init-setup/change-status-template.json +3 -3
- package/template/workflows/specdev/I-init-setup/config-template.json +5 -2
- package/template/workflows/specdev/INDEX.md +6 -6
- package/template/workflows/specdev/P-goal-plan/P-goal-plan.md +16 -16
- package/template/workflows/specdev/P-goal-plan/completion-control.md +8 -8
- package/template/workflows/specdev/P-goal-plan/goal-plan-template.md +20 -14
- package/template/workflows/specdev/P-goal-plan/lead-orchestration.md +5 -5
- package/template/workflows/specdev/P-goal-plan/orchestration-protocol.md +13 -13
- package/template/workflows/specdev/P-goal-plan/planning-modes.md +27 -15
- package/template/workflows/specdev/P-prototype/ui-prototype.md +1 -1
- package/template/workflows/specdev/T-tickets/T-tickets.md +4 -4
- package/template/workflows/specdev/T-tickets/ticket-readiness.md +3 -3
- package/template/workflows/specdev/T-tickets/ticket-template.md +6 -6
- package/template/workflows/specdev/T-tickets/tickets-map-template.md +2 -2
- package/template/workflows/specdev/common/README.md +1 -1
- package/template/workflows/specdev/common/rules/change-completion.md +2 -2
- package/template/workflows/specdev/common/rules/evidence-and-verification.md +10 -6
- package/template/workflows/specdev/common/rules/path-ownership.md +4 -4
- package/template/workflows/specdev/common/schemas/change-status.schema.json +31 -4
- package/template/workflows/specdev/common/schemas/config.schema.json +12 -6
- package/template/workflows/specdev/common/schemas/goal-plan.schema.json +15 -6
- package/template/workflows/specdev/common/skills/dev-worktree/SKILL.md +3 -3
- package/template/workflows/specdev/common/skills/dev-worktree/references/finalize.md +1 -1
- package/template/workflows/specdev/common/skills/subagent-delivery/SKILL.md +4 -4
- package/template/workflows/specdev/common/skills/subagent-delivery/references/external-web-subagent.md +1 -1
- package/template/workflows/specdev/common/skills/subagent-delivery/references/native-subagent.md +4 -4
- package/template/workflows/specdev/common/tools/README.md +2 -1
- package/template/workflows/specdev/common/tools/validate-specdev.mjs +261 -66
- package/template/skills/typescript-standards-builder/README.md +0 -53
- package/template/skills/typescript-standards-builder/SKILL.md +0 -245
- package/template/skills/typescript-standards-builder/examples/sample-generated-tree.md +0 -30
- package/template/skills/typescript-standards-builder/examples/sample-interview-decisions.md +0 -26
- package/template/skills/typescript-standards-builder/manifest.txt +0 -29
- package/template/skills/typescript-standards-builder/references/00-governance-and-fixed-defaults.md +0 -77
- package/template/skills/typescript-standards-builder/references/01-project-discovery.md +0 -100
- package/template/skills/typescript-standards-builder/references/02-interview-workflow.md +0 -129
- package/template/skills/typescript-standards-builder/references/03-project-architecture-and-directory-layout.md +0 -84
- package/template/skills/typescript-standards-builder/references/04-file-directory-and-symbol-naming.md +0 -92
- package/template/skills/typescript-standards-builder/references/05-modules-imports-exports-and-dependencies.md +0 -63
- package/template/skills/typescript-standards-builder/references/06-typescript-type-system.md +0 -64
- package/template/skills/typescript-standards-builder/references/07-functions-async-errors-and-resources.md +0 -42
- package/template/skills/typescript-standards-builder/references/08-comments-jsdoc-and-documentation.md +0 -51
- package/template/skills/typescript-standards-builder/references/09-testing-strategy.md +0 -58
- package/template/skills/typescript-standards-builder/references/10-react-and-frontend.md +0 -39
- package/template/skills/typescript-standards-builder/references/11-node-cli-and-cross-platform.md +0 -31
- package/template/skills/typescript-standards-builder/references/12-formatting-lint-and-complexity.md +0 -58
- package/template/skills/typescript-standards-builder/references/13-configuration-dependencies-and-ci.md +0 -71
- package/template/skills/typescript-standards-builder/references/14-security-performance-and-i18n.md +0 -32
- package/template/skills/typescript-standards-builder/references/15-git-review-and-delivery.md +0 -28
- package/template/skills/typescript-standards-builder/references/16-adoption-exceptions-and-migration.md +0 -61
- package/template/skills/typescript-standards-builder/references/17-generation-contract.md +0 -104
- package/template/skills/typescript-standards-builder/references/README.md +0 -37
- package/template/skills/typescript-standards-builder/templates/agents-compat-skill/SKILL.md +0 -1
- package/template/skills/typescript-standards-builder/templates/claude-skill/SKILL.md +0 -1
- package/template/skills/typescript-standards-builder/templates/project-skill/SKILL.md.template +0 -34
- package/template/skills/typescript-standards-builder/templates/project-skill/references/00-project-profile.md.template +0 -17
- package/template/skills/typescript-standards-builder/templates/project-skill/references/10-review-checklist.md +0 -23
- package/template/skills/typescript-standards-builder/templates/project-skill/references/11-decisions-and-exceptions.md.template +0 -19
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { readFile, readdir, realpath, stat } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import process from 'node:process';
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const CANONICAL_REL = '.agents/skills/engineering-standards';
|
|
11
|
+
const REQUIRED_PROJECT_REFERENCES = [
|
|
12
|
+
'references/project/00-project-profile.md',
|
|
13
|
+
'references/project/01-module-map.md',
|
|
14
|
+
'references/project/02-decisions-and-exceptions.md',
|
|
15
|
+
'references/project/review-checklist.md',
|
|
16
|
+
];
|
|
17
|
+
const ADAPTERS = new Set(['typescript', 'java', 'go', 'rust']);
|
|
18
|
+
|
|
19
|
+
function usage() {
|
|
20
|
+
return `Usage: node scripts/validate-generated-skill.mjs --root <project-root> [options]\n\n` +
|
|
21
|
+
`Validate .agents/skills/engineering-standards and optional compatibility wrappers.\n\n` +
|
|
22
|
+
`Options:\n` +
|
|
23
|
+
` --root <path> Project root (required)\n` +
|
|
24
|
+
` --inventory <path> Project Inventory JSON below --root; auto-discover when omitted\n` +
|
|
25
|
+
` --strict Require every detected adapter/framework and reject unselected ones\n` +
|
|
26
|
+
` --help Show this help\n`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function parseArgs(argv) {
|
|
30
|
+
const result = { root: null, inventory: null, strict: false };
|
|
31
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
32
|
+
const arg = argv[i];
|
|
33
|
+
if (arg === '--help' || arg === '-h') return { help: true };
|
|
34
|
+
if (arg === '--strict') { result.strict = true; continue; }
|
|
35
|
+
if (arg === '--root' || arg === '--inventory') {
|
|
36
|
+
const value = argv[i + 1];
|
|
37
|
+
if (!value || value.startsWith('--')) throw new Error(`${arg} requires a value`);
|
|
38
|
+
if (arg === '--root') result.root = value;
|
|
39
|
+
else result.inventory = value;
|
|
40
|
+
i += 1; continue;
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
43
|
+
}
|
|
44
|
+
if (!result.root) throw new Error('--root is required');
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function toPosix(value) { return value.split(path.sep).join('/'); }
|
|
49
|
+
function isInside(root, candidate) {
|
|
50
|
+
const rel = path.relative(root, candidate);
|
|
51
|
+
return rel === '' || (!rel.startsWith(`..${path.sep}`) && rel !== '..' && !path.isAbsolute(rel));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseFrontmatter(text) {
|
|
55
|
+
if (!text.startsWith('---\n')) return null;
|
|
56
|
+
const end = text.indexOf('\n---\n', 4);
|
|
57
|
+
if (end < 0) return null;
|
|
58
|
+
const values = {};
|
|
59
|
+
for (const line of text.slice(4, end).split('\n')) {
|
|
60
|
+
const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
61
|
+
if (match) values[match[1]] = match[2].trim().replace(/^['"]|['"]$/g, '');
|
|
62
|
+
}
|
|
63
|
+
return { values, body: text.slice(end + 5) };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function markdownLinks(text) {
|
|
67
|
+
const result = [];
|
|
68
|
+
const pattern = /\[[^\]]*\]\(([^)]+)\)/g;
|
|
69
|
+
let match;
|
|
70
|
+
while ((match = pattern.exec(text)) !== null) result.push(match[1].trim());
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isExternal(link) { return /^(?:[a-z]+:|#|\/\/)/i.test(link); }
|
|
75
|
+
|
|
76
|
+
async function collectTree(rootAbs) {
|
|
77
|
+
const files = [];
|
|
78
|
+
const directories = [];
|
|
79
|
+
async function visit(dir) {
|
|
80
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
81
|
+
directories.push({ abs: dir, entries });
|
|
82
|
+
entries.sort((a, b) => a.name.localeCompare(b.name, 'en'));
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
const abs = path.join(dir, entry.name);
|
|
85
|
+
if (entry.isSymbolicLink()) throw new Error(`symlink is not allowed in generated Skill: ${toPosix(path.relative(rootAbs, abs))}`);
|
|
86
|
+
if (entry.isDirectory()) { await visit(abs); continue; }
|
|
87
|
+
if (entry.isFile()) files.push(abs);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await visit(rootAbs);
|
|
91
|
+
return { files, directories };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function sectionForOffset(text, offset) {
|
|
95
|
+
const headings = [...text.matchAll(/^#{1,3}\s+.+$/gm)].map((match) => ({ index: match.index, text: match[0] }));
|
|
96
|
+
const previous = headings.filter((heading) => heading.index <= offset).at(-1);
|
|
97
|
+
const next = headings.find((heading) => heading.index > offset);
|
|
98
|
+
return {
|
|
99
|
+
title: previous?.text ?? '<document>',
|
|
100
|
+
text: text.slice(previous?.index ?? 0, next?.index ?? text.length),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function loadInventory(args, rootReal) {
|
|
105
|
+
if (args.inventory) {
|
|
106
|
+
const inventoryAbs = path.resolve(rootReal, args.inventory);
|
|
107
|
+
if (!isInside(rootReal, inventoryAbs)) throw new Error(`--inventory escapes --root: ${args.inventory}`);
|
|
108
|
+
return JSON.parse(await readFile(inventoryAbs, 'utf8'));
|
|
109
|
+
}
|
|
110
|
+
const discoverScript = path.join(path.dirname(fileURLToPath(import.meta.url)), 'discover-project.mjs');
|
|
111
|
+
const result = spawnSync(process.execPath, [discoverScript, '--root', rootReal], { encoding: 'utf8', timeout: 60000, maxBuffer: 64 * 1024 * 1024 });
|
|
112
|
+
if (result.status !== 0) throw new Error(`automatic project discovery failed: ${(result.stderr || result.stdout).trim()}`);
|
|
113
|
+
return JSON.parse(result.stdout);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function validateWrapper(projectRoot, wrapperRel, errors) {
|
|
117
|
+
const wrapperRoot = path.join(projectRoot, wrapperRel);
|
|
118
|
+
if (!existsSync(wrapperRoot)) return;
|
|
119
|
+
const info = await stat(wrapperRoot);
|
|
120
|
+
if (!info.isDirectory()) { errors.push(`${wrapperRel} must be a directory`); return; }
|
|
121
|
+
const entries = await readdir(wrapperRoot, { withFileTypes: true });
|
|
122
|
+
const nonSkillEntries = entries.filter((entry) => entry.name !== 'SKILL.md');
|
|
123
|
+
if (nonSkillEntries.length > 0) errors.push(`${wrapperRel} compatibility wrapper must contain only SKILL.md`);
|
|
124
|
+
const skillPath = path.join(wrapperRoot, 'SKILL.md');
|
|
125
|
+
if (!existsSync(skillPath)) { errors.push(`${wrapperRel}/SKILL.md is missing`); return; }
|
|
126
|
+
const text = await readFile(skillPath, 'utf8');
|
|
127
|
+
const fm = parseFrontmatter(text);
|
|
128
|
+
if (!fm) { errors.push(`${wrapperRel}/SKILL.md frontmatter is malformed`); return; }
|
|
129
|
+
const expectedName = path.basename(wrapperRoot);
|
|
130
|
+
if (fm.values.name !== expectedName) errors.push(`${wrapperRel}/SKILL.md name must be ${expectedName}`);
|
|
131
|
+
const bodyLines = fm.body.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
132
|
+
if (bodyLines.length !== 1) errors.push(`${wrapperRel}/SKILL.md body must be exactly one non-empty routing line`);
|
|
133
|
+
if (!fm.body.includes('engineering-standards')) errors.push(`${wrapperRel}/SKILL.md does not route to engineering-standards`);
|
|
134
|
+
if (fm.body.length > 400) errors.push(`${wrapperRel}/SKILL.md contains too much content for a compatibility wrapper`);
|
|
135
|
+
if (/typescript-(?:-)?standards\/SKILL\.md/.test(fm.body) && !/engineering-standards/.test(fm.body)) errors.push(`${wrapperRel}/SKILL.md may form a wrapper loop`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function main() {
|
|
139
|
+
let args;
|
|
140
|
+
try { args = parseArgs(process.argv.slice(2)); }
|
|
141
|
+
catch (error) {
|
|
142
|
+
process.stderr.write(`validate-generated-skill: ${error.message}\n\n${usage()}`);
|
|
143
|
+
process.exitCode = 2; return;
|
|
144
|
+
}
|
|
145
|
+
if (args.help) { process.stdout.write(usage()); return; }
|
|
146
|
+
|
|
147
|
+
const errors = [];
|
|
148
|
+
const warnings = [];
|
|
149
|
+
try {
|
|
150
|
+
const rootReal = await realpath(path.resolve(args.root));
|
|
151
|
+
if (!(await stat(rootReal)).isDirectory()) throw new Error('--root is not a directory');
|
|
152
|
+
const canonicalRoot = path.join(rootReal, CANONICAL_REL);
|
|
153
|
+
if (!existsSync(canonicalRoot)) throw new Error(`${CANONICAL_REL} is missing`);
|
|
154
|
+
const canonicalReal = await realpath(canonicalRoot);
|
|
155
|
+
if (!isInside(rootReal, canonicalReal)) throw new Error(`${CANONICAL_REL} resolves outside project root`);
|
|
156
|
+
const { files, directories } = await collectTree(canonicalReal);
|
|
157
|
+
for (const directory of directories) {
|
|
158
|
+
if (directory.entries.length === 0) errors.push(`empty generated directory: ${toPosix(path.relative(rootReal, directory.abs))}`);
|
|
159
|
+
}
|
|
160
|
+
const fileSet = new Set(files);
|
|
161
|
+
const mainSkill = path.join(canonicalReal, 'SKILL.md');
|
|
162
|
+
if (!fileSet.has(mainSkill)) errors.push(`${CANONICAL_REL}/SKILL.md is missing`);
|
|
163
|
+
else {
|
|
164
|
+
const text = await readFile(mainSkill, 'utf8');
|
|
165
|
+
const fm = parseFrontmatter(text);
|
|
166
|
+
if (!fm) errors.push(`${CANONICAL_REL}/SKILL.md frontmatter is malformed`);
|
|
167
|
+
else {
|
|
168
|
+
if (fm.values.name !== 'engineering-standards') errors.push(`canonical frontmatter name must be engineering-standards, found ${fm.values.name ?? '<missing>'}`);
|
|
169
|
+
if (!fm.values.description) errors.push('canonical frontmatter description is missing');
|
|
170
|
+
}
|
|
171
|
+
if (/typescript-(?:-)?standards\/SKILL\.md/.test(text)) errors.push('canonical Skill must not route back to a compatibility alias');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const required of REQUIRED_PROJECT_REFERENCES) {
|
|
175
|
+
const abs = path.join(canonicalReal, required);
|
|
176
|
+
if (!fileSet.has(abs)) errors.push(`required generated reference is missing: ${required}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const file of files.filter((item) => item.endsWith('.md'))) {
|
|
180
|
+
const rel = toPosix(path.relative(canonicalReal, file));
|
|
181
|
+
const text = await readFile(file, 'utf8');
|
|
182
|
+
if (/\{\{[A-Z0-9_]+\}\}|<PROJECT_NAME>|<REPOSITORY_ROOT>/.test(text)) errors.push(`${rel}: unresolved template placeholder`);
|
|
183
|
+
for (let link of markdownLinks(text)) {
|
|
184
|
+
if (isExternal(link)) continue;
|
|
185
|
+
if (link.startsWith('<') && link.endsWith('>')) link = link.slice(1, -1);
|
|
186
|
+
const targetPart = link.split('#')[0].split('?')[0];
|
|
187
|
+
if (!targetPart) continue;
|
|
188
|
+
const target = path.resolve(path.dirname(file), decodeURIComponent(targetPart));
|
|
189
|
+
if (!isInside(canonicalReal, target)) {
|
|
190
|
+
errors.push(`${rel}: link escapes canonical Skill: ${link}`);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (!existsSync(target)) errors.push(`${rel}: broken local link: ${link}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!rel.startsWith('references/project/')) {
|
|
197
|
+
for (const levelMatch of text.matchAll(/^Level:\s*(MUST|SHOULD)\s*$/gm)) {
|
|
198
|
+
const section = sectionForOffset(text, levelMatch.index);
|
|
199
|
+
for (const field of ['Scope:', 'Source:', 'Rule:', 'Verification:']) {
|
|
200
|
+
if (!section.text.includes(field)) errors.push(`${rel} ${section.title}: ${levelMatch[1]} rule is missing ${field}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const inventory = await loadInventory(args, rootReal);
|
|
207
|
+
const detectedAdapters = new Set(inventory?.summary?.adapters ?? []);
|
|
208
|
+
const generatedReferenceRoot = path.join(canonicalReal, 'references');
|
|
209
|
+
const generatedAdapters = new Set();
|
|
210
|
+
if (existsSync(generatedReferenceRoot)) {
|
|
211
|
+
for (const entry of await readdir(generatedReferenceRoot, { withFileTypes: true })) {
|
|
212
|
+
if (entry.isDirectory() && ADAPTERS.has(entry.name)) generatedAdapters.add(entry.name);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
for (const adapter of generatedAdapters) {
|
|
216
|
+
if (!detectedAdapters.has(adapter)) {
|
|
217
|
+
const message = `generated adapter ${adapter} has no matching Project Inventory signal`;
|
|
218
|
+
if (args.strict) errors.push(message); else warnings.push(message);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const adapter of detectedAdapters) {
|
|
222
|
+
if (!generatedAdapters.has(adapter)) {
|
|
223
|
+
const message = `detected adapter ${adapter} is missing from generated references`;
|
|
224
|
+
if (args.strict) errors.push(message); else warnings.push(message);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const detectedFrameworks = new Set(inventory?.summary?.frameworks ?? []);
|
|
229
|
+
const frameworkContracts = [
|
|
230
|
+
['vue', 'typescript', 'references/typescript/frameworks/vue.md'],
|
|
231
|
+
['react', 'typescript', 'references/typescript/frameworks/react.md'],
|
|
232
|
+
['spring-boot', 'java', 'references/java/frameworks/spring-boot.md'],
|
|
233
|
+
];
|
|
234
|
+
for (const [framework, requiredAdapter, rel] of frameworkContracts) {
|
|
235
|
+
const present = fileSet.has(path.join(canonicalReal, rel));
|
|
236
|
+
const frameworkDetected = detectedFrameworks.has(framework);
|
|
237
|
+
const adapterDetected = detectedAdapters.has(requiredAdapter);
|
|
238
|
+
if (present && (!frameworkDetected || !adapterDetected)) {
|
|
239
|
+
const message = `generated framework rule ${framework} has no matching ${requiredAdapter} adapter and framework signal`;
|
|
240
|
+
if (args.strict) errors.push(message); else warnings.push(message);
|
|
241
|
+
}
|
|
242
|
+
if (!present && frameworkDetected && adapterDetected) {
|
|
243
|
+
const message = `detected framework ${framework} is missing generated rule ${rel}`;
|
|
244
|
+
if (args.strict) errors.push(message); else warnings.push(message);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
for (const wrapper of [
|
|
249
|
+
'.agents/skills/typescript-standards',
|
|
250
|
+
'.agents/skills/typescript--standards',
|
|
251
|
+
'.claude/skills/engineering-standards',
|
|
252
|
+
'.claude/skills/typescript-standards',
|
|
253
|
+
]) await validateWrapper(rootReal, wrapper, errors);
|
|
254
|
+
|
|
255
|
+
// Detect substantial duplicate canonical copies under known agent roots.
|
|
256
|
+
for (const baseRel of ['.agents/skills', '.claude/skills']) {
|
|
257
|
+
const base = path.join(rootReal, baseRel);
|
|
258
|
+
if (!existsSync(base)) continue;
|
|
259
|
+
for (const entry of await readdir(base, { withFileTypes: true })) {
|
|
260
|
+
if (!entry.isDirectory()) continue;
|
|
261
|
+
const candidate = path.join(base, entry.name, 'SKILL.md');
|
|
262
|
+
if (!existsSync(candidate) || candidate === mainSkill) continue;
|
|
263
|
+
const text = await readFile(candidate, 'utf8');
|
|
264
|
+
const fm = parseFrontmatter(text);
|
|
265
|
+
if (fm?.values?.name === 'engineering-standards' && fm.body.trim().length > 400) {
|
|
266
|
+
errors.push(`substantial duplicate engineering-standards content found at ${toPosix(path.relative(rootReal, candidate))}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if ((inventory?.scan?.truncated ?? false) === true) warnings.push('Project Inventory scan was truncated; adapter selection requires manual verification');
|
|
272
|
+
for (const item of inventory?.conflicts ?? []) warnings.push(`Project Inventory conflict: ${item.scope ?? 'repository'} ${item.type}`);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
errors.push(error.stack ?? error.message);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for (const warning of warnings) process.stderr.write(`validate-generated-skill: WARN: ${warning}\n`);
|
|
278
|
+
if (errors.length) {
|
|
279
|
+
for (const error of errors) process.stderr.write(`validate-generated-skill: ERROR: ${error}\n`);
|
|
280
|
+
process.exitCode = 1;
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
process.stdout.write(`validate-generated-skill: OK${warnings.length ? ` (${warnings.length} warning(s))` : ''}\n`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
await main();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 生成模板索引
|
|
2
|
+
|
|
3
|
+
模板只用于生成项目专属 Skill;占位符必须在写入目标前全部替换。
|
|
4
|
+
|
|
5
|
+
## Canonical Skill
|
|
6
|
+
|
|
7
|
+
- [主入口](project-skill/SKILL.md.template)
|
|
8
|
+
- [项目画像](project-skill/references/project/00-project-profile.md.template)
|
|
9
|
+
- [模块地图](project-skill/references/project/01-module-map.md.template)
|
|
10
|
+
- [决策与例外](project-skill/references/project/02-decisions-and-exceptions.md.template)
|
|
11
|
+
- [评审清单](project-skill/references/project/review-checklist.md.template)
|
|
12
|
+
|
|
13
|
+
## 单向兼容入口
|
|
14
|
+
|
|
15
|
+
- [Agents:typescript-standards](compatibility/agents-typescript-standards.md)
|
|
16
|
+
- [Agents:typescript--standards](compatibility/agents-typescript--standards.md)
|
|
17
|
+
- [Claude:engineering-standards](compatibility/claude-engineering-standards.md)
|
|
18
|
+
- [Claude:typescript-standards](compatibility/claude-typescript-standards.md)
|
package/template/skills/engineering-standards-builder/templates/project-skill/SKILL.md.template
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: engineering-standards
|
|
3
|
+
description: 为 {{PROJECT_NAME}} 的实现、重构、评审与交付提供按模块路由的工程规范。处理代码、目录、测试、构建、依赖、API 或 CI 变化前使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# {{PROJECT_NAME}} Engineering Standards
|
|
7
|
+
|
|
8
|
+
本 Skill 只描述本项目已确认的规范。先确定变更 scope,再加载最小充分 references;不要把一个模块的语言或框架规则扩散到其他模块。
|
|
9
|
+
|
|
10
|
+
## 每次执行
|
|
11
|
+
|
|
12
|
+
1. 读取 [项目画像](references/project/00-project-profile.md) 和 [模块地图](references/project/01-module-map.md)。
|
|
13
|
+
2. 将当前任务映射到 repository、module、language、framework、runtime 或 path scope。
|
|
14
|
+
3. 读取与变更相关的通用规则:{{COMMON_RULE_LINKS}}。
|
|
15
|
+
4. 按模块地图只读取适用语言/框架规则:{{ADAPTER_ROUTE_LINKS}}。
|
|
16
|
+
5. 读取 [决策与例外](references/project/02-decisions-and-exceptions.md),确认 current、target、migration 与未到期 exception。
|
|
17
|
+
6. 实现前检查 public API、依赖方向、安全、错误/取消/资源和测试影响。
|
|
18
|
+
7. 实现后运行项目画像中该 scope 的真实质量门禁,并按 [评审清单](references/project/review-checklist.md) 报告结果。
|
|
19
|
+
|
|
20
|
+
## 约束
|
|
21
|
+
|
|
22
|
+
- MUST 规则只有在 Verification 可执行或有精确 review 证据时成立。
|
|
23
|
+
- 不适用规则不加载;generated/vendor/frozen scope 不手工修改。
|
|
24
|
+
- 不通过删除测试、关闭核心规则、放宽编译配置或扩大例外获得通过。
|
|
25
|
+
- 新代码遵循 Target;存量偏差按 Migration/Ratchet 处理。
|
|
26
|
+
- 项目事实变化时更新 Project Profile/Module Map,再更新规则,不静默猜测。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 项目画像
|
|
2
|
+
|
|
3
|
+
## 身份
|
|
4
|
+
|
|
5
|
+
- Project: {{PROJECT_NAME}}
|
|
6
|
+
- Repository root: {{REPOSITORY_ROOT}}
|
|
7
|
+
- Topology: {{TOPOLOGY}}
|
|
8
|
+
- Inventory schema: {{INVENTORY_SCHEMA_VERSION}}
|
|
9
|
+
|
|
10
|
+
## 事实来源
|
|
11
|
+
|
|
12
|
+
{{EVIDENCE_SUMMARY}}
|
|
13
|
+
|
|
14
|
+
## 工具链与质量门禁
|
|
15
|
+
|
|
16
|
+
{{QUALITY_GATES}}
|
|
17
|
+
|
|
18
|
+
每个命令必须包含 scope、working directory、来源和当前状态(active/planned)。
|
|
19
|
+
|
|
20
|
+
## 排除与冻结区域
|
|
21
|
+
|
|
22
|
+
{{EXCLUDED_AND_FROZEN_PATHS}}
|
|
23
|
+
|
|
24
|
+
## 未知与冲突
|
|
25
|
+
|
|
26
|
+
{{UNKNOWNS_AND_CONFLICTS}}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 模块地图
|
|
2
|
+
|
|
3
|
+
{{MODULE_TABLE}}
|
|
4
|
+
|
|
5
|
+
每个模块至少记录:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
id
|
|
9
|
+
path
|
|
10
|
+
languages
|
|
11
|
+
frameworks
|
|
12
|
+
runtimes
|
|
13
|
+
build systems
|
|
14
|
+
source/test roots
|
|
15
|
+
public entrypoints
|
|
16
|
+
generated paths
|
|
17
|
+
quality gates
|
|
18
|
+
evidence/confidence
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 依赖方向
|
|
22
|
+
|
|
23
|
+
{{DEPENDENCY_DIRECTIONS}}
|
|
24
|
+
|
|
25
|
+
## 路由
|
|
26
|
+
|
|
27
|
+
{{MODULE_RULE_ROUTES}}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 决策、迁移与例外
|
|
2
|
+
|
|
3
|
+
## 决策
|
|
4
|
+
|
|
5
|
+
{{DECISIONS}}
|
|
6
|
+
|
|
7
|
+
推荐格式:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Decision ID:
|
|
11
|
+
Scope:
|
|
12
|
+
Decision:
|
|
13
|
+
Source: user-decision | repository-fact | official-guidance | builder-baseline
|
|
14
|
+
Rationale:
|
|
15
|
+
Migration:
|
|
16
|
+
Verification:
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 当前状态与目标状态
|
|
20
|
+
|
|
21
|
+
{{CURRENT_TARGET_MIGRATIONS}}
|
|
22
|
+
|
|
23
|
+
## 例外
|
|
24
|
+
|
|
25
|
+
{{EXCEPTIONS}}
|
|
26
|
+
|
|
27
|
+
每个例外必须包含 ID、Scope、Rule、Owner、Reason、Risk、Compensation、Created、Expires/removal condition 和 Verification。没有 owner 或删除条件的临时例外无效。
|
|
28
|
+
|
|
29
|
+
## 待确认
|
|
30
|
+
|
|
31
|
+
{{PENDING_DECISIONS}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 变更评审清单
|
|
2
|
+
|
|
3
|
+
只检查与当前 scope 和风险相关的条目。
|
|
4
|
+
|
|
5
|
+
- [ ] 变更映射到模块地图中的明确 scope。
|
|
6
|
+
- [ ] 依赖只通过允许的 public contract,未产生循环或深导入。
|
|
7
|
+
- [ ] 外部输入、权限、秘密和敏感数据边界已处理。
|
|
8
|
+
- [ ] 错误、超时、取消、资源和并发生命周期完整。
|
|
9
|
+
- [ ] public API、schema、事件、CLI 或持久化兼容影响已说明。
|
|
10
|
+
- [ ] 测试层级匹配风险,失败与清理路径被覆盖。
|
|
11
|
+
- [ ] generated/vendor/frozen 文件未被无意修改。
|
|
12
|
+
- [ ] 实际运行的 format/lint/compile/test/build 命令及退出码已记录。
|
|
13
|
+
- [ ] 当前状态、目标状态、Ratchet 与例外没有混写。
|
|
14
|
+
- [ ] 文档、迁移、回滚、可观测性和发布影响按需更新。
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
- `active` 从仍位于 `changes/` 且 change 状态为 active/blocked/completed 的真实目录核对;不得创建虚假 change。
|
|
27
27
|
- `archived` 从 `archive/YYYY-MM/<change>/` 核对,active/archived 不得重叠。
|
|
28
28
|
- `config.json` 保留语言、Git、执行、验证与规划偏好,并补入当前 schema 的必需默认值。
|
|
29
|
-
- SpecDev config v3 升级为
|
|
29
|
+
- SpecDev config v3/v4 升级为 v5 时,`execution.max_parallel` 只作为旧并发偏好的输入,保留为正整数的 `execution.max_implementation_agents`;补齐 `max_integration_attempts` 与 planning 原型变体配置。删除旧的自动提交和条件 worktree 开关,不把它们解释为授权。
|
|
30
30
|
- change-status v3 只有在 `worktrees` 缺失或为空时才可确定性升级为 v4;存在旧 worktree 记录时,必须逐 Ticket 重建 implementation owner、source commit、candidate/result、E2E disposition 和父分支包含关系。v4 runtime 不得自动升级为 v5:旧状态无法可靠推断 execution authorization 或 Lead leadership,必须保持 pending 并显式对账。
|
|
31
|
-
- active Goal Plan 不是
|
|
31
|
+
- active Goal Plan 不是 v6 时必须重新规划 Lead、workspace 与 integration gate;不能只改 frontmatter 版本号。
|
|
32
32
|
- 已声明为 v4 的 SpecDev config,以及已声明为 v5 的 global status、change-status 和 Goal Plan,必须完整满足当前 schema:必需字段、类型、枚举、嵌套对象和 `additionalProperties` 边界都通过后才能自动保留。不得为不完整状态静默补默认值,也不得只扫描少量标记字段。
|
|
33
33
|
- worktree `removed` 只接受为 `integrated` 后的清理终态;source checkpoint、passed candidate/result、验证、E2E disposition 和 Evidence 必须完整保留。
|
|
34
34
|
- `.config/`、`adr/`、`context/`、`research/`、`changes/`、`archive/` 和声明的 sidecar 都是持久项。
|
|
@@ -59,6 +59,6 @@
|
|
|
59
59
|
- action 后、删除 staged marker 前、原子替换后都递归拒绝 active runtime 中的 symlink;任何失败均恢复原 active 安装。
|
|
60
60
|
- 所有迁移后 JSON 可解析。
|
|
61
61
|
- workspace、install manifest、项目配置和已安装 workflow 全局状态满足当前版本。
|
|
62
|
-
- SpecDev active/archive 索引与目录一致;SpecDev config 满足
|
|
62
|
+
- SpecDev active/archive 索引与目录一致;SpecDev config 满足 v5 合同,global status 满足 v5 合同,change-status 满足 v6 合同,Goal Plan 满足 v6 合同;person 状态满足 schema v1。
|
|
63
63
|
- pending marker 只在全部验证通过后从 staged 安装删除。
|
|
64
64
|
- 执行后 backup manifest 与内容 hash 不变。
|