create-yss-spec 3.5.4 → 3.5.6
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 +10 -0
- package/cli-core.lock.json +130 -0
- package/package.json +7 -3
- package/resources/upgrade-skill/SKILL.md +26 -0
- package/resources/upgrade-skill/protocol.md +40 -0
- package/resources/upgrade-skill/references/cli-families.md +14 -0
- package/src/cli/help.js +1 -0
- package/src/cli/index.js +12 -0
- package/src/filesystem/transaction-runner.js +27 -0
- package/src/template/asset-runtime.js +9 -1
- package/src/template/instance-runtime.js +4 -2
- package/src/template/verification-runtime.js +9 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +2 -2
- package/template/.agents/skills/yss-harness-upgrade/SKILL.md +26 -0
- package/template/.agents/skills/yss-harness-upgrade/references/cli-families.md +14 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +1 -0
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +15 -19
- package/template/.agents/skills/yss-stage-decision/SKILL.md +3 -0
- package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -4
- package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -4
- package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +13 -1
- package/template/.codex/skills/yss-harness-upgrade/SKILL.md +26 -0
- package/template/.codex/skills/yss-harness-upgrade/references/cli-families.md +14 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +1 -0
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +15 -19
- package/template/.codex/skills/yss-stage-decision/SKILL.md +3 -0
- package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -4
- package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -4
- package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +13 -1
- package/template/.cursor/skills/yss-harness-upgrade/SKILL.md +26 -0
- package/template/.cursor/skills/yss-harness-upgrade/references/cli-families.md +14 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +1 -0
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +15 -19
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +3 -0
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -4
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -4
- package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +13 -1
- package/template/.pi/skills/yss-harness-upgrade/SKILL.md +26 -0
- package/template/.pi/skills/yss-harness-upgrade/references/cli-families.md +14 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +1 -0
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +15 -19
- package/template/.pi/skills/yss-stage-decision/SKILL.md +3 -0
- package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -4
- package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -4
- package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +13 -1
- package/template/.template-spec/agents/yss-skill-registry.yaml +9 -1
- package/template/.template-spec/process/contract-reading.md +1 -1
- package/template/.template-spec/process/document-writing.md +12 -0
- package/template/.template-spec/process/harness-upgrade.md +40 -0
- package/template/.template-spec/process/lifecycle-artifact-map.md +2 -2
- package/template/.template-spec/process/lifecycle-registry.yaml +3 -1
- package/template/.template-spec/process/schemas/approval-record.schema.json +23 -0
- package/template/.template-spec/process/stage-tracking.md +2 -2
- package/template/.template-spec/process/structured-assets.md +35 -0
- package/template/.template-spec/process/templates/lifecycle-checkpoint-template.json +48 -0
- package/template/.template-spec/templates/approval-record-template.json +23 -0
- package/template/scripts/check-plan-stage-coverage +12 -0
- package/template/scripts/contract +6 -0
- package/template/scripts/lib/approval-record.mjs +4 -3
- package/template/scripts/lib/asset-command.mjs +35 -0
- package/template/scripts/lib/asset-migration.mjs +101 -0
- package/template/scripts/lib/asset-transactions.mjs +235 -0
- package/template/scripts/lib/checkpoint-boundary.mjs +3 -0
- package/template/scripts/lib/contract-views.mjs +7 -1
- package/template/scripts/lib/json-schema.mjs +43 -4
- package/template/scripts/lib/lifecycle-context-query.mjs +7 -0
- package/template/scripts/lib/lifecycle-presentation.mjs +77 -0
- package/template/scripts/lib/lifecycle-status.mjs +16 -1
- package/template/scripts/lib/plan-stage-coverage.mjs +40 -0
- package/template/scripts/lib/reading-view-bundle.mjs +1 -0
- package/template/scripts/lib/reading-view-markdown.mjs +8 -6
- package/template/scripts/lib/stage-tracking-migration.mjs +11 -3
- package/template/scripts/lib/structured-assets.mjs +81 -0
- package/template/scripts/lib/task-package.mjs +4 -1
- package/template/scripts/lifecycle-status +6 -3
- package/template/scripts/verify-lifecycle-checkpoint +8 -5
- package/template/skills-lock.json +21 -9
- package/template.manifest.json +2 -1
- package/template.snapshot.json +5 -5
- package/vendor/cli-core/build.mjs +302 -0
- package/vendor/cli-core/bundle.mjs +198 -0
- package/vendor/cli-core/cli.mjs +182 -0
- package/vendor/cli-core/command-runner.mjs +107 -0
- package/vendor/cli-core/engine.mjs +239 -0
- package/vendor/cli-core/family.mjs +28 -0
- package/vendor/cli-core/gitignore.mjs +15 -0
- package/vendor/cli-core/identity.mjs +274 -0
- package/vendor/cli-core/io.mjs +153 -0
- package/vendor/cli-core/layout-migration.mjs +64 -0
- package/vendor/cli-core/legacy.mjs +19 -0
- package/vendor/cli-core/migrate.mjs +237 -0
- package/vendor/cli-core/migration-adapter.mjs +19 -0
- package/vendor/cli-core/package.json +13 -0
- package/vendor/cli-core/scaffold.mjs +117 -0
- package/vendor/cli-core/spec-migration-adapter.mjs +83 -0
- package/vendor/cli-core/tests/build.test.mjs +40 -0
- package/vendor/cli-core/tests/cli.test.mjs +1065 -0
- package/vendor/cli-core/tests/migration-version.test.mjs +8 -0
- package/vendor/cli-core/tests/package-contract.mjs +89 -0
- package/vendor/cli-core/transaction.mjs +529 -0
- package/vendor/cli-core/update.mjs +79 -0
- package/vendor/cli-core/vendor/NOTICES.md +6 -0
- package/vendor/cli-core/vendor/yaml.LICENSE +13 -0
- package/vendor/cli-core/vendor/yaml.mjs +6311 -0
- package/vendor/cli-core/verification.mjs +131 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {createRequire} from 'node:module';
|
|
5
|
+
import {hash,ensure,same,descriptor,write} from './io.mjs';
|
|
6
|
+
import {inventory,copyCandidate,migration,parseMigration,assertUpgradeVersion} from './migrate.mjs';
|
|
7
|
+
import {verifyCore} from './build.mjs';
|
|
8
|
+
export function specAdapter(packageRoot) {
|
|
9
|
+
verifyCore(packageRoot);
|
|
10
|
+
const require=createRequire(path.join(packageRoot,'package.json'));
|
|
11
|
+
const {buildSyncContext,applySyncContext}=require('./src/api/_sync-service');
|
|
12
|
+
const {verifyGeneratedProjectInstance,refreshGeneratedProjectInstance,readProjectSkillLock}=require('./src/template/verification-runtime');
|
|
13
|
+
const {readTemplateSnapshot}=require('./src/template/instance-runtime');
|
|
14
|
+
const pkg=require('./package.json'),snapshot=readTemplateSnapshot();
|
|
15
|
+
const family={side:'spec',packageName:'create-yss-spec',profileId:'harness.spec-template',metadataFile:'.yss-template.json'};
|
|
16
|
+
const fingerprint=hash(JSON.stringify({pkg,snapshot,src:inventory(path.join(packageRoot,'src')),driver:inventory(path.join(packageRoot,'vendor/cli-core'))}));
|
|
17
|
+
return {family,fingerprint,template:{version:pkg.version,...snapshot},
|
|
18
|
+
check(root,opts){const c=buildSyncContext({targetDir:root,migrateLayout:opts.migrateLayout});assertUpgradeVersion(c.metadata.cliVersion || c.metadata.templateVersion,pkg.version);},
|
|
19
|
+
prepare(root,opts,id,time){
|
|
20
|
+
const context=buildSyncContext({targetDir:root,migrateLayout:opts.migrateLayout});
|
|
21
|
+
const resolutions={...(opts.resolutions || {})}, conflictMap=new Map(context.syncPlan.forceableConflicts.map(o=>[o.relativePath,o]));
|
|
22
|
+
for(const op of context.syncPlan.forceableConflicts){
|
|
23
|
+
const saved=context.metadata.managedFiles[op.relativePath]?.migrationCustomization;
|
|
24
|
+
if(!resolutions[op.relativePath] && saved?.templateDigest===op.desiredHash && saved.contentDigest===context.syncPlan.currentHashes[op.relativePath])
|
|
25
|
+
resolutions[op.relativePath]={action:'preserve',beforeDigest:saved.contentDigest,templateDigest:saved.templateDigest};
|
|
26
|
+
}
|
|
27
|
+
const unresolved=context.syncPlan.conflicts.filter(o=>!resolutions[o.relativePath]);
|
|
28
|
+
if(unresolved.length)throw Object.assign(new Error(`治理文件冲突,需逐项决议: ${unresolved.map(o=>o.relativePath).join(', ')}`),{code:'CONFLICT',result:{conflicts:unresolved.map(o=>({path:o.relativePath,beforeDigest:context.syncPlan.currentHashes[o.relativePath],templateDigest:o.desiredHash,resolutionSupported:conflictMap.has(o.relativePath)}))}});
|
|
29
|
+
for(const [ref,r]of Object.entries(resolutions)) {
|
|
30
|
+
const op=conflictMap.get(ref);
|
|
31
|
+
ensure(op && context.metadata.managedFiles[ref] && r.beforeDigest===context.syncPlan.currentHashes[ref] && r.templateDigest===op.desiredHash,`非可信或过期的冲突决议: ${ref}`,'CONFLICT');
|
|
32
|
+
ensure(['preserve','merge'].includes(r.action) && (r.action!=='merge' || typeof r.contentBase64==='string'),'冲突决议非法','CONFLICT');
|
|
33
|
+
}
|
|
34
|
+
const scratch=fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(),'yss-spec-migration-')));
|
|
35
|
+
try {
|
|
36
|
+
const before=inventory(root);delete before['.yss-harness-migrate.lock'];copyCandidate(root,scratch,before);
|
|
37
|
+
const stage=buildSyncContext({targetDir:scratch,migrateLayout:opts.migrateLayout});
|
|
38
|
+
stage.syncPlan.forceableConflicts=stage.syncPlan.forceableConflicts.filter(o=>resolutions[o.relativePath]?.action==='merge');
|
|
39
|
+
const applied=applySyncContext(stage,{force:stage.syncPlan.forceableConflicts.length>0,prune:opts.prune});
|
|
40
|
+
try {
|
|
41
|
+
const merged=Object.entries(resolutions).filter(([,r])=>r.action==='merge');
|
|
42
|
+
if(merged.length){
|
|
43
|
+
const lock=readProjectSkillLock(scratch);
|
|
44
|
+
for(const [ref,r] of merged)write(scratch,ref,Buffer.from(r.contentBase64,'base64'),descriptor(root,ref).mode);
|
|
45
|
+
// Regenerate from merged skill bytes; historical upstream baselines remain unchanged.
|
|
46
|
+
const transaction={writeFile:(p,bytes)=>fs.writeFileSync(p,bytes),prepare(){},mark(){},ensureParent:p=>fs.mkdirSync(path.dirname(p),{recursive:true})};
|
|
47
|
+
refreshGeneratedProjectInstance(scratch,{previousSkillLock:lock,previousManagedFiles:stage.metadata.managedFiles,transaction});
|
|
48
|
+
verifyGeneratedProjectInstance(scratch);
|
|
49
|
+
}
|
|
50
|
+
const metaFile=path.join(scratch,family.metadataFile),meta=JSON.parse(fs.readFileSync(metaFile));
|
|
51
|
+
for(const [ref,r] of Object.entries(resolutions)) {
|
|
52
|
+
// Keep the upstream baseline separate from explicitly accepted local content.
|
|
53
|
+
meta.managedFiles[ref]={...context.metadata.managedFiles[ref],contentHash:r.templateDigest,migrationCustomization:{templateDigest:r.templateDigest,contentDigest:hash(fs.readFileSync(path.join(scratch,ref)))}};
|
|
54
|
+
}
|
|
55
|
+
const prior=JSON.parse(fs.readFileSync(path.join(root,family.metadataFile)));
|
|
56
|
+
meta.lastSyncedAt=prior.lastSyncedAt;
|
|
57
|
+
if(JSON.stringify(meta)!==JSON.stringify(prior))meta.lastSyncedAt=time;
|
|
58
|
+
fs.writeFileSync(metaFile,JSON.stringify(meta,null,2)+'\n');
|
|
59
|
+
const after=inventory(scratch),operations=[];
|
|
60
|
+
for(const ref of [...new Set([...Object.keys(before),...Object.keys(after)])].sort()) {
|
|
61
|
+
const a=before[ref] || null,b=after[ref] || null;
|
|
62
|
+
if(a?.type==='directory' || b?.type==='directory')continue;
|
|
63
|
+
if(a?.type==='symlink' || b?.type==='symlink'){ensure(JSON.stringify(a)===JSON.stringify(b),'候选改变符号链接','PATH');continue;}
|
|
64
|
+
if(!same(a,b))operations.push({path:ref,before:a,after:b,bytes:b?fs.readFileSync(path.join(scratch,ref)):undefined});
|
|
65
|
+
}
|
|
66
|
+
operations.sort((a,b)=>(a.path===family.metadataFile?1:0)-(b.path===family.metadataFile?1:0));
|
|
67
|
+
return {operations,changes:context.plan.changes};
|
|
68
|
+
}finally{if(applied.backupPath)fs.rmSync(applied.backupPath,{recursive:true,force:true});}
|
|
69
|
+
}finally{fs.rmSync(scratch,{recursive:true,force:true});}
|
|
70
|
+
},
|
|
71
|
+
verify(root){
|
|
72
|
+
const scratch=fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(),'yss-spec-verify-')));
|
|
73
|
+
try{const tree=inventory(root);delete tree['.yss-harness-migrate.lock'];copyCandidate(root,scratch,tree);verifyGeneratedProjectInstance(scratch);return [{name:'project-instance',status:'passed',location:'isolated-copy'}];}
|
|
74
|
+
finally{fs.rmSync(scratch,{recursive:true,force:true});}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export function runSpecMigration(packageRoot,args){
|
|
79
|
+
const {command,opts}=parseMigration(args),require=createRequire(path.join(packageRoot,'package.json'));
|
|
80
|
+
const {withVerificationOutput}=require('./src/template/verification-runtime'),logs=[];
|
|
81
|
+
const result=withVerificationOutput(text=>logs.push(text),()=>migration(specAdapter(packageRoot),command,opts));
|
|
82
|
+
return {...result,...(logs.length?{verificationLog:logs.join('')}:{})};
|
|
83
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {test} from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {spawnSync} from 'node:child_process';
|
|
7
|
+
import {syncCore,syncTemplate,verifyCore} from '../build.mjs';
|
|
8
|
+
import {loadBundle} from '../bundle.mjs';
|
|
9
|
+
const put=(root,ref,bytes)=>{fs.mkdirSync(path.dirname(path.join(root,ref)),{recursive:true});fs.writeFileSync(path.join(root,ref),bytes);};
|
|
10
|
+
test('战略 YAML 清单投影、固定来源与 WORKTREE 仅在临时副本构建',t=>{
|
|
11
|
+
const tmp=fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(),'harness-build-')));t.after(()=>fs.rmSync(tmp,{recursive:true,force:true}));
|
|
12
|
+
const source=path.join(tmp,'source'),pkg=path.join(tmp,'package');
|
|
13
|
+
fs.mkdirSync(source);put(pkg,'package.json',JSON.stringify({name:'create-yss-harness-design',version:'0.6.0'}));
|
|
14
|
+
fs.cpSync(path.resolve(import.meta.dirname,'..'),path.join(source,'.template-source/cli-core'),{recursive:true});
|
|
15
|
+
for(const name of ['README.md','AGENTS.md','CONTEXT.md','DESIGN.md'])put(source,name,name+'\n');
|
|
16
|
+
put(source,'yss-project.yaml','schema_version: 1\nrepository_mode: template-source\n');
|
|
17
|
+
put(source,'.template-spec/process/harness-profile.yaml','schema_version: 2\nprofile_id: harness.business-ddd-strategy-handoff\n');
|
|
18
|
+
put(source,'.template-spec/user-guide/retired.md','retired handbook\n');
|
|
19
|
+
put(source,'.template-spec/user-guide/current.md','current handbook v1\n');
|
|
20
|
+
put(source,'.template-spec/process/instance-distribution-manifest.yaml',`schema_version: 1
|
|
21
|
+
profile_id: harness.business-ddd-strategy-handoff
|
|
22
|
+
cli_package: create-yss-harness-design
|
|
23
|
+
template_source: github:iloveZzz/yss-harness-design-agent
|
|
24
|
+
allow_root_entries: [.template-spec]
|
|
25
|
+
allow_root_files: [README.md, AGENTS.md, CONTEXT.md, DESIGN.md, yss-project.yaml]
|
|
26
|
+
exclude_root_entries: [.git, .template-source]
|
|
27
|
+
render_paths: [README.md, AGENTS.md, yss-project.yaml]
|
|
28
|
+
`);
|
|
29
|
+
const git=(...args)=>{const r=spawnSync('git',['-C',source,...args],{encoding:'utf8'});assert.equal(r.status,0,r.stderr);return r.stdout.trim();};
|
|
30
|
+
git('init','--initial-branch=main');git('add','.');git('-c','user.name=Fixture','-c','user.email=fixture@example.invalid','commit','-m','fixture');
|
|
31
|
+
const ref=git('rev-parse','HEAD');syncCore(source,ref,pkg);syncTemplate(source,ref,pkg);verifyCore(pkg);loadBundle(pkg);
|
|
32
|
+
const before=fs.readFileSync(path.join(pkg,'template.snapshot.json'));
|
|
33
|
+
put(source,'DESIGN.md','worktree changes\n');syncTemplate(source,ref,pkg,true);assert.deepEqual(fs.readFileSync(path.join(pkg,'template.snapshot.json')),before);
|
|
34
|
+
fs.rmSync(path.join(source,'.template-spec/user-guide/retired.md'));
|
|
35
|
+
put(source,'.template-spec/user-guide/current.md','current handbook v2\n');
|
|
36
|
+
syncTemplate(source,'WORKTREE',pkg);const worktreeBundle=loadBundle(pkg);assert.equal(worktreeBundle.snapshot.sourceState,'working-tree');
|
|
37
|
+
assert.equal(worktreeBundle.retiredFiles['.template-spec/user-guide/retired.md'].digest.length,64);
|
|
38
|
+
assert.equal(worktreeBundle.transitionBaselines['.template-spec/user-guide/current.md'].digest.length,64);
|
|
39
|
+
assert.throws(()=>syncTemplate(source,ref,pkg,true),/漂移/);
|
|
40
|
+
});
|