create-yss-spec 3.2.0 → 3.3.1
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/package.json +3 -2
- package/src/command-runner.mjs +107 -0
- package/src/self-update.js +7 -4
- package/src/template/instance-runtime.js +1 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +2 -2
- package/template/.agents/skills/code-review/SKILL.md +4 -0
- package/template/.agents/skills/code-review/agents/openai.yaml +1 -1
- package/template/.agents/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.agents/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.agents/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.agents/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.agents/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.agents/skills/yss-repository/SKILL.md +28 -70
- package/template/.agents/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.agents/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.agents/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.agents/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.agents/skills/yss-research/SKILL.md +1 -1
- package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.agents/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.claude/skills/code-review/SKILL.md +4 -0
- package/template/.claude/skills/code-review/agents/openai.yaml +1 -1
- package/template/.claude/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.claude/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.claude/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.claude/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.claude/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.claude/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.claude/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.claude/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.claude/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.claude/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.claude/skills/yss-repository/SKILL.md +28 -70
- package/template/.claude/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.claude/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.claude/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.claude/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.claude/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.claude/skills/yss-research/SKILL.md +1 -1
- package/template/.claude/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.claude/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.claude/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.claude/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.codex/skills/code-review/SKILL.md +4 -0
- package/template/.codex/skills/code-review/agents/openai.yaml +1 -1
- package/template/.codex/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.codex/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.codex/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.codex/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.codex/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.codex/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.codex/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.codex/skills/yss-repository/SKILL.md +28 -70
- package/template/.codex/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.codex/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.codex/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.codex/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.codex/skills/yss-research/SKILL.md +1 -1
- package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.codex/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.cursor/skills/code-review/SKILL.md +4 -0
- package/template/.cursor/skills/code-review/agents/openai.yaml +1 -1
- package/template/.cursor/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.cursor/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.cursor/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.cursor/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.cursor/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.cursor/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.cursor/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.cursor/skills/yss-repository/SKILL.md +28 -70
- package/template/.cursor/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.cursor/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.cursor/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.cursor/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.cursor/skills/yss-research/SKILL.md +1 -1
- package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.pi/skills/code-review/SKILL.md +4 -0
- package/template/.pi/skills/code-review/agents/openai.yaml +1 -1
- package/template/.pi/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.pi/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.pi/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.pi/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.pi/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.pi/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.pi/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.pi/skills/yss-repository/SKILL.md +28 -70
- package/template/.pi/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.pi/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.pi/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.pi/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.pi/skills/yss-research/SKILL.md +1 -1
- package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.pi/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.qoder/skills/code-review/SKILL.md +4 -0
- package/template/.qoder/skills/code-review/agents/openai.yaml +1 -1
- package/template/.qoder/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.qoder/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.qoder/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.qoder/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.qoder/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.qoder/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.qoder/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.qoder/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.qoder/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.qoder/skills/yss-repository/SKILL.md +28 -70
- package/template/.qoder/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.qoder/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.qoder/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.qoder/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.qoder/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.qoder/skills/yss-research/SKILL.md +1 -1
- package/template/.qoder/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.qoder/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.qoder/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.trae/skills/code-review/SKILL.md +4 -0
- package/template/.trae/skills/code-review/agents/openai.yaml +1 -1
- package/template/.trae/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.trae/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.trae/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.trae/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.trae/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.trae/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.trae/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.trae/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.trae/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.trae/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.trae/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.trae/skills/yss-repository/SKILL.md +28 -70
- package/template/.trae/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.trae/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.trae/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.trae/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.trae/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.trae/skills/yss-research/SKILL.md +1 -1
- package/template/.trae/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.trae/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.trae/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.trae/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/AGENTS.md +2 -2
- package/template/CONTEXT.md +3 -2
- package/template/README.md +3 -3
- package/template/docs/agents/digital-human-roles.md +1 -1
- package/template/docs/agents/digital-human-roles.yaml +13 -11
- package/template/docs/agents/issue-tracker.md +1 -1
- package/template/docs/agents/strategic-design-skills-integration.md +2 -0
- package/template/docs/agents/yss-skill-registry.yaml +5 -0
- package/template/docs/architecture/README.md +1 -1
- package/template/docs/architecture/templates/business-architecture-template.md +1 -1
- package/template/docs/architecture/templates/functional-architecture-template.md +1 -1
- package/template/docs/design/README.md +1 -1
- package/template/docs/design/templates/interaction-spec-template.md +1 -1
- package/template/docs/design/templates/product-overview-design-template.md +1 -1
- package/template/docs/{discovery → plan}/IDEATION.md +5 -5
- package/template/docs/plan/README.md +9 -0
- package/template/docs/plan/entry-review.md +23 -0
- package/template/docs/plan/templates/plan-template.md +58 -0
- package/template/docs/process/harness-process-tailoring.md +1 -1
- package/template/docs/process/lifecycle-artifact-map.md +10 -6
- package/template/docs/process/lifecycle-registry-baseline.json +10 -1
- package/template/docs/process/lifecycle-registry.yaml +48 -20
- package/template/docs/process/plan-migration.md +13 -0
- package/template/docs/process/schemas/digital-human-task-package.schema.json +2 -0
- package/template/docs/process/schemas/implementation-repository-preparation-result.schema.json +38 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +3 -0
- package/template/docs/process/schemas/lifecycle-registry.schema.json +1 -1
- package/template/docs/process/schemas/project-scaffold-contract.schema.json +113 -0
- package/template/docs/process/template-engineering-overview.md +2 -2
- package/template/docs/process/template-verification-profiles.yaml +25 -0
- package/template/docs/process/templates/context-reconciliation-template.yaml +2 -2
- package/template/docs/process/templates/lifecycle-checkpoint-template.yaml +1 -1
- package/template/docs/requirements/README.md +2 -2
- package/template/docs/templates/implementation-repo-registry-template.md +8 -0
- package/template/docs/templates/local-parent-ticket-template.md +1 -1
- package/template/docs/templates/review-report-template.md +7 -3
- package/template/docs/templates/subagent-task-package-template.md +1 -1
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +1 -1
- package/template/scripts/cache-template-commit +2 -2
- package/template/scripts/fixtures/strategic-handoff/source-roles.json +7 -7
- package/template/scripts/fixtures/user-decision/plan-fixture.mjs +30 -0
- package/template/scripts/lib/backend-delivery.mjs +5 -2
- package/template/scripts/lib/command-runner.mjs +107 -0
- package/template/scripts/lib/context-reconciliation.mjs +34 -0
- package/template/scripts/lib/json-schema.mjs +42 -13
- package/template/scripts/lib/lifecycle-context-query.mjs +141 -0
- package/template/scripts/lib/lifecycle-transition.mjs +118 -6
- package/template/scripts/lib/plan-spec-entry.mjs +87 -0
- package/template/scripts/lib/scenario-checks.mjs +44 -38
- package/template/scripts/lib/skill-registry.mjs +9 -0
- package/template/scripts/lib/skill-supply-chain.mjs +18 -2
- package/template/scripts/lib/strategic-handoff-io.mjs +5 -4
- package/template/scripts/lib/strategic-handoff.mjs +10 -9
- package/template/scripts/lib/task-package.mjs +2 -0
- package/template/scripts/lib/template-commit-cache.mjs +7 -5
- package/template/scripts/query-lifecycle-context +25 -0
- package/template/scripts/run-template-verification +9 -3
- package/template/scripts/sync-strategic-handoff-tools +9 -0
- package/template/scripts/verify-business-language-scenarios +0 -7
- package/template/scripts/verify-context-reconciliation +2 -48
- package/template/scripts/verify-context-reconciliation-scenarios +1 -1
- package/template/scripts/verify-frontend-scaffold-generator-scenarios +2 -0
- package/template/scripts/verify-lifecycle-checkpoint +2 -0
- package/template/scripts/verify-lifecycle-context-query-scenarios +88 -0
- package/template/scripts/verify-lifecycle-transition-scenarios +44 -4
- package/template/scripts/verify-plan-spec-entry +11 -0
- package/template/scripts/verify-plan-spec-entry-scenarios +79 -0
- package/template/scripts/verify-script-performance-scenarios +56 -0
- package/template/scripts/verify-subagent-task-package-scenarios +9 -8
- package/template/scripts/verify-template-cache-scenarios +11 -1
- package/template/scripts/verify-user-decision-scenarios +4 -4
- package/template/skills-lock.json +23 -23
- package/template.manifest.json +2 -1
- package/template.snapshot.json +5 -5
- package/template/.agents/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.agents/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.agents/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.agents/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.agents/skills/yss-mybatis/references/README.md +0 -57
- package/template/.agents/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.claude/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.claude/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.claude/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.claude/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.claude/skills/yss-mybatis/references/README.md +0 -57
- package/template/.claude/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.codex/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.codex/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.codex/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.codex/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.codex/skills/yss-mybatis/references/README.md +0 -57
- package/template/.codex/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.cursor/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.cursor/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.cursor/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.cursor/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.cursor/skills/yss-mybatis/references/README.md +0 -57
- package/template/.cursor/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.pi/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.pi/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.pi/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.pi/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.pi/skills/yss-mybatis/references/README.md +0 -57
- package/template/.pi/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.qoder/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.qoder/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.qoder/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.qoder/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.qoder/skills/yss-mybatis/references/README.md +0 -57
- package/template/.qoder/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.trae/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.trae/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.trae/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.trae/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.trae/skills/yss-mybatis/references/README.md +0 -57
- package/template/.trae/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/docs/discovery/README.md +0 -87
- package/template/docs/discovery/reports/.gitkeep +0 -0
- package/template/docs/discovery/reports/agent-governance-options.md +0 -71
- package/template/docs/discovery/reports/competitor-deep-dive/.gitkeep +0 -0
- package/template/docs/discovery/templates/discovery-template.md +0 -94
- /package/template/docs/{discovery → plan}/templates/competitive-analysis-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/competitive-matrix-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/market-analysis-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/user-pain-points-template.md +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, mkdtempSync, rmSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { buildPlanFixture } from "../fixtures/user-decision/plan-fixture.mjs";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import { buildDecisionFixture, buildImplementationFixture } from "../fixtures/user-decision/build-fixture.mjs";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -58,8 +59,8 @@ function validateInvocationBoundary(data) {
|
|
|
58
59
|
ensure(native?.default_entry === "yss-product-lifecycle" && native?.formal_artifact_owner === "yss-product-lifecycle", "生命周期原生入口未持有默认正式资产所有权");
|
|
59
60
|
ensure(native?.user_confirmation_policy_ref === "docs/agents/digital-human-roles.yaml#user_decision_policy", "生命周期人工门禁集合已漂移");
|
|
60
61
|
const routes = data.work_unit_routes;
|
|
61
|
-
ensure(routes?.["work-unit.
|
|
62
|
-
ensure(routes?.["work-unit.
|
|
62
|
+
ensure(routes?.["work-unit.plan-requirements"]?.skills?.includes("grilling") && routes?.["work-unit.plan-requirements"]?.skills?.includes("domain-modeling"), "需求分析工作单元缺少 grilling/domain-modeling");
|
|
63
|
+
ensure(routes?.["work-unit.plan-opportunity"]?.route_by?.market_or_competitor_fact === "competitive-intelligence" && routes["work-unit.plan-opportunity"].route_by.technical_or_standard_fact === "yss-research:technical-evidence" && routes["work-unit.plan-opportunity"].route_by.strategy_fact === "yss-research:strategy-evidence", "机会调研事实路由不准确");
|
|
63
64
|
const strategyResearch = routes?.["work-unit.domain-strategy-design"]?.research_contract;
|
|
64
65
|
ensure(strategyResearch?.profile === "strategy-evidence" && strategyResearch.mode_before_gate === "evidence-audited" && strategyResearch.artifact_owner === "yss-research" && strategyResearch.downstream_owner === "yss-stage-decision", "领域战略研究合同缺少 profile、门禁前审计或资产所有权边界");
|
|
65
66
|
const stageDecisionResearch = routes?.["work-unit.stage-decision"]?.research_contract;
|
|
@@ -76,7 +77,9 @@ function validateInvocationBoundary(data) {
|
|
|
76
77
|
ensure(routes?.["work-unit.frontend-implementation-verification"]?.skills?.includes("code-review") && routes?.["work-unit.frontend-implementation-verification"]?.applies_when === "ui_impact", "前端还原验证未绑定 UI fidelity 审查轴");
|
|
77
78
|
const reviewRoute = routes?.["work-unit.code-review"];
|
|
78
79
|
ensure(reviewRoute?.primary_skill === "code-review" && reviewRoute?.review_standards_route?.unique_default_skill === "code-review" && reviewRoute?.review_standards_route?.second_generic_review_skill === "forbidden", "code-review 不是唯一默认审查入口或允许第二套通用审查 skill");
|
|
79
|
-
ensure(includesAll(reviewRoute?.supporting_skills, ["alibaba-java-code-style", "yss-ui", "yss-domain"]) && includesAll(reviewRoute?.skills, ["code-review", "alibaba-java-code-style", "yss-ui"]), "审查工作单元缺少 YSS / Alibaba 专项检查输入");
|
|
80
|
+
ensure(includesAll(reviewRoute?.supporting_skills, ["alibaba-java-code-style", "yss-ui", "yss-domain", "yss-repository", "yss-mybatis"]) && includesAll(reviewRoute?.skills, ["code-review", "alibaba-java-code-style", "yss-ui", "yss-repository", "yss-mybatis"]), "审查工作单元缺少 YSS / Alibaba / Repository / MyBatis 专项检查输入");
|
|
81
|
+
const reviewScope = reviewRoute?.review_standards_route?.project_scope;
|
|
82
|
+
ensure(includesAll(reviewScope?.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"]) && includesAll(reviewScope?.include, ["project-itself", "registered-backend-development-projects"]) && includesAll(reviewScope?.exclude, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"]) && reviewScope?.fixed_apps_backend_assumption === "forbidden", "后端审查范围未绑定本体项目与已登记后端研发项目,或仍固定为 apps/backend");
|
|
80
83
|
const disposition = reviewRoute?.review_standards_route?.finding_disposition;
|
|
81
84
|
ensure(includesAll(disposition?.same_loop_for, ["product-slice", "template-maintenance"]) && disposition?.reviewer_write_implementation === "forbidden", "审查 finding 闭环未同时覆盖产品切片与模板维护,或允许审查者写实现");
|
|
82
85
|
ensure(includesAll(disposition?.repair_then_full_rereview?.kinds, ["violation", "machine_check_failure", "blank_applicable_row", "missing_evidence"]) && disposition?.repair_then_full_rereview?.actor === "implementer" && disposition?.repair_then_full_rereview?.then === "recapture_candidate_and_rerun_all_axes", "violation 类 finding 未要求实现者修复后全轴复审");
|
|
@@ -92,7 +95,7 @@ function validateInvocationBoundary(data) {
|
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
|
|
98
|
+
function validateWorkflowExecutionResult(payload, contract, workUnitRoutes, options = {}) {
|
|
96
99
|
for (const field of contract.required) ensure(Object.hasOwn(payload, field), `Workflow Execution Result 缺少 ${field}`);
|
|
97
100
|
ensure(contract.result_values.includes(payload.result), "Workflow Execution Result result 无效");
|
|
98
101
|
if (Object.hasOwn(payload, "unavailable_skill")) {
|
|
@@ -105,7 +108,7 @@ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
|
|
|
105
108
|
const workUnit = workUnitRoutes?.[payload.work_unit];
|
|
106
109
|
ensure(workUnit, `未知 Workflow Execution Result work_unit: ${payload.work_unit}`);
|
|
107
110
|
if (payload.result === "completed") {
|
|
108
|
-
const routeResult = validateNextRoute(payload.work_unit, payload.next_route, payload);
|
|
111
|
+
const routeResult = validateNextRoute(payload.work_unit, payload.next_route, payload, options);
|
|
109
112
|
ensure(routeResult.result === "allowed", `Workflow Execution Result next_route 非法: ${routeResult.blocking_signals.join(", ")}`);
|
|
110
113
|
ensure(payload.context_reconciliation?.status === "reconciled", "project-instance 完成态必须具有 reconciled context_reconciliation");
|
|
111
114
|
ensure(hasText(payload.context_reconciliation?.ref) && payload.evidence_refs.includes(payload.context_reconciliation.ref) && exists(payload.context_reconciliation.ref), "context_reconciliation.ref 必须可读并包含在 evidence_refs 中");
|
|
@@ -125,6 +128,8 @@ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
|
|
|
125
128
|
const implementationState = {
|
|
126
129
|
user_decisions: payload.user_decisions,
|
|
127
130
|
slice_contract_ref: payload.slice_contract_ref,
|
|
131
|
+
delivery_impacts: payload.delivery_impacts,
|
|
132
|
+
implementation_repository_preparation: payload.implementation_repository_preparation,
|
|
128
133
|
tracker_kind: payload.tracker_kind,
|
|
129
134
|
predecessor_work_unit: payload.predecessor_work_unit,
|
|
130
135
|
ready_for_agent: payload.ready_for_agent,
|
|
@@ -164,18 +169,15 @@ function validateInvocationMetadata(boundary, skillContents) {
|
|
|
164
169
|
for (const skill of boundary.model_invoked_skills) ensure(!skillContents(skill).includes("disable-model-invocation: true"), `${skill} 不应出现在 model-invoked 白名单`);
|
|
165
170
|
}
|
|
166
171
|
|
|
167
|
-
function
|
|
168
|
-
ensure(
|
|
169
|
-
ensure(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
ensure(skill.includes("不得自动调用它们或代替其创建正式资产") && skill.includes("Workflow Execution Result"), "主技能未限制 user-invoked 调用或未采用新结果协议");
|
|
177
|
-
ensure(adapter.includes("workflow reference 不表示调用") && adapter.includes("正式 Spec、Ticket 或实现资产仍只能由对应显式用户入口创建"), "适配器未限制 workflow reference 的正式资产所有权");
|
|
178
|
-
ensure(orchestration.includes("只实际调用允许的 model-invoked skill") && orchestration.includes("用户显式启动"), "编排协议未区分 model-invoked 原语和显式用户入口");
|
|
172
|
+
function validateLifecycleEntrySkill(skill) {
|
|
173
|
+
ensure(/^---\nname: yss-product-lifecycle\n/m.test(skill), "生命周期入口缺少有效 frontmatter");
|
|
174
|
+
ensure(Buffer.byteLength(skill) <= 8192, "生命周期入口超过 8KB 上下文预算");
|
|
175
|
+
for (const reference of ["docs/process/lifecycle-registry.yaml", "references/orchestration-contract.yaml", "docs/agents/yss-skill-registry.yaml", "scripts/query-lifecycle-context"]) {
|
|
176
|
+
ensure(skill.includes(reference), `生命周期入口缺少权威引用: ${reference}`);
|
|
177
|
+
}
|
|
178
|
+
for (const heading of ["### 仓库身份", "### 流转与实现", "### 用户决定", "### 外部副作用与 Git"]) {
|
|
179
|
+
ensure(skill.includes(heading), `生命周期入口缺少边界分组: ${heading}`);
|
|
180
|
+
}
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
const profiles = {
|
|
@@ -192,7 +194,7 @@ const profiles = {
|
|
|
192
194
|
prototype: {
|
|
193
195
|
message: "原型到后端脚手架及后续 YSS 代码生成压力场景验证通过",
|
|
194
196
|
files: [".agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs", ".agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml"],
|
|
195
|
-
markers: [[".agents/skills/yss-
|
|
197
|
+
markers: [[".agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml", "controlled-generation"]]
|
|
196
198
|
},
|
|
197
199
|
implementationContractCompiler: {
|
|
198
200
|
message: "YSS implementation contract compiler stage 7 scenarios passed",
|
|
@@ -248,7 +250,10 @@ export function runScenario(name) {
|
|
|
248
250
|
{ from: "work-unit.spec-synthesis", to: "work-unit.slice-implementation" },
|
|
249
251
|
{ from: "work-unit.prototype-design", to: "work-unit.slice-implementation" },
|
|
250
252
|
{ from: "work-unit.technical-analysis", to: "work-unit.slice-implementation" },
|
|
251
|
-
|
|
253
|
+
{ from: "work-unit.technical-analysis", to: "work-unit.ticket-decomposition" },
|
|
254
|
+
]), "生命周期转换图缺少工程准备、Ticket 正式化与实现越级阻断");
|
|
255
|
+
ensure(contract.transition_graph?.routes?.["work-unit.implementation-repository-preparation"]?.includes("work-unit.ticket-decomposition"), "实现仓库准备未成为 Ticket 正式化前置");
|
|
256
|
+
ensure(contract.implementation_repository_preparation?.gate === "gate.implementation-repositories-ready", "实现仓库准备聚合门禁缺失");
|
|
252
257
|
ensure(lifecycleTransitionContract.next_routes["work-unit.ticket-decomposition"]?.includes("work-unit.slice-implementation"), "转换校验器未允许 Ticket 正式化后进入实现");
|
|
253
258
|
ensure(contract.release_readiness?.conditional?.ui_impact?.includes("gate.frontend-implementation-verified") && contract.frontend_implementation_plan?.acceptance?.includes("no_template_placeholders"), "发布公式或前端计划实质校验不完整");
|
|
254
259
|
const templateRejected = spawnSync("scripts/verify-frontend-implementation-evidence", ["docs/process/templates/frontend-implementation-plan-template.yaml"], { cwd: root, encoding: "utf8" });
|
|
@@ -264,7 +269,9 @@ export function runScenario(name) {
|
|
|
264
269
|
process.on("exit", () => rmSync(decisionTemp, { recursive: true, force: true }));
|
|
265
270
|
const specDecision = buildDecisionFixture(path.join(decisionTemp, "spec"));
|
|
266
271
|
const implementationDecision = buildImplementationFixture(path.join(decisionTemp, "implementation"), "docs/.scratch/demo/issues/01-valid-slice.md");
|
|
272
|
+
const planFixture = buildPlanFixture(path.join(decisionTemp, 'plan'));
|
|
267
273
|
const validResult = {
|
|
274
|
+
...planFixture.state,
|
|
268
275
|
user_decisions: [specDecision.requirement],
|
|
269
276
|
result_schema: "workflow-execution-result-v1",
|
|
270
277
|
work_unit: "work-unit.spec-synthesis",
|
|
@@ -275,10 +282,10 @@ export function runScenario(name) {
|
|
|
275
282
|
changed_artifacts: [],
|
|
276
283
|
new_impacts: [],
|
|
277
284
|
stale_candidates: [],
|
|
278
|
-
next_route: "work-unit.
|
|
285
|
+
next_route: "work-unit.implementation-repository-preparation",
|
|
279
286
|
blocking_signals: []
|
|
280
287
|
};
|
|
281
|
-
validateWorkflowExecutionResult(validResult, data.workflow_execution_result, data.work_unit_routes);
|
|
288
|
+
validateWorkflowExecutionResult(validResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
|
|
282
289
|
const validTicketResult = {
|
|
283
290
|
...validResult,
|
|
284
291
|
work_unit: "work-unit.ticket-decomposition",
|
|
@@ -286,7 +293,7 @@ export function runScenario(name) {
|
|
|
286
293
|
ticket_decomposition_result_ref: "docs/.scratch/demo/evidence/ticket-decomposition-result.yaml",
|
|
287
294
|
vertical_slice_ticket_ref: "docs/.scratch/demo/issues/01-valid-slice.md",
|
|
288
295
|
};
|
|
289
|
-
validateWorkflowExecutionResult(validTicketResult, data.workflow_execution_result, data.work_unit_routes);
|
|
296
|
+
validateWorkflowExecutionResult(validTicketResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
|
|
290
297
|
const validImplementationResult = {
|
|
291
298
|
...validResult,
|
|
292
299
|
...implementationDecision.state,
|
|
@@ -304,8 +311,16 @@ export function runScenario(name) {
|
|
|
304
311
|
slice_contract_status: "approved",
|
|
305
312
|
slice_contract_persisted: true,
|
|
306
313
|
slice_contract_current_version: true,
|
|
314
|
+
delivery_impacts: { backend: true, frontend: false },
|
|
315
|
+
implementation_repository_preparation: {
|
|
316
|
+
result: "completed", current_version: true, evidence_refs: ["docs/process/lifecycle-registry.yaml"],
|
|
317
|
+
projects: [
|
|
318
|
+
{ project_id: "backend", delivery_role: "backend", status: "existing-and-onboarded", repository_ref: "git://backend", project_root: "/workspace/backend", repository_scope: "external-repository", onboarding_result: { status: "completed", ref: "docs/process/lifecycle-registry.yaml" } },
|
|
319
|
+
{ project_id: "frontend-na", delivery_role: "frontend", status: "not-applicable", reason: "no frontend impact" },
|
|
320
|
+
],
|
|
321
|
+
},
|
|
307
322
|
};
|
|
308
|
-
validateWorkflowExecutionResult(validImplementationResult, data.workflow_execution_result, data.work_unit_routes);
|
|
323
|
+
validateWorkflowExecutionResult(validImplementationResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
|
|
309
324
|
for (const mutate of [
|
|
310
325
|
(item) => { item.vertical_slice_ticket_role = "ready-for-human"; },
|
|
311
326
|
(item) => { item.vertical_slice_ticket_kind = "parent-ticket"; },
|
|
@@ -317,22 +332,22 @@ export function runScenario(name) {
|
|
|
317
332
|
]) {
|
|
318
333
|
const invalid = structuredClone(validImplementationResult); mutate(invalid);
|
|
319
334
|
let rejected = false;
|
|
320
|
-
try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes); } catch { rejected = true; }
|
|
335
|
+
try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { rejected = true; }
|
|
321
336
|
ensure(rejected, "实现 Workflow Execution Result 的 Ticket 语义变异未被拒绝");
|
|
322
337
|
}
|
|
323
338
|
const unavailableResult = structuredClone(validResult);
|
|
324
339
|
unavailableResult.result = "blocked";
|
|
325
340
|
unavailableResult.unavailable_skill = { skill: "yss-ui", provider: "codex", fallback: "manual-review", resolution: "needs-human" };
|
|
326
341
|
unavailableResult.blocking_signals = ["missing_evidence"];
|
|
327
|
-
validateWorkflowExecutionResult(unavailableResult, data.workflow_execution_result, data.work_unit_routes);
|
|
342
|
+
validateWorkflowExecutionResult(unavailableResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
|
|
328
343
|
const malformedUnavailable = structuredClone(unavailableResult);
|
|
329
344
|
delete malformedUnavailable.unavailable_skill.fallback;
|
|
330
345
|
let unavailableRejected = false;
|
|
331
|
-
try { validateWorkflowExecutionResult(malformedUnavailable, data.workflow_execution_result, data.work_unit_routes); } catch { unavailableRejected = true; }
|
|
346
|
+
try { validateWorkflowExecutionResult(malformedUnavailable, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { unavailableRejected = true; }
|
|
332
347
|
ensure(unavailableRejected, "技能不可用结果缺少 fallback 时未被拒绝");
|
|
333
348
|
const compatibleResult = structuredClone(validResult);
|
|
334
349
|
compatibleResult.workflow_reference = { source: "mattpocock/skills", skill: "to-spec", invocation_mode: "reference" };
|
|
335
|
-
validateWorkflowExecutionResult(compatibleResult, data.workflow_execution_result, data.work_unit_routes);
|
|
350
|
+
validateWorkflowExecutionResult(compatibleResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
|
|
336
351
|
for (const mutate of [
|
|
337
352
|
(item) => { delete item.workflow_reference; },
|
|
338
353
|
(item) => { delete item.context_reconciliation; },
|
|
@@ -348,7 +363,7 @@ export function runScenario(name) {
|
|
|
348
363
|
]) {
|
|
349
364
|
const invalid = structuredClone(validResult); mutate(invalid);
|
|
350
365
|
let rejected = false;
|
|
351
|
-
try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes); } catch { rejected = true; }
|
|
366
|
+
try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { rejected = true; }
|
|
352
367
|
ensure(rejected, "Workflow Execution Result 完成态变异未被拒绝");
|
|
353
368
|
}
|
|
354
369
|
let metadataRejected = false;
|
|
@@ -377,16 +392,7 @@ export function runScenario(name) {
|
|
|
377
392
|
ensure(rejected, "Matt/YSS 契约变异未被 baseline oracle 拒绝");
|
|
378
393
|
}
|
|
379
394
|
const skill = read(".agents/skills/yss-product-lifecycle/SKILL.md");
|
|
380
|
-
|
|
381
|
-
const orchestration = read(".agents/skills/yss-product-lifecycle/references/orchestration.md");
|
|
382
|
-
validateMattProse(skill, adapter);
|
|
383
|
-
validateInvocationProse(skill, adapter, orchestration);
|
|
384
|
-
let proseRejected = false;
|
|
385
|
-
try { validateMattProse(skill.replace("任何写入前回交本编排器", "允许直接写入"), adapter); } catch { proseRejected = true; }
|
|
386
|
-
ensure(proseRejected, "Matt/YSS prose 变异未被 baseline oracle 拒绝");
|
|
387
|
-
let invocationProseRejected = false;
|
|
388
|
-
try { validateInvocationProse(skill.replace("不得自动调用它们或代替其创建正式资产", "可以自动调用并创建正式资产"), adapter, orchestration); } catch { invocationProseRejected = true; }
|
|
389
|
-
ensure(invocationProseRejected, "调用边界 prose 变异未被 baseline oracle 拒绝");
|
|
395
|
+
validateLifecycleEntrySkill(skill);
|
|
390
396
|
for (const relative of ["SKILL.md", "references/matt-yss-adapter.md", "references/orchestration-contract.yaml"]) {
|
|
391
397
|
ensure(read(`.agents/skills/yss-product-lifecycle/${relative}`) === read(`.codex/skills/yss-product-lifecycle/${relative}`), `YSS 生命周期投影未同步: ${relative}`);
|
|
392
398
|
}
|
|
@@ -166,6 +166,10 @@ function validateReviewInputFinding(reviewInput) {
|
|
|
166
166
|
if (reviewInput.completed_requires_no_open_mandatory_violations !== true) fail("未关闭的 mandatory violation 不得 completed");
|
|
167
167
|
if (reviewInput.completed_requires_no_blank_applicable_rows !== true) fail("适用报告行空白不得 completed");
|
|
168
168
|
if (reviewInput.reviewer_write_implementation !== "forbidden") fail("review_input 禁止审查者写实现");
|
|
169
|
+
requireObject(reviewInput.scope_resolution, "review_input.scope_resolution");
|
|
170
|
+
requireStringSet(reviewInput.scope_resolution.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"], "review_input.scope_resolution.sources");
|
|
171
|
+
requireStringSet(reviewInput.scope_resolution.backend_includes, ["project-itself", "registered-backend-development-projects"], "review_input.scope_resolution.backend_includes");
|
|
172
|
+
requireStringSet(reviewInput.scope_resolution.excludes, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"], "review_input.scope_resolution.excludes");
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
function validateCodeReviewRoute(route, resolve) {
|
|
@@ -180,6 +184,11 @@ function validateCodeReviewRoute(route, resolve) {
|
|
|
180
184
|
if (standards.contract_required_skills !== "required") fail("Standards 必须消费 Slice 合同 required_skills");
|
|
181
185
|
requireString(standards.report_template, "review_standards_route.report_template");
|
|
182
186
|
if (!existsSync(path.join(ROOT, standards.report_template))) fail(`审查报告模板不存在: ${standards.report_template}`);
|
|
187
|
+
requireObject(standards.project_scope, "review_standards_route.project_scope");
|
|
188
|
+
requireStringSet(standards.project_scope.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"], "review_standards_route.project_scope.sources");
|
|
189
|
+
requireStringSet(standards.project_scope.include, ["project-itself", "registered-backend-development-projects"], "review_standards_route.project_scope.include");
|
|
190
|
+
requireStringSet(standards.project_scope.exclude, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"], "review_standards_route.project_scope.exclude");
|
|
191
|
+
if (standards.project_scope.fixed_apps_backend_assumption !== "forbidden") fail("code-review 不得把后端审查范围固定为 apps/backend");
|
|
183
192
|
const conditional = standards.conditional_skills;
|
|
184
193
|
if (!conditional || typeof conditional !== "object" || Array.isArray(conditional)) {
|
|
185
194
|
fail("review_standards_route.conditional_skills 必须是对象");
|
|
@@ -117,7 +117,16 @@ function loadStrategicDesignSkillManifest() {
|
|
|
117
117
|
return validateStrategicDesignSkillManifest(JSON.parse(readFileSync(STRATEGIC_DESIGN_MANIFEST_PATH, "utf8")));
|
|
118
118
|
}
|
|
119
119
|
function git(args) { return spawnSync("git", args, { cwd: ROOT, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }); }
|
|
120
|
-
function
|
|
120
|
+
function trackedPaths() {
|
|
121
|
+
const result = git(["ls-files", "-z"]);
|
|
122
|
+
if (result.status !== 0) throw new TypeError("无法读取 Git 受跟踪路径");
|
|
123
|
+
const paths = new Set();
|
|
124
|
+
for (const file of result.stdout.split("\0").filter(Boolean)) {
|
|
125
|
+
let ref = file;
|
|
126
|
+
while (ref !== ".") { paths.add(ref); ref = path.posix.dirname(ref); }
|
|
127
|
+
}
|
|
128
|
+
return paths;
|
|
129
|
+
}
|
|
121
130
|
function parseLock() { return existsSync(LOCK_PATH) ? JSON.parse(readFileSync(LOCK_PATH, "utf8")) : null; }
|
|
122
131
|
function sharedFromLock(lock) {
|
|
123
132
|
const shared = lock?.version === 3 && lock.skills?.shared;
|
|
@@ -137,6 +146,13 @@ export function unlockedCanonicalEntries(names, allowedNames, hasSkillMd = () =>
|
|
|
137
146
|
return names.filter((name) => !allowed.has(name) && !OBSOLETE.has(name) && hasSkillMd(name)).sort();
|
|
138
147
|
}
|
|
139
148
|
export function syncSkills({ check = false } = {}) {
|
|
149
|
+
let trackedSet;
|
|
150
|
+
const tracked = ref => (trackedSet ??= trackedPaths()).has(ref);
|
|
151
|
+
const sourceHashes = new Map();
|
|
152
|
+
const sourceHash = source => {
|
|
153
|
+
if (!sourceHashes.has(source)) sourceHashes.set(source, treeHash(source));
|
|
154
|
+
return sourceHashes.get(source);
|
|
155
|
+
};
|
|
140
156
|
const lock = parseLock();
|
|
141
157
|
const shared = sharedFromLock(lock);
|
|
142
158
|
const absent = shared.filter((name) => !lstatSafe(path.join(SOURCE_ROOT, name))?.isDirectory());
|
|
@@ -162,7 +178,7 @@ export function syncSkills({ check = false } = {}) {
|
|
|
162
178
|
if (info?.isSymbolicLink()) {
|
|
163
179
|
if (!existsSync(target) || realpathSync(target) !== realpathSync(source)) drift.push(`projection target mismatch: ${relative(target)}`);
|
|
164
180
|
} else if (!info?.isDirectory()) drift.push(`missing projection: ${relative(target)}`);
|
|
165
|
-
else if (
|
|
181
|
+
else if (sourceHash(source) !== treeHash(target)) drift.push(`projection drift: ${relative(target)}`);
|
|
166
182
|
} else if (info?.isSymbolicLink() && existsSync(target) && realpathSync(target) === realpathSync(source)) {
|
|
167
183
|
continue;
|
|
168
184
|
} else {
|
|
@@ -3,6 +3,7 @@ import { existsSync, lstatSync, readdirSync, readFileSync, mkdirSync, writeFileS
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { validateJsonSchemas } from './json-schema.mjs';
|
|
6
7
|
import { parseDocument } from '../vendor/yaml.mjs';
|
|
7
8
|
export const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
8
9
|
export const ensure = (condition, message) => { if (!condition) throw new TypeError(message); };
|
|
@@ -50,11 +51,11 @@ export function project(root) {
|
|
|
50
51
|
ensure(value.schema_version === 1 && value.repository_mode === 'project-instance', '只允许 project-instance 导出或导入业务包');
|
|
51
52
|
return realpathSync(root);
|
|
52
53
|
}
|
|
53
|
-
export function
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
ensure(out.status === 0, `schema 校验失败: ${out.error?.message || out.stdout || out.stderr}`);
|
|
54
|
+
export function schemaBatch(items) {
|
|
55
|
+
const results = validateJsonSchemas(items.map(([value, ref]) => ({ value, schemaPath: safe(ROOT, ref), formatChecker: false, errorStyle: 'verbose' })));
|
|
56
|
+
for (const result of results) ensure(result.valid, `schema 校验失败: ${result.error}\n`);
|
|
57
57
|
}
|
|
58
|
+
export function schema(value, ref) { schemaBatch([[value, ref]]); }
|
|
58
59
|
export function archive(command, source, destination) {
|
|
59
60
|
const out = spawnSync('python3', [path.join(ROOT, 'scripts/lib/strategic-handoff-zip.py'), command, source, destination], { encoding: 'utf8' });
|
|
60
61
|
ensure(out.status === 0, `ZIP 操作失败: ${out.error?.message || out.stderr}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, lstatSync, readFileSync, mkdirSync, mkdtempSync, renameSync, rmSync, cpSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
|
-
import { ensure, canonical, digest, hash, json, parse, read, safe, relative, files, write, project, schema, archive, ROOT, sourceApprovalPolicy } from './strategic-handoff-io.mjs';
|
|
4
|
+
import { ensure, canonical, digest, hash, json, parse, read, safe, relative, files, write, project, schema, schemaBatch, archive, ROOT, sourceApprovalPolicy } from './strategic-handoff-io.mjs';
|
|
5
5
|
import { parseContextSource, parseContextContract, resolveContextTermRefs } from './context-contract.mjs';
|
|
6
6
|
import { countersignRuleForGate } from './digital-human-roles.mjs';
|
|
7
7
|
import { validateApprovalRecord } from './approval-record.mjs';
|
|
@@ -91,8 +91,7 @@ export async function inspectSource(root, handoffRef) {
|
|
|
91
91
|
snapshot(handoff.source_context_snapshot,source); checkDelta(handoff,source);
|
|
92
92
|
const strategy=read(safe(root,handoff.source.domain_strategy_ref.persisted_ref));
|
|
93
93
|
const stage=read(safe(root,handoff.source.stage_decision_package_ref.persisted_ref));
|
|
94
|
-
|
|
95
|
-
schema(stage,'docs/process/schemas/strategic-handoff-stage-decision-package.schema.json');
|
|
94
|
+
schemaBatch([[strategy,'docs/process/schemas/strategic-handoff-domain-strategy.schema.json'],[stage,'docs/process/schemas/strategic-handoff-stage-decision-package.schema.json']]);
|
|
96
95
|
snapshot(strategy.context_snapshot,source); snapshot(stage.context_snapshot,source);
|
|
97
96
|
ensure(strategy.status==='approved' && stage.status==='approved', '战略合同/方案决策包尚未批准');
|
|
98
97
|
ensure(strategy.domain_strategy_id===handoff.source.domain_strategy_ref.id && strategy.domain_version===handoff.source.domain_strategy_ref.version, '战略身份/版本不一致');
|
|
@@ -141,21 +140,22 @@ function collect(root, handoffRef, handoff, config) {
|
|
|
141
140
|
if(Array.isArray(value)) { if(key==='evidence_refs') value.forEach(enqueue); else value.forEach(v=>refs(v,key)); }
|
|
142
141
|
else if(value && typeof value==='object') for(const [k,v]of Object.entries(value)) { if(['approval_ref','persisted_ref','user_decision_ref'].includes(k)&&typeof v==='string')enqueue(v); else if(k==='ref'&&typeof v==='string'&&!/^[a-z]+:\/\//i.test(v))enqueue(v); else refs(v,k); }
|
|
143
142
|
}
|
|
143
|
+
let totalBytes = 0;
|
|
144
144
|
while(queue.length) {
|
|
145
145
|
const ref=symbolic[queue[0]]||queue[0]; queue.shift(); if(/^https?:\/\//i.test(ref))continue; relative(ref);
|
|
146
146
|
if(collected.has(ref))continue;
|
|
147
147
|
const full=safe(root,ref),stat=lstatSync(full);
|
|
148
148
|
if(stat.isDirectory()) { queue.push(...files(root,ref)); continue; }
|
|
149
149
|
ensure(stat.isFile() && stat.size<=MAX_BYTES,`源文件类型/大小无效: ${ref}`);
|
|
150
|
-
const bytes=readFileSync(full); collected.set(ref,bytes);
|
|
151
|
-
ensure(collected.size<=20000 &&
|
|
150
|
+
const bytes=readFileSync(full); collected.set(ref,bytes); totalBytes += bytes.length;
|
|
151
|
+
ensure(collected.size<=20000 && totalBytes<=MAX_BYTES,'交接包大小超限');
|
|
152
152
|
if(/\.(yaml|yml|json)$/.test(ref))refs(parse(bytes));
|
|
153
153
|
queue.push(...documentLinks(ref,bytes));
|
|
154
154
|
}
|
|
155
155
|
return collected;
|
|
156
156
|
}
|
|
157
|
-
function materialize(
|
|
158
|
-
for(const file of manifest.files.filter(x=>x.original_ref))write(destination,file.original_ref,
|
|
157
|
+
function materialize(captured, manifest, destination) {
|
|
158
|
+
for(const file of manifest.files.filter(x=>x.original_ref))write(destination,file.original_ref,captured.get(file.path));
|
|
159
159
|
}
|
|
160
160
|
export async function openBundle(input, action) {
|
|
161
161
|
const temp=mkdtempSync(path.join(tmpdir(),'yss-handoff-'));
|
|
@@ -170,10 +170,11 @@ export async function openBundle(input, action) {
|
|
|
170
170
|
ensure(new Set(paths.map(x=>x.toLowerCase())).size===paths.length,'包文件路径重复');
|
|
171
171
|
ensure(own([...paths,'manifest.json'].sort(),files(root).sort()),'包文件缺失或存在未登记文件');
|
|
172
172
|
ensure(manifest.files.length<=20000 && manifest.files.reduce((n,f)=>n+f.size_bytes,0)<=MAX_BYTES,'包大小超限');
|
|
173
|
-
|
|
173
|
+
const captured = new Map();
|
|
174
|
+
for(const file of manifest.files){const bytes=readFileSync(safe(root,file.path));ensure(bytes.length===file.size_bytes && hash(bytes)===file.sha256,`文件摘要不一致: ${file.path}`);if(file.original_ref)relative(file.original_ref);captured.set(file.path,bytes);}
|
|
174
175
|
const originals=manifest.files.filter(x=>x.original_ref).map(x=>x.original_ref);
|
|
175
176
|
ensure(new Set(originals.map(x=>x.toLowerCase())).size===originals.length,'源路径重复');
|
|
176
|
-
const source=path.join(temp,'source');mkdirSync(source);materialize(
|
|
177
|
+
const source=path.join(temp,'source');mkdirSync(source);materialize(captured,manifest,source);
|
|
177
178
|
const inspected=await inspectSource(source,manifest.handoff_ref);
|
|
178
179
|
ensure(manifest.bundle_id===inspected.handoff.handoff_id && manifest.version===inspected.handoff.handoff_version,'包身份与源交接不一致');
|
|
179
180
|
ensure(own(read(safe(root,'indexes/rules.json')),inspected.indexes.rules) && own(read(safe(root,'indexes/scenarios.json')),inspected.indexes.scenarios),'规则/场景索引与源资产不一致');
|
|
@@ -6,6 +6,7 @@ import { loadRegistry, ROOT } from "./lifecycle-registry.mjs";
|
|
|
6
6
|
import { loadMaintenanceCheckpoint, validateMaintenanceCheckpoint } from "./maintenance-intensity.mjs";
|
|
7
7
|
import { assertImplementationDecision } from "./user-decision.mjs";
|
|
8
8
|
import { validateNextRoute } from "./lifecycle-transition.mjs";
|
|
9
|
+
import { assertPlanSpecEntry } from "./plan-spec-entry.mjs";
|
|
9
10
|
import { enforceHarnessTaskScope } from "./harness-execution-scope.mjs";
|
|
10
11
|
import { enforceFrontendDelivery } from "./frontend-delivery-boundary.mjs";
|
|
11
12
|
import { LEGACY_TASK_PACKAGE_SCHEMA, TASK_PACKAGE_SCHEMA, validateTaskPackageSchema } from "./task-package-schema.mjs";
|
|
@@ -59,6 +60,7 @@ function validateSkillSource(value, registry) {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
function validateCommon(value, registry, lifecycle) {
|
|
63
|
+
if (value.work_unit_id === 'work-unit.spec-synthesis') assertPlanSpecEntry(value);
|
|
62
64
|
const workUnit = lifecycle.work_units.find((item) => item.id === value.work_unit_id);
|
|
63
65
|
if (!workUnit && value.contract.kind !== "slice-implementation") fail(`未知 work_unit_id: ${value.work_unit_id}`);
|
|
64
66
|
const roleDefaults = taskPackageDefaults(value.role_id, registry);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runCommandSync } from "./command-runner.mjs";
|
|
1
2
|
import { spawnSync } from "node:child_process";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
4
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -7,13 +8,14 @@ import { ROOT } from "./template-verification.mjs";
|
|
|
7
8
|
|
|
8
9
|
function fail(message) { throw new TypeError(message); }
|
|
9
10
|
function ensure(condition, message) { if (!condition) fail(message); }
|
|
10
|
-
function git(args, cwd) {
|
|
11
|
-
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
12
|
-
if (result.status !== 0) fail(result.stderr.trim() || `git ${args.join(" ")} 执行失败`);
|
|
11
|
+
function git(args, cwd, timeoutMs = 0, cleanupPathsOnFailure = []) {
|
|
12
|
+
const result = args.includes("fetch") ? runCommandSync("git", args, { cwd, timeoutMs, progress: true, cleanupPathsOnFailure }) : spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
13
|
+
if (result.status !== 0) fail(result.termination || result.error?.message || result.stderr.trim() || `git ${args.join(" ")} 执行失败`);
|
|
13
14
|
return result.stdout.trim();
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
export function acquireTemplateCommit({ repository, commit, cacheRoot = path.join(ROOT, ".template-source/cache/remote-templates"), allowLocal = false }) {
|
|
17
|
+
export function acquireTemplateCommit({ repository, commit, cacheRoot = path.join(ROOT, ".template-source/cache/remote-templates"), allowLocal = false, timeoutMs = 0 }) {
|
|
18
|
+
ensure(Number.isFinite(timeoutMs) && timeoutMs >= 0, "timeoutMs 必须是非负毫秒数");
|
|
17
19
|
ensure(typeof repository === "string" && repository.trim(), "repository 不能为空");
|
|
18
20
|
ensure(/^[a-f0-9]{40}$/.test(commit), "模板 ref 必须是 40 位 commit");
|
|
19
21
|
if (!allowLocal) ensure(/^(?:https?:\/\/|ssh:\/\/|git@)/.test(repository), "正式模板缓存只接受远程 repository URL");
|
|
@@ -35,7 +37,7 @@ export function acquireTemplateCommit({ repository, commit, cacheRoot = path.joi
|
|
|
35
37
|
try {
|
|
36
38
|
const temporaryRepository = path.join(temporary, "repository.git");
|
|
37
39
|
git(["init", "--bare", "-q", temporaryRepository], ROOT);
|
|
38
|
-
git(["--git-dir", temporaryRepository, "fetch", "--depth=1", "--no-tags", repository, commit], ROOT);
|
|
40
|
+
git(["--git-dir", temporaryRepository, "fetch", "--depth=1", "--no-tags", repository, commit], ROOT, timeoutMs, [temporary]);
|
|
39
41
|
const actual = git(["--git-dir", temporaryRepository, "rev-parse", "FETCH_HEAD^{commit}"], ROOT);
|
|
40
42
|
ensure(actual === commit, `远程返回 commit 与请求不一致: ${actual}`);
|
|
41
43
|
writeFileSync(path.join(temporary, "metadata.json"), `${JSON.stringify({ schema_version: 1, key, repository, commit })}\n`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { queryLifecycleContext } from "./lib/lifecycle-context-query.mjs";
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
const { values } = parseArgs({
|
|
7
|
+
options: {
|
|
8
|
+
mode: { type: "string" },
|
|
9
|
+
stage: { type: "string" },
|
|
10
|
+
"work-unit": { type: "string" },
|
|
11
|
+
include: { type: "string", multiple: true },
|
|
12
|
+
},
|
|
13
|
+
strict: true,
|
|
14
|
+
});
|
|
15
|
+
const result = queryLifecycleContext({
|
|
16
|
+
mode: values.mode,
|
|
17
|
+
stageId: values.stage,
|
|
18
|
+
workUnitId: values["work-unit"],
|
|
19
|
+
include: values.include ?? [],
|
|
20
|
+
});
|
|
21
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
process.stderr.write(`${error.message}\n`);
|
|
24
|
+
process.exitCode = 1;
|
|
25
|
+
}
|
|
@@ -23,12 +23,18 @@ function collectChangedFiles(base) {
|
|
|
23
23
|
function runCommand(command) {
|
|
24
24
|
return new Promise((resolve) => {
|
|
25
25
|
const started = Date.now();
|
|
26
|
+
process.stderr.write(`[开始] ${command}\n`);
|
|
26
27
|
const child = spawn(command, { cwd: ROOT, shell: true, env: process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
27
28
|
let stdout = "";
|
|
28
29
|
let stderr = "";
|
|
29
30
|
child.stdout.on("data", (chunk) => { stdout += chunk; });
|
|
30
31
|
child.stderr.on("data", (chunk) => { stderr += chunk; });
|
|
31
|
-
child.on("
|
|
32
|
+
child.on("error", error => { stderr += `${error.message}\n`; });
|
|
33
|
+
child.on("close", (code) => {
|
|
34
|
+
const duration_ms = Date.now() - started;
|
|
35
|
+
process.stderr.write(`[${code === 0 ? "完成" : "失败"}] ${command} (${duration_ms}ms, exit=${code ?? 1})\n`);
|
|
36
|
+
resolve({ command, code: code ?? 1, duration_ms, stdout, stderr });
|
|
37
|
+
});
|
|
32
38
|
});
|
|
33
39
|
}
|
|
34
40
|
|
|
@@ -106,8 +112,8 @@ try {
|
|
|
106
112
|
const concurrency = Number(values.concurrency || plan.max_concurrency);
|
|
107
113
|
if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > 4) throw new TypeError("concurrency 必须为 1..4");
|
|
108
114
|
|
|
109
|
-
process.
|
|
110
|
-
if (plan.escalation_reason) process.
|
|
115
|
+
process.stderr.write(`模板核验 profile: ${plan.requested_profile} -> ${plan.effective_profile}\n`);
|
|
116
|
+
if (plan.escalation_reason) process.stderr.write(`自动升级原因: ${plan.escalation_reason}\n`);
|
|
111
117
|
const groups = await runGroups(plan, modeResult.stdout.trim(), concurrency);
|
|
112
118
|
printResults(groups);
|
|
113
119
|
const failed = groups.flatMap((group) => group.results).find((result) => result.code !== 0);
|
|
@@ -7,10 +7,19 @@ const root=path.resolve(import.meta.dirname,'..');
|
|
|
7
7
|
const check=process.argv.includes('--check');
|
|
8
8
|
const targets=['submodules/yss-harness-design-agent','submodules/yss-harness-dev-agent','submodules/yss-harness-backend-agent','submodules/yss-harness-frontend-agent'];
|
|
9
9
|
const shared=['scripts/strategic-handoff','scripts/verify-strategic-handoff-consumption','scripts/verify-strategic-handoff-package-scenarios','scripts/verify-strategic-context-import','scripts/verify-strategic-context-import-scenarios','scripts/lib/context-contract.mjs','docs/process/strategic-handoff-package.md','docs/process/schemas/strategic-design-handoff.schema.json',...readdirSync(path.join(root,'scripts/lib')).filter(x=>x.startsWith('strategic-handoff-')||x==='strategic-handoff.mjs').map(x=>`scripts/lib/${x}`),...readdirSync(path.join(root,'docs/process/schemas')).filter(x=>x.startsWith('strategic-handoff-')).map(x=>`docs/process/schemas/${x}`),...readdirSync(path.join(root,'scripts/fixtures/strategic-handoff')).map(x=>`scripts/fixtures/strategic-handoff/${x}`)];
|
|
10
|
+
shared.push('scripts/lib/command-runner.mjs','scripts/lib/json-schema.mjs','scripts/lib/context-reconciliation.mjs','scripts/verify-context-reconciliation');
|
|
10
11
|
shared.push('scripts/instantiate-harness','scripts/backend-delivery','scripts/verify-frontend-delivery','scripts/lib/backend-delivery.mjs','scripts/lib/frontend-delivery.mjs','scripts/lib/frontend-delivery-boundary.mjs','docs/process/frontend-backend-delivery.md','docs/process/schemas/backend-delivery.schema.json','docs/process/schemas/backend-delivery-verification.schema.json','docs/process/schemas/frontend-delivery-acceptance.schema.json');
|
|
11
12
|
let differences=[];
|
|
12
13
|
// 专职执行范围由各模板持有;后端只消费 wire 校验器,不恢复原型构建技能。
|
|
13
14
|
function sync(source,dest){let bytes=readFileSync(source);if(dest.includes('/yss-harness-backend-agent/')){let content=bytes.toString();if(dest.endsWith('/scripts/lib/strategic-handoff.mjs'))content=content.replace('../../.agents/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs','./visual-baseline-contract.mjs');if(dest.endsWith('/scripts/fixtures/strategic-handoff/fixture.mjs'))content=content.replace('../../../.agents/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs','../../lib/visual-baseline-contract.mjs');bytes=Buffer.from(content);}if(!existsSync(dest)||!bytes.equals(readFileSync(dest))){differences.push(path.relative(root,dest));if(!check){mkdirSync(path.dirname(dest),{recursive:true});writeFileSync(dest,bytes);}}if(!check&&path.basename(path.dirname(dest))==='scripts'&&!path.extname(dest))chmodSync(dest,0o755);}
|
|
15
|
+
// CLI core owns the portable external-command runner; all runtime copies are generated here.
|
|
16
|
+
sync(path.join(root,'.template-source/cli-core/command-runner.mjs'),path.join(root,'scripts/lib/command-runner.mjs'));
|
|
17
|
+
for(const name of ['create-yss-spec','create-yss-strategic-design','create-yss-harness-dev']) {
|
|
18
|
+
const target=`submodules/${name}`;
|
|
19
|
+
if(!existsSync(path.join(root,target,'.git')))continue;
|
|
20
|
+
if(!check){const state=inspectWorkingTreeScope(root,{project_root:target,repository_scope:'git-submodule',checkout_state:'attached-branch'});if(!state.writable)throw new Error(`${target}: ${state.violation}`);}
|
|
21
|
+
sync(path.join(root,'.template-source/cli-core/command-runner.mjs'),path.join(root,target,'src/command-runner.mjs'));
|
|
22
|
+
}
|
|
14
23
|
for(const kind of ['domain-strategy','stage-decision-package'])sync(path.join(root,`.agents/skills/yss-stage-decision/references/${kind}.schema.json`),path.join(root,`docs/process/schemas/strategic-handoff-${kind}.schema.json`));
|
|
15
24
|
for(const target of targets){
|
|
16
25
|
if(!existsSync(path.join(root,target,'.git')))continue;
|
|
@@ -25,13 +25,6 @@ for (const relativePath of PUBLIC_FILES) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const lifecycle = read(".agents/skills/yss-product-lifecycle/SKILL.md");
|
|
29
|
-
for (const phrase of [
|
|
30
|
-
"机会与目标 → 业务故事 → 责任与交接 → 规则、例子与疑问 → 可验收需求 → 页面验证 → 业务任务 → 交接研发",
|
|
31
|
-
"业务方案总览",
|
|
32
|
-
"不成为新的事实源",
|
|
33
|
-
]) assert.match(lifecycle, new RegExp(phrase));
|
|
34
|
-
|
|
35
28
|
const registry = read("docs/process/lifecycle-registry.yaml");
|
|
36
29
|
for (const stableId of ["work-unit.domain-strategy-design", "artifact.domain-strategy", "gate.domain-strategy-approved"]) {
|
|
37
30
|
assert.match(registry, new RegExp(`id: ${stableId.replaceAll(".", "\\.")}`));
|
|
@@ -1,56 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { spawnSync } from "node:child_process";
|
|
5
2
|
import { parseArgs } from "node:util";
|
|
6
|
-
import {
|
|
7
|
-
import { parseDocument } from "./vendor/yaml.mjs";
|
|
8
|
-
import { resolveContextTermRefs, verifyContextSnapshot } from "./lib/context-contract.mjs";
|
|
9
|
-
|
|
10
|
-
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const schemaPath = path.join(repoRoot, "docs/process/schemas/context-reconciliation.schema.json");
|
|
12
|
-
const pythonValidator = String.raw`
|
|
13
|
-
import json, sys
|
|
14
|
-
from jsonschema import Draft202012Validator
|
|
15
|
-
schema = json.load(open(sys.argv[1], encoding="utf-8"))
|
|
16
|
-
value = json.load(sys.stdin)
|
|
17
|
-
errors = sorted(Draft202012Validator(schema).iter_errors(value), key=lambda error: list(error.absolute_path))
|
|
18
|
-
for error in errors:
|
|
19
|
-
where = ".".join(str(part) for part in error.absolute_path) or "<root>"
|
|
20
|
-
print(f"{where}: {error.message}", file=sys.stderr)
|
|
21
|
-
sys.exit(1 if errors else 0)
|
|
22
|
-
`;
|
|
23
|
-
|
|
24
|
-
function parseFile(file) {
|
|
25
|
-
const document = parseDocument(readFileSync(file, "utf8"), { maxAliasCount: 0, uniqueKeys: true });
|
|
26
|
-
if (document.errors.length) throw new TypeError(document.errors[0].message);
|
|
27
|
-
return document.toJS({ maxAliasCount: 0 });
|
|
28
|
-
}
|
|
29
|
-
|
|
3
|
+
import { verifyContextReconciliation } from "./lib/context-reconciliation.mjs";
|
|
30
4
|
try {
|
|
31
5
|
const { values, positionals } = parseArgs({ options: { root: { type: "string", default: process.cwd() } }, allowPositionals: true, strict: true });
|
|
32
6
|
if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-context-reconciliation [--root <repo>] <record.yaml|json>");
|
|
33
|
-
|
|
34
|
-
const file = path.resolve(positionals[0]);
|
|
35
|
-
const value = parseFile(file);
|
|
36
|
-
const schemaResult = spawnSync("python3", ["-c", pythonValidator, schemaPath], { encoding: "utf8", input: JSON.stringify(value) });
|
|
37
|
-
if (schemaResult.status !== 0) throw new TypeError(`${schemaResult.stdout}${schemaResult.stderr}`.trim());
|
|
38
|
-
const manifest = parseFile(path.join(root, "yss-project.yaml"));
|
|
39
|
-
if (value.repository_mode !== manifest.repository_mode) throw new TypeError("repository_mode 必须与根目录 yss-project.yaml 一致");
|
|
40
|
-
const contract = verifyContextSnapshot(value.context_snapshot, { root });
|
|
41
|
-
const changedRefs = [...value.changes.added, ...value.changes.updated, ...value.changes.deprecated];
|
|
42
|
-
resolveContextTermRefs(contract, changedRefs);
|
|
43
|
-
if (new Set(changedRefs).size !== changedRefs.length) throw new TypeError("changes 中的术语引用不得跨分类重复");
|
|
44
|
-
if (value.repository_mode === "project-instance" && value.status !== "reconciled") throw new TypeError("project-instance 工作单元只有 status=reconciled 才允许批准或进入下一步");
|
|
45
|
-
if (value.status === "reconciled" && value.unresolved_terms.length) throw new TypeError("reconciled 不得包含 unresolved_terms");
|
|
46
|
-
if (value.status === "blocked" && value.unresolved_terms.length === 0) throw new TypeError("blocked 必须说明 unresolved_terms");
|
|
47
|
-
if (value.status === "not-applicable" && (value.repository_mode !== "template-source" || !value.reason)) throw new TypeError("not-applicable 只适用于 template-source 且必须说明 reason");
|
|
48
|
-
for (const ref of value.evidence_refs) {
|
|
49
|
-
if (/^https?:\/\//.test(ref)) continue;
|
|
50
|
-
const resolved = path.resolve(root, ref);
|
|
51
|
-
if (!resolved.startsWith(`${root}${path.sep}`) && resolved !== root) throw new TypeError(`evidence_ref 越出仓库: ${ref}`);
|
|
52
|
-
if (!existsSync(resolved)) throw new TypeError(`evidence_ref 不可读: ${ref}`);
|
|
53
|
-
}
|
|
7
|
+
verifyContextReconciliation(positionals[0], { root: values.root });
|
|
54
8
|
process.stdout.write("Context reconciliation 验证通过\n");
|
|
55
9
|
} catch (error) {
|
|
56
10
|
process.stderr.write(`Context reconciliation 验证失败: ${error.message}\n`);
|
|
@@ -40,7 +40,7 @@ function record(overrides = {}) {
|
|
|
40
40
|
return {
|
|
41
41
|
schema_version: 1,
|
|
42
42
|
repository_mode: "project-instance",
|
|
43
|
-
stage: "stage.
|
|
43
|
+
stage: "stage.plan",
|
|
44
44
|
work_unit: "work-unit.domain-strategy-design",
|
|
45
45
|
status: "reconciled",
|
|
46
46
|
context_snapshot: snapshot,
|
|
@@ -6,6 +6,7 @@ import { parseArgs } from "node:util";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { parseDocument } from "./vendor/yaml.mjs";
|
|
8
8
|
import { assertCheckpointApprovals, assertCheckpointUserDecisions } from "./lib/approval-record.mjs";
|
|
9
|
+
import { assertPlanCheckpoint } from "./lib/plan-spec-entry.mjs";
|
|
9
10
|
|
|
10
11
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
12
|
const schemaPath = path.join(root, "docs/process/schemas/lifecycle-checkpoint.schema.json");
|
|
@@ -32,6 +33,7 @@ try {
|
|
|
32
33
|
const result = spawnSync("python3", ["-c", validator, schemaPath], { cwd: root, encoding: "utf8", input: JSON.stringify(value) });
|
|
33
34
|
if (result.status !== 0) throw new TypeError(`${result.stdout}${result.stderr}`.trim());
|
|
34
35
|
assertCheckpointApprovals(value, sourcePath);
|
|
36
|
+
assertPlanCheckpoint(value);
|
|
35
37
|
assertCheckpointUserDecisions(value);
|
|
36
38
|
if (value.repository_mode === "project-instance" && ["paused-human-gate", "completed"].includes(value.status)) {
|
|
37
39
|
if (value.context_reconciliation?.status !== "reconciled" || !value.context_reconciliation?.ref) throw new TypeError("project-instance 在会签或完成前必须具有 reconciled context_reconciliation");
|