create-yss-spec 3.4.9 → 3.4.10
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/package.json +1 -1
- package/src/template/attach-planner.js +5 -0
- package/src/template/sync-planner.js +5 -0
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.agents/skills/yss-openapi-draft-review/SKILL.md +2 -0
- package/template/.agents/skills/yss-openapi-governance/SKILL.md +4 -0
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +11 -5
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +63 -1
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.agents/skills/yss-prototype-stage/SKILL.md +2 -0
- package/template/.agents/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs +2 -2
- package/template/.agents/skills/yss-stage-decision/SKILL.md +2 -0
- package/template/.agents/skills/yss-tactical-design/SKILL.md +2 -0
- package/template/.agents/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.agents/skills/yss-technical-design/scripts/engineering-design.mjs +1 -1
- package/template/.agents/skills/yss-technical-design/scripts/validate-technical-design.mjs +11 -8
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.codex/skills/yss-openapi-draft-review/SKILL.md +2 -0
- package/template/.codex/skills/yss-openapi-governance/SKILL.md +4 -0
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +11 -5
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +63 -1
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.codex/skills/yss-prototype-stage/SKILL.md +2 -0
- package/template/.codex/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs +2 -2
- package/template/.codex/skills/yss-stage-decision/SKILL.md +2 -0
- package/template/.codex/skills/yss-tactical-design/SKILL.md +2 -0
- package/template/.codex/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.codex/skills/yss-technical-design/scripts/engineering-design.mjs +1 -1
- package/template/.codex/skills/yss-technical-design/scripts/validate-technical-design.mjs +11 -8
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.cursor/skills/yss-openapi-draft-review/SKILL.md +2 -0
- package/template/.cursor/skills/yss-openapi-governance/SKILL.md +4 -0
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +11 -5
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +63 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.cursor/skills/yss-prototype-stage/SKILL.md +2 -0
- package/template/.cursor/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs +2 -2
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +2 -0
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +2 -0
- package/template/.cursor/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.cursor/skills/yss-technical-design/scripts/engineering-design.mjs +1 -1
- package/template/.cursor/skills/yss-technical-design/scripts/validate-technical-design.mjs +11 -8
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.pi/skills/yss-openapi-draft-review/SKILL.md +2 -0
- package/template/.pi/skills/yss-openapi-governance/SKILL.md +4 -0
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +11 -5
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +63 -1
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.pi/skills/yss-prototype-stage/SKILL.md +2 -0
- package/template/.pi/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs +2 -2
- package/template/.pi/skills/yss-stage-decision/SKILL.md +2 -0
- package/template/.pi/skills/yss-tactical-design/SKILL.md +2 -0
- package/template/.pi/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.pi/skills/yss-technical-design/scripts/engineering-design.mjs +1 -1
- package/template/.pi/skills/yss-technical-design/scripts/validate-technical-design.mjs +11 -8
- package/template/AGENTS.md +2 -0
- package/template/CONTEXT.md +2 -1
- package/template/README.md +1 -0
- package/template/docs/agents/issue-tracker.md +7 -0
- package/template/docs/process/contract-reading.md +46 -0
- package/template/docs/process/lifecycle-artifact-map.md +2 -2
- package/template/docs/process/lifecycle-registry-baseline.json +2 -1
- package/template/docs/process/lifecycle-registry.yaml +10 -4
- package/template/docs/process/schemas/api-contract-decision-v2.schema.json +198 -0
- package/template/docs/process/schemas/digital-human-task-package.schema.json +8 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +259 -0
- package/template/docs/process/schemas/stage-tracking.schema.json +259 -0
- package/template/docs/process/stage-tracking.md +62 -0
- package/template/docs/process/strategic-handoff-package.md +8 -0
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +2 -0
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214/347/264/242/345/274/225.md +1 -0
- package/template/docs/user-guide//351/230/266/346/256/265/346/216/245/345/205/245/344/270/216/344/272/247/347/211/251/345/244/215/347/224/250/344/275/277/347/224/250/346/211/213/345/206/214.md +243 -0
- package/template/scripts/api-contract-decision +16 -0
- package/template/scripts/complete-backend-delivery +17 -0
- package/template/scripts/contract +13 -0
- package/template/scripts/dispatch-slice-task +13 -0
- package/template/scripts/lib/api-contract-decision.mjs +45 -4
- package/template/scripts/lib/approval-record.mjs +1 -1
- package/template/scripts/lib/approved-execution-context.mjs +35 -7
- package/template/scripts/lib/backend-architecture.mjs +2 -2
- package/template/scripts/lib/backend-delivery-terminal.mjs +51 -0
- package/template/scripts/lib/backend-platform-provenance.mjs +1 -1
- package/template/scripts/lib/backend-platform.mjs +1 -1
- package/template/scripts/lib/backend-scaffold-prerequisites.mjs +1 -1
- package/template/scripts/lib/context-contract.mjs +1 -1
- package/template/scripts/lib/context-reconciliation.mjs +1 -1
- package/template/scripts/lib/contract-source.mjs +22 -0
- package/template/scripts/lib/contract-views.mjs +109 -0
- package/template/scripts/lib/delivery-preflight.mjs +3 -2
- package/template/scripts/lib/digital-human-roles.mjs +1 -1
- package/template/scripts/lib/existing-backend-architecture.mjs +4 -3
- package/template/scripts/lib/existing-ui-baseline.mjs +4 -2
- package/template/scripts/lib/frontend-delivery-boundary.mjs +1 -1
- package/template/scripts/lib/frontend-delivery.mjs +1 -1
- package/template/scripts/lib/harness-execution-scope.mjs +15 -1
- package/template/scripts/lib/implementation-contract-compiler.mjs +4 -4
- package/template/scripts/lib/json-schema.mjs +19 -4
- package/template/scripts/lib/lifecycle-context-query.mjs +5 -1
- package/template/scripts/lib/lifecycle-controls.mjs +1 -1
- package/template/scripts/lib/lifecycle-execution-scope.mjs +92 -0
- package/template/scripts/lib/lifecycle-registry.mjs +2 -1
- package/template/scripts/lib/lifecycle-transition.mjs +21 -3
- package/template/scripts/lib/openapi-draft-validation.mjs +2 -1
- package/template/scripts/lib/skill-registry.mjs +1 -1
- package/template/scripts/lib/slice-contract-preparation.mjs +16 -14
- package/template/scripts/lib/slice-contract-views.mjs +1 -1
- package/template/scripts/lib/slice-contract.mjs +18 -3
- package/template/scripts/lib/slice-execution-preflight.mjs +7 -3
- package/template/scripts/lib/slice-repositories.mjs +1 -1
- package/template/scripts/lib/slice-task-package.mjs +3 -2
- package/template/scripts/lib/stage-tracking-migration.mjs +176 -0
- package/template/scripts/lib/stage-tracking.mjs +184 -0
- package/template/scripts/lib/strategic-handoff-consumption.mjs +5 -4
- package/template/scripts/lib/strategic-handoff-io.mjs +5 -2
- package/template/scripts/lib/strategic-handoff-routing.mjs +31 -0
- package/template/scripts/lib/strategic-handoff.mjs +4 -2
- package/template/scripts/lib/task-package.mjs +2 -0
- package/template/scripts/lib/technical-design-boundary.mjs +4 -2
- package/template/scripts/lib/ui-baseline.mjs +1 -1
- package/template/scripts/lib/user-decision.mjs +1 -1
- package/template/scripts/lib/validation-phase.mjs +72 -0
- package/template/scripts/stage-tracking +25 -0
- package/template/scripts/strategic-consumer-entry +47 -0
- package/template/scripts/verify-context-reconciliation +4 -3
- package/template/scripts/verify-lifecycle-checkpoint +10 -0
- package/template/skills-lock.json +13 -13
- package/template.snapshot.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { normalizeSliceContract } from './slice-contract.mjs';
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { readFileSync } from
|
|
3
|
+
import { readFileSync } from './validation-phase.mjs';
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parseDocument } from "../vendor/yaml.mjs";
|
|
6
6
|
import { ROOT } from "./lifecycle-registry.mjs";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
|
+
import {createHash} from 'node:crypto';
|
|
5
|
+
import {AsyncLocalStorage} from 'node:async_hooks';
|
|
6
|
+
|
|
7
|
+
// Only a live local call owns these snapshots. Neither receipts nor cache data confer approval.
|
|
8
|
+
const phases=new AsyncLocalStorage();
|
|
9
|
+
const checksum=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
10
|
+
const filename=value=>path.resolve(value instanceof URL?fileURLToPath(value):value);
|
|
11
|
+
const error=(code,detail)=>Object.assign(new TypeError(`${code}: ${detail}`),{code});
|
|
12
|
+
const current=()=>{const phase=phases.getStore();if(phase&&!phase.active)throw error('VALIDATION_PHASE_EXPIRED','验证阶段已经结束');if(phase?.signal?.aborted)throw error('VALIDATION_CANCELLED','验证阶段已取消');return phase;};
|
|
13
|
+
const statShape=stat=>({type:stat.isSymbolicLink()?'link':stat.isDirectory()?'directory':stat.isFile()?'file':'other',mode:Number(stat.mode),ino:String(stat.ino),dev:String(stat.dev)});
|
|
14
|
+
function observe(file,kind,read){const phase=current();if(!phase)return read();const key=`${kind}\0${file}`;if(!phase.observations.has(key))phase.observations.set(key,{file,kind,value:read()});return phase.observations.get(key).value;}
|
|
15
|
+
function pathIdentity(file){let part=path.parse(file).root;for(const name of path.relative(part,file).split(path.sep).filter(Boolean)){part=path.join(part,name);const nameRef=part;observe(nameRef,'stat',()=>{try{return statShape(fs.lstatSync(nameRef));}catch(e){if(e.code==='ENOENT')return null;throw e;}});}}
|
|
16
|
+
export function readFileSync(file,options){
|
|
17
|
+
const phase=current();if(!phase||typeof file==='number'||(typeof options==='object'&&options?.flag&&options.flag!=='r'))return fs.readFileSync(file,options);
|
|
18
|
+
const ref=filename(file);pathIdentity(ref);
|
|
19
|
+
if(!phase.files.has(ref))phase.files.set(ref,Buffer.from(fs.readFileSync(ref)));
|
|
20
|
+
const bytes=phase.files.get(ref),encoding=typeof options==='string'?options:options?.encoding;
|
|
21
|
+
return encoding?bytes.toString(encoding):Buffer.from(bytes);
|
|
22
|
+
}
|
|
23
|
+
export async function readFile(file,options){return readFileSync(file,options);}
|
|
24
|
+
export async function readdir(file,options){return readdirSync(file,options);}
|
|
25
|
+
export function existsSync(file){const phase=current();if(!phase||typeof file==='number')return fs.existsSync(file);const ref=filename(file);pathIdentity(ref);return observe(ref,'exists',()=>fs.existsSync(ref));}
|
|
26
|
+
export function lstatSync(file,options){const result=fs.lstatSync(file,options);const phase=current();if(phase&&result){const ref=filename(file);observe(ref,'stat',()=>statShape(result));}return result;}
|
|
27
|
+
export function readdirSync(file,options){
|
|
28
|
+
const result=fs.readdirSync(file,options),phase=current();
|
|
29
|
+
if(phase){const ref=filename(file);pathIdentity(ref);
|
|
30
|
+
// Record the enumeration actually returned to the consumer, not a second read.
|
|
31
|
+
const encoding=typeof options==='string'?options:options?.encoding||'utf8';
|
|
32
|
+
const names=result.map(entry=>{const name=typeof entry==='string'||Buffer.isBuffer(entry)?entry:entry.name;return Buffer.isBuffer(name)?name.toString():Buffer.from(name,encoding==='buffer'?'utf8':encoding).toString();}).sort();
|
|
33
|
+
const recorded=observe(ref,'directory',()=>names);
|
|
34
|
+
if(JSON.stringify(recorded)!==JSON.stringify(names))throw error('VALIDATION_INPUT_CHANGED',ref);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
function actualObservation(row){if(row.kind==='exists')return fs.existsSync(row.file);if(row.kind==='directory')return fs.readdirSync(row.file).sort();if(row.kind==='stat'){try{return statShape(fs.lstatSync(row.file));}catch(e){if(e.code==='ENOENT')return null;throw e;}}throw error('VALIDATION_RECEIPT_INVALID','未知依赖类型');}
|
|
39
|
+
function receipt(phase){return{schema_version:1,files:[...phase.files].map(([file,bytes])=>({file,digest:checksum(bytes)})),observations:[...phase.observations.values()]};}
|
|
40
|
+
function checkReceipt(value){
|
|
41
|
+
if(value?.schema_version!==1||!Array.isArray(value.files)||!Array.isArray(value.observations))throw error('VALIDATION_RECEIPT_INVALID','缺少受控校验进程的依赖');
|
|
42
|
+
for(const row of value.files){if(!path.isAbsolute(row.file)||!/^[a-f0-9]{64}$/.test(row.digest))throw error('VALIDATION_RECEIPT_INVALID','非法文件依赖');try{if(checksum(fs.readFileSync(row.file))!==row.digest)throw Error('changed');}catch{throw error('VALIDATION_INPUT_CHANGED',row.file);}}
|
|
43
|
+
for(const row of value.observations){if(!path.isAbsolute(row.file))throw error('VALIDATION_RECEIPT_INVALID','非法路径依赖');try{if(JSON.stringify(actualObservation(row))!==JSON.stringify(row.value))throw Error('changed');}catch{throw error('VALIDATION_INPUT_CHANGED',row.file);}}
|
|
44
|
+
}
|
|
45
|
+
function mergedReceipt(phase){
|
|
46
|
+
const files=new Map(),observations=new Map();
|
|
47
|
+
for(const part of [receipt(phase),...phase.children]){
|
|
48
|
+
if(part?.schema_version!==1||!Array.isArray(part.files)||!Array.isArray(part.observations))throw error('VALIDATION_RECEIPT_INVALID','缺少受控校验进程的依赖');
|
|
49
|
+
for(const row of part.files){if(typeof row.file!=='string'||!path.isAbsolute(row.file)||!/^[a-f0-9]{64}$/.test(row.digest))throw error('VALIDATION_RECEIPT_INVALID','非法文件依赖');if(files.has(row.file)&&files.get(row.file).digest!==row.digest)throw error('VALIDATION_INPUT_CHANGED',row.file);files.set(row.file,row);}
|
|
50
|
+
for(const row of part.observations){if(typeof row.file!=='string'||!path.isAbsolute(row.file)||!['stat','exists','directory'].includes(row.kind))throw error('VALIDATION_RECEIPT_INVALID','非法路径依赖');const key=`${row.kind}\0${row.file}`;if(observations.has(key)&&JSON.stringify(observations.get(key).value)!==JSON.stringify(row.value))throw error('VALIDATION_INPUT_CHANGED',row.file);observations.set(key,row);}
|
|
51
|
+
}
|
|
52
|
+
return{schema_version:1,files:[...files.values()],observations:[...observations.values()]};
|
|
53
|
+
}
|
|
54
|
+
export function acceptValidationDependencies(value){
|
|
55
|
+
const phase=current();if(!phase)throw error('VALIDATION_PHASE_REQUIRED','子进程依赖必须交回本次验证阶段');
|
|
56
|
+
// Compare parent/child observations now; verify their union against disk before returning.
|
|
57
|
+
phase.children.push(structuredClone(value));mergedReceipt(phase);
|
|
58
|
+
}
|
|
59
|
+
export function validationDependencies(){const phase=current();if(!phase)throw error('VALIDATION_PHASE_REQUIRED','没有活动阶段');return structuredClone(mergedReceipt(phase));}
|
|
60
|
+
export function validationCache(namespace,key,...values){const phase=current();if(!phase)return undefined;const cache=phase.memo.get(namespace)||new Map();phase.memo.set(namespace,cache);if(values.length)cache.set(key,structuredClone(values[0]));return structuredClone(cache.get(key));}
|
|
61
|
+
export function validationMemo(namespace,key,compute){const phase=current();if(!phase)return compute();const cache=phase.memo.get(namespace)||new Map();phase.memo.set(namespace,cache);if(!cache.has(key))cache.set(key,structuredClone(compute()));return structuredClone(cache.get(key));}
|
|
62
|
+
export function validationPhaseToken(){return current()?.token;}
|
|
63
|
+
export function inValidationPhase(){return !!current();}
|
|
64
|
+
export function withValidationPhase(binding,action){
|
|
65
|
+
const parent=current(),identity=JSON.stringify({root:path.resolve(binding.root||process.cwd()),purpose:binding.purpose,unit:binding.work_unit_id||null,slice:binding.slice_id||null,readOnly:binding.readOnly===true});
|
|
66
|
+
if(binding.signal?.aborted)throw error('VALIDATION_CANCELLED','验证阶段已取消');
|
|
67
|
+
if(parent?.identity===identity&&(!binding.signal||binding.signal===parent.signal))return action();
|
|
68
|
+
const phase={identity,token:Object.freeze({}),active:true,files:new Map(),observations:new Map(),memo:new Map(),children:[],signal:binding.signal};
|
|
69
|
+
const finish=value=>{try{current();const dependencies=mergedReceipt(phase);checkReceipt(dependencies);if(parent){parent.children.push(dependencies);mergedReceipt(parent);}return value;}finally{phase.active=false;}};
|
|
70
|
+
return phases.run(phase,()=>{try{const value=action();if(value&&typeof value.then==='function')return value.then(finish,error=>{phase.active=false;throw error;});return finish(value);}catch(error){phase.active=false;throw error;}});
|
|
71
|
+
}
|
|
72
|
+
export default {...fs,readFileSync,existsSync,lstatSync,readdirSync};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { parseArgs } from 'node:util';
|
|
5
|
+
import { parseYaml } from './lib/stage-tracking.mjs';
|
|
6
|
+
import { checkTracking, planTracking, applyTracking } from './lib/stage-tracking-migration.mjs';
|
|
7
|
+
try {
|
|
8
|
+
const { values, positionals } = parseArgs({ allowPositionals: true, strict: true, options: { root: { type: 'string' }, checkpoint: { type: 'string' }, items: { type: 'string' }, plan: { type: 'string' }, refresh: { type: 'boolean', default: false } } });
|
|
9
|
+
const root = path.resolve(values.root || path.resolve(import.meta.dirname, '..'));
|
|
10
|
+
const command = positionals[0];
|
|
11
|
+
if (positionals.length !== 1 || !['check', 'plan', 'apply'].includes(command)) throw new Error('用法: stage-tracking check|plan --root <项目> --checkpoint <相对路径> [--items <yaml>] [--refresh];apply --root <项目> --plan <json>');
|
|
12
|
+
let result;
|
|
13
|
+
if (command === 'apply') {
|
|
14
|
+
if (!values.plan || values.checkpoint || values.items || values.refresh) throw new Error('apply 只接受 --root 和 --plan');
|
|
15
|
+
result = applyTracking(root, JSON.parse(readFileSync(values.plan, 'utf8')));
|
|
16
|
+
} else {
|
|
17
|
+
if (!values.checkpoint || values.plan) throw new Error('check/plan 需要 --checkpoint');
|
|
18
|
+
if (command === 'check' && (values.items || values.refresh)) throw new Error('check 不接受写入意图参数');
|
|
19
|
+
const input = values.items ? parseYaml(readFileSync(values.items, 'utf8')) : [];
|
|
20
|
+
if (!Array.isArray(input)) throw new Error('--items 必须是工作项数组');
|
|
21
|
+
result = command === 'check' ? checkTracking(root, values.checkpoint) : planTracking(root, { checkpoint_ref: values.checkpoint, items: input, refresh: values.refresh });
|
|
22
|
+
if (result.status === 'blocked' || (result.status === 'missing-checkpoint' && result.enabled)) process.exitCode = 1;
|
|
23
|
+
}
|
|
24
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
25
|
+
} catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
5
|
+
import { openBundle, openDelivery, importBundle } from './lib/strategic-handoff.mjs';
|
|
6
|
+
import { read, safe, ensure, hash, schema, project } from './lib/strategic-handoff-io.mjs';
|
|
7
|
+
import { consumerEntry } from './lib/strategic-handoff-routing.mjs';
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const { values } = parseArgs({ options: { root: { type: 'string' }, receipt: { type: 'string' }, bundle: { type: 'string' } } });
|
|
11
|
+
const root = project(values.root);
|
|
12
|
+
ensure(Boolean(values.receipt) !== Boolean(values.bundle), 'provide-receipt-or-bundle');
|
|
13
|
+
const inspect = b => {
|
|
14
|
+
ensure(b.handoff.schema_version === 5, 'design-entry-requires-handoff-v5');
|
|
15
|
+
const route = b.handoff.consumer_routes.find(item => item.capability === 'backend-technical-design');
|
|
16
|
+
ensure(route && route.activation !== 'not-applicable', 'backend-consumer-route-not-active');
|
|
17
|
+
return { ...consumerEntry(root, route.capability, route.entry_work_unit), route_id: route.route_id,
|
|
18
|
+
bundle_id: b.manifest.bundle_id, version: b.manifest.version, bundle_digest: b.manifest.bundle_digest };
|
|
19
|
+
};
|
|
20
|
+
let receiptRef = values.receipt;
|
|
21
|
+
if (values.bundle) {
|
|
22
|
+
const input = path.resolve(values.bundle);
|
|
23
|
+
// Validate the destination route before any import writes.
|
|
24
|
+
if (existsSync(path.join(input, 'delivery-record.json'))) await openDelivery(input, inspect);
|
|
25
|
+
else await openBundle(input, inspect);
|
|
26
|
+
receiptRef = (await importBundle({ bundle: input, targetRoot: root })).receipt_ref;
|
|
27
|
+
}
|
|
28
|
+
const receipt = read(safe(root, receiptRef));
|
|
29
|
+
ensure([2, 3].includes(receipt.schema_version), 'design-entry-receipt-version');
|
|
30
|
+
schema(receipt, receipt.schema_version === 3 ? 'docs/process/schemas/strategic-handoff-import-receipt-v3.schema.json' : 'docs/process/schemas/strategic-handoff-import-receipt.schema.json');
|
|
31
|
+
const base = `docs/handoffs/${receipt.bundle_id}/${receipt.version}`;
|
|
32
|
+
ensure(receiptRef === `${base}/import-receipt.json` && receipt.package_ref === `${base}/package`, 'design-entry-receipt-path');
|
|
33
|
+
const entry = await openBundle(safe(root, receipt.package_ref), inspect);
|
|
34
|
+
ensure(entry.bundle_id === receipt.bundle_id && entry.version === receipt.version && entry.bundle_digest === receipt.bundle_digest, 'design-entry-receipt-drift');
|
|
35
|
+
const route = receipt.routes.find(item => item.capability === entry.capability);
|
|
36
|
+
ensure(route?.route_id === entry.route_id && route.activation !== 'not-applicable', 'design-entry-receipt-route');
|
|
37
|
+
if (receipt.schema_version === 3) {
|
|
38
|
+
ensure(receipt.source_delivery_record_ref === `${base}/source-delivery-record.json`, 'design-entry-delivery-path');
|
|
39
|
+
const bytes = readFileSync(safe(root, receipt.source_delivery_record_ref));
|
|
40
|
+
ensure(hash(bytes) === receipt.source_delivery_record_sha256, 'design-entry-delivery-drift');
|
|
41
|
+
const record = JSON.parse(bytes);
|
|
42
|
+
ensure(record.bundle_digest === receipt.bundle_digest && record.handoff.id === receipt.bundle_id && record.handoff.version === receipt.version, 'design-entry-delivery-binding');
|
|
43
|
+
}
|
|
44
|
+
console.log(JSON.stringify({ result: values.bundle ? 'design-imported' : 'design-inputs-verified', ...entry,
|
|
45
|
+
import_receipt_ref: receiptRef, next_work_unit: entry.target_work_unit, ready_for_agent: false,
|
|
46
|
+
stage_verification_required: true, pending: ['target-context-reconciliation', 'engineering-design-and-consumption', 'slice-contract-approval'] }, null, 2));
|
|
47
|
+
} catch (error) { console.error(JSON.stringify({ result: 'blocked', error: error.message, ready_for_agent: false })); process.exitCode = 1; }
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {withValidationPhase,validationDependencies} from "./lib/validation-phase.mjs";
|
|
2
3
|
import { parseArgs } from "node:util";
|
|
3
4
|
import { verifyContextReconciliation } from "./lib/context-reconciliation.mjs";
|
|
4
5
|
try {
|
|
5
|
-
const { values, positionals } = parseArgs({ options: { root: { type: "string", default: process.cwd() } }, allowPositionals: true, strict: true });
|
|
6
|
+
const { values, positionals } = parseArgs({ options: { "validation-dependencies": {type:"boolean",default:false}, root: { type: "string", default: process.cwd() } }, allowPositionals: true, strict: true });
|
|
6
7
|
if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-context-reconciliation [--root <repo>] <record.yaml|json>");
|
|
7
|
-
verifyContextReconciliation(positionals[0], { root: values.root });
|
|
8
|
-
process.stdout.write("Context reconciliation 验证通过\n");
|
|
8
|
+
const result=withValidationPhase({root:values.root,purpose:"context-reconciliation",readOnly:true},()=>{verifyContextReconciliation(positionals[0], { root: values.root });return values["validation-dependencies"]?{result:"verified",validation_dependencies:validationDependencies()}:null;});
|
|
9
|
+
process.stdout.write(result?JSON.stringify(result)+"\n":"Context reconciliation 验证通过\n");
|
|
9
10
|
} catch (error) {
|
|
10
11
|
process.stderr.write(`Context reconciliation 验证失败: ${error.message}\n`);
|
|
11
12
|
process.exitCode = 1;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { assertStageTracking } from './lib/stage-tracking.mjs';
|
|
2
3
|
import { readFileSync } from "node:fs";
|
|
3
4
|
import { spawnSync } from "node:child_process";
|
|
4
5
|
import path from "node:path";
|
|
@@ -6,6 +7,7 @@ import { parseArgs } from "node:util";
|
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
import { parseDocument } from "./vendor/yaml.mjs";
|
|
8
9
|
import { assertCheckpointApprovals, assertCheckpointUserDecisions } from "./lib/approval-record.mjs";
|
|
10
|
+
import { loadExecutionScope, assertScopeWorkUnit, verifyDeliveryTerminal } from './lib/lifecycle-execution-scope.mjs';
|
|
9
11
|
import { assertPlanCheckpoint } from "./lib/plan-spec-entry.mjs";
|
|
10
12
|
|
|
11
13
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -32,6 +34,14 @@ try {
|
|
|
32
34
|
const value = document.toJS({ maxAliasCount: 0 });
|
|
33
35
|
const result = spawnSync("python3", ["-c", validator, schemaPath], { cwd: root, encoding: "utf8", input: JSON.stringify(value) });
|
|
34
36
|
if (result.status !== 0) throw new TypeError(`${result.stdout}${result.stderr}`.trim());
|
|
37
|
+
if(loadExecutionScope(root)) {
|
|
38
|
+
if(value.status==='completed') {
|
|
39
|
+
if(value.next_work_unit!==null)throw new TypeError('后端终点不得继续其他工作单元');
|
|
40
|
+
verifyDeliveryTerminal(root);
|
|
41
|
+
} else if(value.next_work_unit) assertScopeWorkUnit(value.next_work_unit,{root,readOnly:value.mode==='audit'||value.mode==='route'});
|
|
42
|
+
else if(value.mode==='resume'||value.mode==='orchestrate') assertScopeWorkUnit('work-unit.entry-triage',{root});
|
|
43
|
+
}
|
|
44
|
+
assertStageTracking(value, { root, checkpointRef: path.relative(root, sourcePath), nextWorkUnit: value.next_work_unit, entering: value.mode === 'resume' || value.mode === 'orchestrate' });
|
|
35
45
|
assertCheckpointApprovals(value, sourcePath);
|
|
36
46
|
assertPlanCheckpoint(value);
|
|
37
47
|
assertCheckpointUserDecisions(value);
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"revision": "c4d958f18cc947cb91cbe1bd48783fa4601cc18f"
|
|
19
19
|
},
|
|
20
20
|
"iloveZzz/yss-harness-design-agent": {
|
|
21
|
-
"revision": "
|
|
21
|
+
"revision": "9e17922a0a718e5bd1845ddab11850a2f43becad"
|
|
22
22
|
},
|
|
23
23
|
"ayghri/i-have-adhd": {
|
|
24
24
|
"revision": "7b9069b39972e269e61bd95c2f66ebb90cac6a02"
|
|
@@ -425,7 +425,7 @@
|
|
|
425
425
|
"sourceType": "git-submodule",
|
|
426
426
|
"skillPath": ".agents/skills/prototype-review/SKILL.md",
|
|
427
427
|
"effectiveHash": "410ed10f248f6eb396cd50cea905032e45ec9b203aad41dbf78dbd03aba84b55",
|
|
428
|
-
"sourceRevision": "
|
|
428
|
+
"sourceRevision": "9e17922a0a718e5bd1845ddab11850a2f43becad",
|
|
429
429
|
"upstreamHash": "6df02dd4de236a749a80efd5eba46d18be7979849af2a9af28636906ccfcb2a0",
|
|
430
430
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
431
431
|
"targets": [
|
|
@@ -707,7 +707,7 @@
|
|
|
707
707
|
"sourceType": "git-submodule",
|
|
708
708
|
"skillPath": ".agents/skills/yss-design-system/SKILL.md",
|
|
709
709
|
"effectiveHash": "b3ddbff30926f6675ac60cbf89182593df7ed272d7a1dc75f657f7640960c1b8",
|
|
710
|
-
"sourceRevision": "
|
|
710
|
+
"sourceRevision": "9e17922a0a718e5bd1845ddab11850a2f43becad",
|
|
711
711
|
"upstreamHash": "e156229435c35827c48d3699b021e5e171ec565c2bf91cc91cbb033bf7802d7c",
|
|
712
712
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
713
713
|
"targets": [
|
|
@@ -832,7 +832,7 @@
|
|
|
832
832
|
"source": "project",
|
|
833
833
|
"sourceType": "local",
|
|
834
834
|
"skillPath": ".agents/skills/yss-implementation-contract-compiler/SKILL.md",
|
|
835
|
-
"effectiveHash": "
|
|
835
|
+
"effectiveHash": "68cc10eaedad5ff77e48f1d75b7bb37de46b0f250dcd18a7deb6c8d9e64d6035",
|
|
836
836
|
"targets": [
|
|
837
837
|
".agents/skills",
|
|
838
838
|
".codex/skills",
|
|
@@ -868,7 +868,7 @@
|
|
|
868
868
|
"source": "project",
|
|
869
869
|
"sourceType": "local",
|
|
870
870
|
"skillPath": ".agents/skills/yss-openapi-draft-review/SKILL.md",
|
|
871
|
-
"effectiveHash": "
|
|
871
|
+
"effectiveHash": "d4ff53b34a41c852f5f7ac0b9c0d2f70ca8a027e04a9622f7c0770683a0ab69d",
|
|
872
872
|
"targets": [
|
|
873
873
|
".agents/skills",
|
|
874
874
|
".codex/skills",
|
|
@@ -880,7 +880,7 @@
|
|
|
880
880
|
"source": "project",
|
|
881
881
|
"sourceType": "local",
|
|
882
882
|
"skillPath": ".agents/skills/yss-openapi-governance/SKILL.md",
|
|
883
|
-
"effectiveHash": "
|
|
883
|
+
"effectiveHash": "d00b62edef550e2d8c066ce8aa034422bd00825adcc15b6b0953dff7d23af4c0",
|
|
884
884
|
"targets": [
|
|
885
885
|
".agents/skills",
|
|
886
886
|
".codex/skills",
|
|
@@ -892,7 +892,7 @@
|
|
|
892
892
|
"source": "project",
|
|
893
893
|
"sourceType": "local",
|
|
894
894
|
"skillPath": ".agents/skills/yss-product-lifecycle/SKILL.md",
|
|
895
|
-
"effectiveHash": "
|
|
895
|
+
"effectiveHash": "0904753ec31459a719530aae71864e5a8f2d8acef66f64065c7e2848a362c23e",
|
|
896
896
|
"targets": [
|
|
897
897
|
".agents/skills",
|
|
898
898
|
".codex/skills",
|
|
@@ -904,8 +904,8 @@
|
|
|
904
904
|
"source": "iloveZzz/yss-harness-design-agent",
|
|
905
905
|
"sourceType": "git-submodule",
|
|
906
906
|
"skillPath": ".agents/skills/yss-prototype-stage/SKILL.md",
|
|
907
|
-
"effectiveHash": "
|
|
908
|
-
"sourceRevision": "
|
|
907
|
+
"effectiveHash": "4cc7d388f89feddf50d208b2d5db3a4ffa41974afb364328270c097970fc39c0",
|
|
908
|
+
"sourceRevision": "9e17922a0a718e5bd1845ddab11850a2f43becad",
|
|
909
909
|
"upstreamHash": "6e1bcdf107d95c11faee2b988e4e0c36b8e5b76f6b40312a206b83733a96b0fc",
|
|
910
910
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
911
911
|
"targets": [
|
|
@@ -982,8 +982,8 @@
|
|
|
982
982
|
"source": "iloveZzz/yss-harness-design-agent",
|
|
983
983
|
"sourceType": "git-submodule",
|
|
984
984
|
"skillPath": ".agents/skills/yss-stage-decision/SKILL.md",
|
|
985
|
-
"effectiveHash": "
|
|
986
|
-
"sourceRevision": "
|
|
985
|
+
"effectiveHash": "43a83bc02fea3c36105be6791ad019036b7ea1a17e5f0704daf93fb7be29b60b",
|
|
986
|
+
"sourceRevision": "9e17922a0a718e5bd1845ddab11850a2f43becad",
|
|
987
987
|
"upstreamHash": "f7f765e20f4dca6aca667be03e2b9a7f2a8acc3510eefba88306961882d86ed4",
|
|
988
988
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
989
989
|
"targets": [
|
|
@@ -997,7 +997,7 @@
|
|
|
997
997
|
"source": "project",
|
|
998
998
|
"sourceType": "local",
|
|
999
999
|
"skillPath": ".agents/skills/yss-tactical-design/SKILL.md",
|
|
1000
|
-
"effectiveHash": "
|
|
1000
|
+
"effectiveHash": "c4a519d1faef1de31c85a9bfae0b5b3888432da68470bb23a434be8751164548",
|
|
1001
1001
|
"targets": [
|
|
1002
1002
|
".agents/skills",
|
|
1003
1003
|
".codex/skills",
|
|
@@ -1009,7 +1009,7 @@
|
|
|
1009
1009
|
"source": "project",
|
|
1010
1010
|
"sourceType": "local",
|
|
1011
1011
|
"skillPath": ".agents/skills/yss-technical-design/SKILL.md",
|
|
1012
|
-
"effectiveHash": "
|
|
1012
|
+
"effectiveHash": "0b701b6a323a227bf4be9201661039f70760ded9c5dcbda594f5bc6d18226fcd",
|
|
1013
1013
|
"targets": [
|
|
1014
1014
|
".agents/skills",
|
|
1015
1015
|
".codex/skills",
|
package/template.snapshot.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"templateName": "yss-spec-project-template",
|
|
4
4
|
"templateSource": "github:iloveZzz/yss-spec-project-template",
|
|
5
5
|
"templateRepository": "https://github.com/iloveZzz/yss-spec-project-template.git",
|
|
6
|
-
"requestedRef": "
|
|
7
|
-
"templateCommit": "
|
|
6
|
+
"requestedRef": "445172278b7a107ac42ec00ee1dd936bdd244933",
|
|
7
|
+
"templateCommit": "445172278b7a107ac42ec00ee1dd936bdd244933",
|
|
8
8
|
"sourceState": "committed",
|
|
9
9
|
"manifestHash": "7c2fe5e36a464fd32b4ec6466e18e8c762a59bda9cb5b598950aba7dd6358891",
|
|
10
10
|
"encodedPaths": {
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
".gitignore": "__yss_dotfile__.gitignore",
|
|
18
18
|
".pi/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/.gitignore": ".pi/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/__yss_dotfile__.gitignore"
|
|
19
19
|
},
|
|
20
|
-
"snapshotHash": "
|
|
21
|
-
"generatedAt": "2026-09-
|
|
20
|
+
"snapshotHash": "7a8f13451bd03f54c57a0b4fa3f713fcf0e43601212590a3fb6e8e5db34f5b37",
|
|
21
|
+
"generatedAt": "2026-09-22T11:13:45.412Z"
|
|
22
22
|
}
|