create-yss-spec 3.5.6 → 3.5.9
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/bin/create-yss-spec.js +3 -1
- package/cli-core.lock.json +10 -6
- package/package.json +4 -1
- package/src/api/_sync-service.js +3 -1
- package/src/command-runner.mjs +44 -9
- package/src/commands/doctor.js +40 -0
- package/src/commands/skills.js +7 -2
- package/src/content-identity.js +111 -0
- package/src/runtime-store.mjs +650 -0
- package/src/template/asset-runtime.js +124 -22
- package/src/template/instance-runtime.js +23 -7
- package/src/validation/metadata.js +8 -0
- package/template/.agents/skills/.strategic-design-skills-manifest.json +3 -3
- package/template/.agents/skills/alibaba-java-code-style/SKILL.md +30 -36
- package/template/.agents/skills/archify/SKILL.md +2 -2
- package/template/.agents/skills/archify/scripts/yss-safe-deliver.mjs +10 -6
- package/template/.agents/skills/archify/test/yss-safe-deliver.test.mjs +9 -2
- package/template/.agents/skills/code-review/SKILL.md +19 -11
- package/template/.agents/skills/code-review/references/candidate-capture.md +1 -1
- package/template/.agents/skills/code-review/references/legacy-convergence.md +3 -1
- package/template/.agents/skills/code-review/references/review-axis-checklists.md +2 -0
- package/template/.agents/skills/code-review/references/yss-review-standards.md +4 -2
- package/template/.agents/skills/competitive-intelligence/SKILL.md +32 -74
- package/template/.agents/skills/file-export-download/SKILL.md +4 -73
- package/template/.agents/skills/file-export-download/references/binary-contract-example.md +26 -0
- package/template/.agents/skills/file-export-download/references/download-call-example.md +45 -0
- package/template/.agents/skills/formily-foundation/SKILL.md +6 -105
- package/template/.agents/skills/formily-foundation/references/async-save-example.md +57 -0
- package/template/.agents/skills/formily-foundation/references/query-layout.md +50 -0
- package/template/.agents/skills/formily-linkage-effects/SKILL.md +3 -116
- package/template/.agents/skills/formily-linkage-effects/references/linkage-example.md +116 -0
- package/template/.agents/skills/formily-mode-slot-detail/SKILL.md +3 -81
- package/template/.agents/skills/formily-mode-slot-detail/references/mode-slot-example.md +81 -0
- package/template/.agents/skills/formily-step-flow/SKILL.md +3 -143
- package/template/.agents/skills/formily-step-flow/references/step-flow-example.md +143 -0
- package/template/.agents/skills/handoff/SKILL.md +3 -1
- package/template/.agents/skills/i-have-adhd/SKILL.md +2 -2
- package/template/.agents/skills/i-have-adhd/references/yss-adaptation.md +2 -2
- package/template/.agents/skills/i-have-adhd/tests/verify-integration.mjs +7 -2
- package/template/.agents/skills/implement/SKILL.md +2 -2
- package/template/.agents/skills/llm-wiki/references/transactions.md +2 -2
- package/template/.agents/skills/llm-wiki/scripts/core.mjs +40 -2
- package/template/.agents/skills/llm-wiki/scripts/transaction.mjs +30 -27
- package/template/.agents/skills/llm-wiki/scripts/v2.test.mjs +38 -2
- package/template/.agents/skills/lombok/SKILL.md +2 -0
- package/template/.agents/skills/mapstruct/SKILL.md +2 -0
- package/template/.agents/skills/tdd/SKILL.md +2 -2
- package/template/.agents/skills/theme-token-usage/SKILL.md +6 -5
- package/template/.agents/skills/wayfinder/references/chart-map.md +2 -2
- package/template/.agents/skills/wayfinder/references/ticket-types.md +1 -1
- package/template/.agents/skills/yss-api-integration/SKILL.md +13 -50
- package/template/.agents/skills/yss-api-integration/references/orval-list-example.md +38 -0
- package/template/.agents/skills/yss-application/SKILL.md +11 -5
- package/template/.agents/skills/yss-audit-log/SKILL.md +8 -6
- package/template/.agents/skills/yss-audit-log/references/README.md +5 -5
- package/template/.agents/skills/yss-cache/SKILL.md +4 -4
- package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +7 -8
- package/template/.agents/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +13 -6
- package/template/.agents/skills/yss-ddd-scaffold-generator/references/command-examples.md +2 -0
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +28 -1
- package/template/.agents/skills/yss-design-system/SKILL.md +2 -2
- package/template/.agents/skills/yss-distributed-id/SKILL.md +4 -4
- package/template/.agents/skills/yss-dto/SKILL.md +9 -9
- package/template/.agents/skills/yss-dto/references/README.md +4 -4
- package/template/.agents/skills/yss-dto/references/wire-validation-checklist.md +4 -4
- package/template/.agents/skills/yss-excel-mvc/SKILL.md +4 -4
- package/template/.agents/skills/yss-exception/SKILL.md +42 -48
- package/template/.agents/skills/yss-formily-schema-generator/SKILL.md +26 -170
- package/template/.agents/skills/yss-formily-schema-generator/references/workflow.md +49 -193
- package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +14 -10
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +4 -6
- package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +15 -1
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.agents/skills/yss-mybatis/SKILL.md +4 -4
- package/template/.agents/skills/yss-openapi-draft-review/SKILL.md +6 -4
- package/template/.agents/skills/yss-openapi-draft-review/references/review-output.md +2 -0
- package/template/.agents/skills/yss-openapi-draft-review/references/semantic-review.md +3 -3
- package/template/.agents/skills/yss-openapi-governance/SKILL.md +5 -7
- package/template/.agents/skills/yss-openapi-governance/references/governance-output.md +2 -0
- package/template/.agents/skills/yss-openapi-governance/references/governance-workflow.md +3 -3
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +32 -26
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +1 -1
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +28 -6
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +143 -4
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +38 -13
- package/template/.agents/skills/yss-product-lifecycle/references/plan-requirements.md +7 -6
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +3 -1
- package/template/.agents/skills/yss-product-lifecycle/references/user-decisions.md +3 -3
- package/template/.agents/skills/yss-prototype-stage/SKILL.md +1 -5
- package/template/.agents/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +1 -0
- package/template/.agents/skills/yss-repository/SKILL.md +2 -2
- package/template/.agents/skills/yss-research/SKILL.md +39 -48
- package/template/.agents/skills/yss-research/assets/competitive-evidence-template.yaml +146 -0
- package/template/.agents/skills/yss-research/references/competitive-analysis.md +76 -0
- package/template/.agents/skills/yss-research/references/competitive-analysis.schema.json +324 -0
- package/template/.agents/skills/yss-research/references/evidence-contract.md +8 -0
- package/template/.agents/skills/yss-research/scripts/lib/competitive-analysis.mjs +185 -0
- package/template/.agents/skills/yss-research/scripts/render-competitive-outputs.mjs +16 -0
- package/template/.agents/skills/yss-research/scripts/validate-research-package.mjs +6 -2
- package/template/.agents/skills/yss-research/tests/competitive-scenarios.test.mjs +270 -0
- package/template/.agents/skills/yss-resilience4j/SKILL.md +25 -31
- package/template/.agents/skills/yss-security-algorithm/SKILL.md +37 -43
- package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +29 -36
- package/template/.agents/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +1 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +2 -5
- package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -5
- package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -5
- package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +83 -13
- package/template/.agents/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.agents/skills/yss-tactical-design/references/output-template.md +3 -3
- package/template/.agents/skills/yss-tactical-design/references/tactical-design-contract.md +1 -1
- package/template/.agents/skills/yss-technical-design/SKILL.md +6 -5
- package/template/.agents/skills/yss-ui/SKILL.md +7 -1
- package/template/.agents/skills/yss-ui/assets/docs/guide/gitlab-ci-integration.md +2 -2
- package/template/.agents/skills/yss-ui/references/checklist.md +38 -96
- package/template/.agents/skills/yss-ui/references/component-routing.md +3 -1
- package/template/.agents/skills/yss-ui/references/quick-recipes.md +17 -272
- package/template/.agents/skills/yss-ui/references/specialized-components.md +3 -3
- package/template/.agents/skills/yss-ui-business-page-generation/SKILL.md +1 -1
- package/template/.agents/skills/yss-up-springboot3/SKILL.md +19 -21
- package/template/.agents/skills/yss-userinfo/SKILL.md +27 -33
- package/template/.agents/skills/yss-validation/SKILL.md +26 -32
- package/template/.agents/skills/yss-web-controller/SKILL.md +11 -44
- package/template/.agents/skills/yss-web-controller/references/crud-generation.md +38 -0
- package/template/.agents/skills/ytable-usage/SKILL.md +2 -2
- package/template/.agents/skills/ytree-usage/SKILL.md +2 -80
- package/template/.agents/skills/ytree-usage/references/tree-and-confirmation-example.md +81 -0
- package/template/.codex/skills/alibaba-java-code-style/SKILL.md +30 -36
- package/template/.codex/skills/archify/SKILL.md +2 -2
- package/template/.codex/skills/archify/scripts/yss-safe-deliver.mjs +10 -6
- package/template/.codex/skills/archify/test/yss-safe-deliver.test.mjs +9 -2
- package/template/.codex/skills/code-review/SKILL.md +19 -11
- package/template/.codex/skills/code-review/references/candidate-capture.md +1 -1
- package/template/.codex/skills/code-review/references/legacy-convergence.md +3 -1
- package/template/.codex/skills/code-review/references/review-axis-checklists.md +2 -0
- package/template/.codex/skills/code-review/references/yss-review-standards.md +4 -2
- package/template/.codex/skills/competitive-intelligence/SKILL.md +32 -74
- package/template/.codex/skills/file-export-download/SKILL.md +4 -73
- package/template/.codex/skills/file-export-download/references/binary-contract-example.md +26 -0
- package/template/.codex/skills/file-export-download/references/download-call-example.md +45 -0
- package/template/.codex/skills/formily-foundation/SKILL.md +6 -105
- package/template/.codex/skills/formily-foundation/references/async-save-example.md +57 -0
- package/template/.codex/skills/formily-foundation/references/query-layout.md +50 -0
- package/template/.codex/skills/formily-linkage-effects/SKILL.md +3 -116
- package/template/.codex/skills/formily-linkage-effects/references/linkage-example.md +116 -0
- package/template/.codex/skills/formily-mode-slot-detail/SKILL.md +3 -81
- package/template/.codex/skills/formily-mode-slot-detail/references/mode-slot-example.md +81 -0
- package/template/.codex/skills/formily-step-flow/SKILL.md +3 -143
- package/template/.codex/skills/formily-step-flow/references/step-flow-example.md +143 -0
- package/template/.codex/skills/handoff/SKILL.md +3 -1
- package/template/.codex/skills/i-have-adhd/SKILL.md +2 -2
- package/template/.codex/skills/i-have-adhd/references/yss-adaptation.md +2 -2
- package/template/.codex/skills/i-have-adhd/tests/verify-integration.mjs +7 -2
- package/template/.codex/skills/implement/SKILL.md +2 -2
- package/template/.codex/skills/llm-wiki/references/transactions.md +2 -2
- package/template/.codex/skills/llm-wiki/scripts/core.mjs +40 -2
- package/template/.codex/skills/llm-wiki/scripts/transaction.mjs +30 -27
- package/template/.codex/skills/llm-wiki/scripts/v2.test.mjs +38 -2
- package/template/.codex/skills/lombok/SKILL.md +2 -0
- package/template/.codex/skills/mapstruct/SKILL.md +2 -0
- package/template/.codex/skills/product-design/references/communication-protocol.md +3 -3
- package/template/.codex/skills/product-design/references/critical-overrides.md +4 -5
- package/template/.codex/skills/product-design/skills/audit/SKILL.md +2 -4
- package/template/.codex/skills/product-design/skills/get-context/SKILL.md +6 -8
- package/template/.codex/skills/product-design/skills/ideate/SKILL.md +3 -3
- package/template/.codex/skills/product-design/skills/image-to-code/SKILL.md +3 -5
- package/template/.codex/skills/product-design/skills/index/SKILL.md +1 -1
- package/template/.codex/skills/product-design/skills/prototype/SKILL.md +2 -4
- package/template/.codex/skills/product-design/skills/research/SKILL.md +4 -6
- package/template/.codex/skills/product-design/skills/research/assets/research-brief-template.md +3 -3
- package/template/.codex/skills/product-design/skills/share/SKILL.md +2 -4
- package/template/.codex/skills/product-design/skills/url-to-code/SKILL.md +2 -4
- package/template/.codex/skills/product-design/skills/user-context/SKILL.md +1 -1
- package/template/.codex/skills/tdd/SKILL.md +2 -2
- package/template/.codex/skills/theme-token-usage/SKILL.md +6 -5
- package/template/.codex/skills/wayfinder/references/chart-map.md +2 -2
- package/template/.codex/skills/wayfinder/references/ticket-types.md +1 -1
- package/template/.codex/skills/yss-api-integration/SKILL.md +13 -50
- package/template/.codex/skills/yss-api-integration/references/orval-list-example.md +38 -0
- package/template/.codex/skills/yss-application/SKILL.md +11 -5
- package/template/.codex/skills/yss-audit-log/SKILL.md +8 -6
- package/template/.codex/skills/yss-audit-log/references/README.md +5 -5
- package/template/.codex/skills/yss-cache/SKILL.md +4 -4
- package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +7 -8
- package/template/.codex/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +13 -6
- package/template/.codex/skills/yss-ddd-scaffold-generator/references/command-examples.md +2 -0
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +28 -1
- package/template/.codex/skills/yss-design-system/SKILL.md +2 -2
- package/template/.codex/skills/yss-distributed-id/SKILL.md +4 -4
- package/template/.codex/skills/yss-dto/SKILL.md +9 -9
- package/template/.codex/skills/yss-dto/references/README.md +4 -4
- package/template/.codex/skills/yss-dto/references/wire-validation-checklist.md +4 -4
- package/template/.codex/skills/yss-excel-mvc/SKILL.md +4 -4
- package/template/.codex/skills/yss-exception/SKILL.md +42 -48
- package/template/.codex/skills/yss-formily-schema-generator/SKILL.md +26 -170
- package/template/.codex/skills/yss-formily-schema-generator/references/workflow.md +49 -193
- package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +14 -10
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +4 -6
- package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +15 -1
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.codex/skills/yss-mybatis/SKILL.md +4 -4
- package/template/.codex/skills/yss-openapi-draft-review/SKILL.md +6 -4
- package/template/.codex/skills/yss-openapi-draft-review/references/review-output.md +2 -0
- package/template/.codex/skills/yss-openapi-draft-review/references/semantic-review.md +3 -3
- package/template/.codex/skills/yss-openapi-governance/SKILL.md +5 -7
- package/template/.codex/skills/yss-openapi-governance/references/governance-output.md +2 -0
- package/template/.codex/skills/yss-openapi-governance/references/governance-workflow.md +3 -3
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +32 -26
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +1 -1
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +28 -6
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +143 -4
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +38 -13
- package/template/.codex/skills/yss-product-lifecycle/references/plan-requirements.md +7 -6
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +3 -1
- package/template/.codex/skills/yss-product-lifecycle/references/user-decisions.md +3 -3
- package/template/.codex/skills/yss-prototype-stage/SKILL.md +1 -5
- package/template/.codex/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +1 -0
- package/template/.codex/skills/yss-repository/SKILL.md +2 -2
- package/template/.codex/skills/yss-research/SKILL.md +39 -48
- package/template/.codex/skills/yss-research/assets/competitive-evidence-template.yaml +146 -0
- package/template/.codex/skills/yss-research/references/competitive-analysis.md +76 -0
- package/template/.codex/skills/yss-research/references/competitive-analysis.schema.json +324 -0
- package/template/.codex/skills/yss-research/references/evidence-contract.md +8 -0
- package/template/.codex/skills/yss-research/scripts/lib/competitive-analysis.mjs +185 -0
- package/template/.codex/skills/yss-research/scripts/render-competitive-outputs.mjs +16 -0
- package/template/.codex/skills/yss-research/scripts/validate-research-package.mjs +6 -2
- package/template/.codex/skills/yss-research/tests/competitive-scenarios.test.mjs +270 -0
- package/template/.codex/skills/yss-resilience4j/SKILL.md +25 -31
- package/template/.codex/skills/yss-security-algorithm/SKILL.md +37 -43
- package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +29 -36
- package/template/.codex/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +1 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +2 -5
- package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -5
- package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -5
- package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +83 -13
- package/template/.codex/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.codex/skills/yss-tactical-design/references/output-template.md +3 -3
- package/template/.codex/skills/yss-tactical-design/references/tactical-design-contract.md +1 -1
- package/template/.codex/skills/yss-technical-design/SKILL.md +6 -5
- package/template/.codex/skills/yss-ui/SKILL.md +7 -1
- package/template/.codex/skills/yss-ui/assets/docs/guide/gitlab-ci-integration.md +2 -2
- package/template/.codex/skills/yss-ui/references/checklist.md +38 -96
- package/template/.codex/skills/yss-ui/references/component-routing.md +3 -1
- package/template/.codex/skills/yss-ui/references/quick-recipes.md +17 -272
- package/template/.codex/skills/yss-ui/references/specialized-components.md +3 -3
- package/template/.codex/skills/yss-ui-business-page-generation/SKILL.md +1 -1
- package/template/.codex/skills/yss-up-springboot3/SKILL.md +19 -21
- package/template/.codex/skills/yss-userinfo/SKILL.md +27 -33
- package/template/.codex/skills/yss-validation/SKILL.md +26 -32
- package/template/.codex/skills/yss-web-controller/SKILL.md +11 -44
- package/template/.codex/skills/yss-web-controller/references/crud-generation.md +38 -0
- package/template/.codex/skills/ytable-usage/SKILL.md +2 -2
- package/template/.codex/skills/ytree-usage/SKILL.md +2 -80
- package/template/.codex/skills/ytree-usage/references/tree-and-confirmation-example.md +81 -0
- package/template/.cursor/skills/alibaba-java-code-style/SKILL.md +30 -36
- package/template/.cursor/skills/archify/SKILL.md +2 -2
- package/template/.cursor/skills/archify/scripts/yss-safe-deliver.mjs +10 -6
- package/template/.cursor/skills/archify/test/yss-safe-deliver.test.mjs +9 -2
- package/template/.cursor/skills/code-review/SKILL.md +19 -11
- package/template/.cursor/skills/code-review/references/candidate-capture.md +1 -1
- package/template/.cursor/skills/code-review/references/legacy-convergence.md +3 -1
- package/template/.cursor/skills/code-review/references/review-axis-checklists.md +2 -0
- package/template/.cursor/skills/code-review/references/yss-review-standards.md +4 -2
- package/template/.cursor/skills/competitive-intelligence/SKILL.md +32 -74
- package/template/.cursor/skills/file-export-download/SKILL.md +4 -73
- package/template/.cursor/skills/file-export-download/references/binary-contract-example.md +26 -0
- package/template/.cursor/skills/file-export-download/references/download-call-example.md +45 -0
- package/template/.cursor/skills/formily-foundation/SKILL.md +6 -105
- package/template/.cursor/skills/formily-foundation/references/async-save-example.md +57 -0
- package/template/.cursor/skills/formily-foundation/references/query-layout.md +50 -0
- package/template/.cursor/skills/formily-linkage-effects/SKILL.md +3 -116
- package/template/.cursor/skills/formily-linkage-effects/references/linkage-example.md +116 -0
- package/template/.cursor/skills/formily-mode-slot-detail/SKILL.md +3 -81
- package/template/.cursor/skills/formily-mode-slot-detail/references/mode-slot-example.md +81 -0
- package/template/.cursor/skills/formily-step-flow/SKILL.md +3 -143
- package/template/.cursor/skills/formily-step-flow/references/step-flow-example.md +143 -0
- package/template/.cursor/skills/handoff/SKILL.md +3 -1
- package/template/.cursor/skills/i-have-adhd/SKILL.md +2 -2
- package/template/.cursor/skills/i-have-adhd/references/yss-adaptation.md +2 -2
- package/template/.cursor/skills/i-have-adhd/tests/verify-integration.mjs +7 -2
- package/template/.cursor/skills/implement/SKILL.md +2 -2
- package/template/.cursor/skills/llm-wiki/references/transactions.md +2 -2
- package/template/.cursor/skills/llm-wiki/scripts/core.mjs +40 -2
- package/template/.cursor/skills/llm-wiki/scripts/transaction.mjs +30 -27
- package/template/.cursor/skills/llm-wiki/scripts/v2.test.mjs +38 -2
- package/template/.cursor/skills/lombok/SKILL.md +2 -0
- package/template/.cursor/skills/mapstruct/SKILL.md +2 -0
- package/template/.cursor/skills/tdd/SKILL.md +2 -2
- package/template/.cursor/skills/theme-token-usage/SKILL.md +6 -5
- package/template/.cursor/skills/wayfinder/references/chart-map.md +2 -2
- package/template/.cursor/skills/wayfinder/references/ticket-types.md +1 -1
- package/template/.cursor/skills/yss-api-integration/SKILL.md +13 -50
- package/template/.cursor/skills/yss-api-integration/references/orval-list-example.md +38 -0
- package/template/.cursor/skills/yss-application/SKILL.md +11 -5
- package/template/.cursor/skills/yss-audit-log/SKILL.md +8 -6
- package/template/.cursor/skills/yss-audit-log/references/README.md +5 -5
- package/template/.cursor/skills/yss-cache/SKILL.md +4 -4
- package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +7 -8
- package/template/.cursor/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +13 -6
- package/template/.cursor/skills/yss-ddd-scaffold-generator/references/command-examples.md +2 -0
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +28 -1
- package/template/.cursor/skills/yss-design-system/SKILL.md +2 -2
- package/template/.cursor/skills/yss-distributed-id/SKILL.md +4 -4
- package/template/.cursor/skills/yss-dto/SKILL.md +9 -9
- package/template/.cursor/skills/yss-dto/references/README.md +4 -4
- package/template/.cursor/skills/yss-dto/references/wire-validation-checklist.md +4 -4
- package/template/.cursor/skills/yss-excel-mvc/SKILL.md +4 -4
- package/template/.cursor/skills/yss-exception/SKILL.md +42 -48
- package/template/.cursor/skills/yss-formily-schema-generator/SKILL.md +26 -170
- package/template/.cursor/skills/yss-formily-schema-generator/references/workflow.md +49 -193
- package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +14 -10
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +4 -6
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +15 -1
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.cursor/skills/yss-mybatis/SKILL.md +4 -4
- package/template/.cursor/skills/yss-openapi-draft-review/SKILL.md +6 -4
- package/template/.cursor/skills/yss-openapi-draft-review/references/review-output.md +2 -0
- package/template/.cursor/skills/yss-openapi-draft-review/references/semantic-review.md +3 -3
- package/template/.cursor/skills/yss-openapi-governance/SKILL.md +5 -7
- package/template/.cursor/skills/yss-openapi-governance/references/governance-output.md +2 -0
- package/template/.cursor/skills/yss-openapi-governance/references/governance-workflow.md +3 -3
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +32 -26
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +1 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +28 -6
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +143 -4
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +38 -13
- package/template/.cursor/skills/yss-product-lifecycle/references/plan-requirements.md +7 -6
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +3 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/user-decisions.md +3 -3
- package/template/.cursor/skills/yss-prototype-stage/SKILL.md +1 -5
- package/template/.cursor/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +1 -0
- package/template/.cursor/skills/yss-repository/SKILL.md +2 -2
- package/template/.cursor/skills/yss-research/SKILL.md +39 -48
- package/template/.cursor/skills/yss-research/assets/competitive-evidence-template.yaml +146 -0
- package/template/.cursor/skills/yss-research/references/competitive-analysis.md +76 -0
- package/template/.cursor/skills/yss-research/references/competitive-analysis.schema.json +324 -0
- package/template/.cursor/skills/yss-research/references/evidence-contract.md +8 -0
- package/template/.cursor/skills/yss-research/scripts/lib/competitive-analysis.mjs +185 -0
- package/template/.cursor/skills/yss-research/scripts/render-competitive-outputs.mjs +16 -0
- package/template/.cursor/skills/yss-research/scripts/validate-research-package.mjs +6 -2
- package/template/.cursor/skills/yss-research/tests/competitive-scenarios.test.mjs +270 -0
- package/template/.cursor/skills/yss-resilience4j/SKILL.md +25 -31
- package/template/.cursor/skills/yss-security-algorithm/SKILL.md +37 -43
- package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +29 -36
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +1 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +2 -5
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -5
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -5
- package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +83 -13
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.cursor/skills/yss-tactical-design/references/output-template.md +3 -3
- package/template/.cursor/skills/yss-tactical-design/references/tactical-design-contract.md +1 -1
- package/template/.cursor/skills/yss-technical-design/SKILL.md +6 -5
- package/template/.cursor/skills/yss-ui/SKILL.md +7 -1
- package/template/.cursor/skills/yss-ui/assets/docs/guide/gitlab-ci-integration.md +2 -2
- package/template/.cursor/skills/yss-ui/references/checklist.md +38 -96
- package/template/.cursor/skills/yss-ui/references/component-routing.md +3 -1
- package/template/.cursor/skills/yss-ui/references/quick-recipes.md +17 -272
- package/template/.cursor/skills/yss-ui/references/specialized-components.md +3 -3
- package/template/.cursor/skills/yss-ui-business-page-generation/SKILL.md +1 -1
- package/template/.cursor/skills/yss-up-springboot3/SKILL.md +19 -21
- package/template/.cursor/skills/yss-userinfo/SKILL.md +27 -33
- package/template/.cursor/skills/yss-validation/SKILL.md +26 -32
- package/template/.cursor/skills/yss-web-controller/SKILL.md +11 -44
- package/template/.cursor/skills/yss-web-controller/references/crud-generation.md +38 -0
- package/template/.cursor/skills/ytable-usage/SKILL.md +2 -2
- package/template/.cursor/skills/ytree-usage/SKILL.md +2 -80
- package/template/.cursor/skills/ytree-usage/references/tree-and-confirmation-example.md +81 -0
- package/template/.pi/skills/alibaba-java-code-style/SKILL.md +30 -36
- package/template/.pi/skills/archify/SKILL.md +2 -2
- package/template/.pi/skills/archify/scripts/yss-safe-deliver.mjs +10 -6
- package/template/.pi/skills/archify/test/yss-safe-deliver.test.mjs +9 -2
- package/template/.pi/skills/code-review/SKILL.md +19 -11
- package/template/.pi/skills/code-review/references/candidate-capture.md +1 -1
- package/template/.pi/skills/code-review/references/legacy-convergence.md +3 -1
- package/template/.pi/skills/code-review/references/review-axis-checklists.md +2 -0
- package/template/.pi/skills/code-review/references/yss-review-standards.md +4 -2
- package/template/.pi/skills/competitive-intelligence/SKILL.md +32 -74
- package/template/.pi/skills/file-export-download/SKILL.md +4 -73
- package/template/.pi/skills/file-export-download/references/binary-contract-example.md +26 -0
- package/template/.pi/skills/file-export-download/references/download-call-example.md +45 -0
- package/template/.pi/skills/formily-foundation/SKILL.md +6 -105
- package/template/.pi/skills/formily-foundation/references/async-save-example.md +57 -0
- package/template/.pi/skills/formily-foundation/references/query-layout.md +50 -0
- package/template/.pi/skills/formily-linkage-effects/SKILL.md +3 -116
- package/template/.pi/skills/formily-linkage-effects/references/linkage-example.md +116 -0
- package/template/.pi/skills/formily-mode-slot-detail/SKILL.md +3 -81
- package/template/.pi/skills/formily-mode-slot-detail/references/mode-slot-example.md +81 -0
- package/template/.pi/skills/formily-step-flow/SKILL.md +3 -143
- package/template/.pi/skills/formily-step-flow/references/step-flow-example.md +143 -0
- package/template/.pi/skills/handoff/SKILL.md +3 -1
- package/template/.pi/skills/i-have-adhd/SKILL.md +2 -2
- package/template/.pi/skills/i-have-adhd/references/yss-adaptation.md +2 -2
- package/template/.pi/skills/i-have-adhd/tests/verify-integration.mjs +7 -2
- package/template/.pi/skills/implement/SKILL.md +2 -2
- package/template/.pi/skills/llm-wiki/references/transactions.md +2 -2
- package/template/.pi/skills/llm-wiki/scripts/core.mjs +40 -2
- package/template/.pi/skills/llm-wiki/scripts/transaction.mjs +30 -27
- package/template/.pi/skills/llm-wiki/scripts/v2.test.mjs +38 -2
- package/template/.pi/skills/lombok/SKILL.md +2 -0
- package/template/.pi/skills/mapstruct/SKILL.md +2 -0
- package/template/.pi/skills/tdd/SKILL.md +2 -2
- package/template/.pi/skills/theme-token-usage/SKILL.md +6 -5
- package/template/.pi/skills/wayfinder/references/chart-map.md +2 -2
- package/template/.pi/skills/wayfinder/references/ticket-types.md +1 -1
- package/template/.pi/skills/yss-api-integration/SKILL.md +13 -50
- package/template/.pi/skills/yss-api-integration/references/orval-list-example.md +38 -0
- package/template/.pi/skills/yss-application/SKILL.md +11 -5
- package/template/.pi/skills/yss-audit-log/SKILL.md +8 -6
- package/template/.pi/skills/yss-audit-log/references/README.md +5 -5
- package/template/.pi/skills/yss-cache/SKILL.md +4 -4
- package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +7 -8
- package/template/.pi/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +13 -6
- package/template/.pi/skills/yss-ddd-scaffold-generator/references/command-examples.md +2 -0
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +28 -1
- package/template/.pi/skills/yss-design-system/SKILL.md +2 -2
- package/template/.pi/skills/yss-distributed-id/SKILL.md +4 -4
- package/template/.pi/skills/yss-dto/SKILL.md +9 -9
- package/template/.pi/skills/yss-dto/references/README.md +4 -4
- package/template/.pi/skills/yss-dto/references/wire-validation-checklist.md +4 -4
- package/template/.pi/skills/yss-excel-mvc/SKILL.md +4 -4
- package/template/.pi/skills/yss-exception/SKILL.md +42 -48
- package/template/.pi/skills/yss-formily-schema-generator/SKILL.md +26 -170
- package/template/.pi/skills/yss-formily-schema-generator/references/workflow.md +49 -193
- package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +14 -10
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +4 -6
- package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +15 -1
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.pi/skills/yss-mybatis/SKILL.md +4 -4
- package/template/.pi/skills/yss-openapi-draft-review/SKILL.md +6 -4
- package/template/.pi/skills/yss-openapi-draft-review/references/review-output.md +2 -0
- package/template/.pi/skills/yss-openapi-draft-review/references/semantic-review.md +3 -3
- package/template/.pi/skills/yss-openapi-governance/SKILL.md +5 -7
- package/template/.pi/skills/yss-openapi-governance/references/governance-output.md +2 -0
- package/template/.pi/skills/yss-openapi-governance/references/governance-workflow.md +3 -3
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +32 -26
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +1 -1
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +28 -6
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +143 -4
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +38 -13
- package/template/.pi/skills/yss-product-lifecycle/references/plan-requirements.md +7 -6
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +3 -1
- package/template/.pi/skills/yss-product-lifecycle/references/user-decisions.md +3 -3
- package/template/.pi/skills/yss-prototype-stage/SKILL.md +1 -5
- package/template/.pi/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +1 -0
- package/template/.pi/skills/yss-repository/SKILL.md +2 -2
- package/template/.pi/skills/yss-research/SKILL.md +39 -48
- package/template/.pi/skills/yss-research/assets/competitive-evidence-template.yaml +146 -0
- package/template/.pi/skills/yss-research/references/competitive-analysis.md +76 -0
- package/template/.pi/skills/yss-research/references/competitive-analysis.schema.json +324 -0
- package/template/.pi/skills/yss-research/references/evidence-contract.md +8 -0
- package/template/.pi/skills/yss-research/scripts/lib/competitive-analysis.mjs +185 -0
- package/template/.pi/skills/yss-research/scripts/render-competitive-outputs.mjs +16 -0
- package/template/.pi/skills/yss-research/scripts/validate-research-package.mjs +6 -2
- package/template/.pi/skills/yss-research/tests/competitive-scenarios.test.mjs +270 -0
- package/template/.pi/skills/yss-resilience4j/SKILL.md +25 -31
- package/template/.pi/skills/yss-security-algorithm/SKILL.md +37 -43
- package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +29 -36
- package/template/.pi/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +1 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +2 -5
- package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +8 -5
- package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +8 -5
- package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +83 -13
- package/template/.pi/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.pi/skills/yss-tactical-design/references/output-template.md +3 -3
- package/template/.pi/skills/yss-tactical-design/references/tactical-design-contract.md +1 -1
- package/template/.pi/skills/yss-technical-design/SKILL.md +6 -5
- package/template/.pi/skills/yss-ui/SKILL.md +7 -1
- package/template/.pi/skills/yss-ui/assets/docs/guide/gitlab-ci-integration.md +2 -2
- package/template/.pi/skills/yss-ui/references/checklist.md +38 -96
- package/template/.pi/skills/yss-ui/references/component-routing.md +3 -1
- package/template/.pi/skills/yss-ui/references/quick-recipes.md +17 -272
- package/template/.pi/skills/yss-ui/references/specialized-components.md +3 -3
- package/template/.pi/skills/yss-ui-business-page-generation/SKILL.md +1 -1
- package/template/.pi/skills/yss-up-springboot3/SKILL.md +19 -21
- package/template/.pi/skills/yss-userinfo/SKILL.md +27 -33
- package/template/.pi/skills/yss-validation/SKILL.md +26 -32
- package/template/.pi/skills/yss-web-controller/SKILL.md +11 -44
- package/template/.pi/skills/yss-web-controller/references/crud-generation.md +38 -0
- package/template/.pi/skills/ytable-usage/SKILL.md +2 -2
- package/template/.pi/skills/ytree-usage/SKILL.md +2 -80
- package/template/.pi/skills/ytree-usage/references/tree-and-confirmation-example.md +81 -0
- package/template/.template-spec/agents/backend-architecture-profiles.md +1 -1
- package/template/.template-spec/agents/digital-human-roles.md +5 -1
- package/template/.template-spec/agents/digital-human-roles.yaml +49 -1
- package/template/.template-spec/engineering/backend-platforms.json +1 -1
- package/template/.template-spec/plan/entry-review.md +2 -1
- package/template/.template-spec/plan/templates/competitive-analysis-template.md +38 -36
- package/template/.template-spec/plan/templates/competitive-matrix-template.md +37 -17
- package/template/.template-spec/plan/templates/plan-template.md +11 -5
- package/template/.template-spec/process/document-writing.md +22 -3
- package/template/.template-spec/process/harness-process-tailoring.md +5 -1
- package/template/.template-spec/process/implementation-repo-integration.md +26 -8
- package/template/.template-spec/process/research-completion.md +2 -0
- package/template/.template-spec/process/runtime-storage.md +78 -0
- package/template/.template-spec/process/schemas/approval-context.schema.json +67 -0
- package/template/.template-spec/process/schemas/approval-record.schema.json +179 -16
- package/template/.template-spec/process/schemas/backend-delivery.schema.json +16 -0
- package/template/.template-spec/process/schemas/delivery-preflight-input.schema.json +4 -0
- package/template/.template-spec/process/schemas/digital-human-task-package.schema.json +236 -1
- package/template/.template-spec/process/schemas/implementation-repository-preparation-result.schema.json +335 -52
- package/template/.template-spec/process/schemas/lifecycle-checkpoint.schema.json +11 -0
- package/template/.template-spec/process/schemas/project-scaffold-contract.schema.json +3 -0
- package/template/.template-spec/process/schemas/review-bundle.schema.json +347 -35
- package/template/.template-spec/process/schemas/strategic-design-handoff-v3.schema.json +504 -0
- package/template/.template-spec/process/schemas/strategic-design-handoff-v4.schema.json +544 -8
- package/template/.template-spec/process/schemas/strategic-design-handoff-v5.schema.json +616 -0
- package/template/.template-spec/process/schemas/strategic-design-handoff.schema.json +616 -0
- package/template/.template-spec/process/schemas/strategic-handoff-domain-strategy-v3.schema.json +712 -109
- package/template/.template-spec/process/schemas/strategic-handoff-domain-strategy.schema.json +595 -90
- package/template/.template-spec/process/schemas/strategic-handoff-export-v2.schema.json +448 -0
- package/template/.template-spec/process/schemas/strategic-handoff-export.schema.json +392 -0
- package/template/.template-spec/process/schemas/strategic-handoff-stage-decision-package-v3.schema.json +556 -83
- package/template/.template-spec/process/schemas/strategic-handoff-stage-decision-package.schema.json +418 -57
- package/template/.template-spec/process/script-execution.md +37 -0
- package/template/.template-spec/process/subagent-collaboration.md +7 -1
- package/template/.template-spec/templates/approval-record-template.json +7 -3
- package/template/.template-spec/templates/approval-record-template.yaml +8 -2
- package/template/.template-spec/templates/examples/lifecycle-writing-examples.md +92 -2
- package/template/.template-spec/templates/retro-report-template.md +10 -3
- package/template/.template-spec/templates/review-bundle-template.yaml +19 -10
- package/template/.template-spec/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +2 -0
- package/template/AGENTS.md +4 -3
- package/template/CONTEXT.md +2 -2
- package/template/README.md +2 -2
- package/template/scripts/advance-maintenance-iteration +51 -0
- package/template/scripts/lib/approval-checkpoint-discovery.mjs +26 -0
- package/template/scripts/lib/approval-consumption.mjs +35 -0
- package/template/scripts/lib/approval-current.mjs +111 -0
- package/template/scripts/lib/approval-record-io.mjs +56 -0
- package/template/scripts/lib/approval-record.mjs +79 -184
- package/template/scripts/lib/approved-execution-context.mjs +8 -6
- package/template/scripts/lib/asset-transactions.mjs +5 -1
- package/template/scripts/lib/backend-delivery.mjs +1 -1
- package/template/scripts/lib/backend-review.mjs +2 -1
- package/template/scripts/lib/backend-scaffold-prerequisites.mjs +3 -2
- package/template/scripts/lib/business-ticket-lifecycle.mjs +2 -1
- package/template/scripts/lib/checkpoint-commit.mjs +50 -0
- package/template/scripts/lib/command-runner.mjs +44 -9
- package/template/scripts/lib/content-identity.mjs +273 -0
- package/template/scripts/lib/delivery-preflight.mjs +2 -1
- package/template/scripts/lib/digital-human-roles.mjs +12 -5
- package/template/scripts/lib/drift-report.mjs +110 -0
- package/template/scripts/lib/existing-backend-architecture.mjs +4 -1
- package/template/scripts/lib/lifecycle-context-query.mjs +172 -11
- package/template/scripts/lib/lifecycle-controls.mjs +9 -19
- package/template/scripts/lib/lifecycle-presentation.mjs +5 -0
- package/template/scripts/lib/lifecycle-status.mjs +63 -12
- package/template/scripts/lib/lifecycle-transition.mjs +2 -1
- package/template/scripts/lib/maintenance-candidate.mjs +24 -30
- package/template/scripts/lib/maintenance-research.mjs +52 -8
- package/template/scripts/lib/maintenance-storage.mjs +81 -0
- package/template/scripts/lib/plan-spec-entry.mjs +2 -1
- package/template/scripts/lib/project-governance.mjs +2 -1
- package/template/scripts/lib/read-only-intake.mjs +44 -9
- package/template/scripts/lib/review-capabilities.mjs +234 -0
- package/template/scripts/lib/review-package.mjs +100 -0
- package/template/scripts/lib/runtime-store.mjs +650 -0
- package/template/scripts/lib/skill-registry.mjs +4 -4
- package/template/scripts/lib/strategic-handoff.mjs +22 -9
- package/template/scripts/lib/task-package.mjs +47 -16
- package/template/scripts/lifecycle-status +26 -1
- package/template/scripts/maintenance-path +11 -0
- package/template/scripts/prepare-review-package +8 -0
- package/template/scripts/project-ci +13 -3
- package/template/scripts/query-lifecycle-context +8 -1
- package/template/scripts/run-read-only-intake +2 -2
- package/template/scripts/runtime-store +40 -0
- package/template/scripts/verify-approval-record +21 -13
- package/template/scripts/verify-lifecycle-checkpoint +7 -3
- package/template/scripts/verify-project-instance +21 -1
- package/template/skills-lock.json +64 -63
- package/template.snapshot.json +4 -4
- package/vendor/cli-core/cli.mjs +2 -0
- package/vendor/cli-core/command-runner.mjs +44 -9
- package/vendor/cli-core/package.json +1 -1
- package/vendor/cli-core/runtime-store.mjs +650 -0
- package/vendor/cli-core/scaffold.mjs +4 -2
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
// Git-native content identity. A "git-sha1" / "git-sha256" identity is the blob
|
|
7
|
+
// hash Git itself would record for the path (default clean filters), obtained
|
|
8
|
+
// from the index only when the path is provably complete, and from
|
|
9
|
+
// "git hash-object" otherwise. "sha256" is the disclosed fallback without Git.
|
|
10
|
+
export const GIT_SHA1 = "git-sha1";
|
|
11
|
+
export const GIT_SHA256 = "git-sha256";
|
|
12
|
+
export const SHA256 = "sha256";
|
|
13
|
+
export const UNRESOLVED = "unresolved";
|
|
14
|
+
const HEX_LENGTH = { "git-sha1": 40, "git-sha256": 64, sha256: 64 };
|
|
15
|
+
const IDENTITY_PATTERN = /^(git-sha1|git-sha256|sha256):([0-9a-f]+)$/;
|
|
16
|
+
const SKIP_NAMES = new Set([".DS_Store", "__pycache__", ".git"]);
|
|
17
|
+
const SKIP_FILE = /\.(iml|pyc|pyo)$/;
|
|
18
|
+
|
|
19
|
+
export function parseIdentity(value) {
|
|
20
|
+
if (typeof value !== "string") return null;
|
|
21
|
+
const match = IDENTITY_PATTERN.exec(value);
|
|
22
|
+
if (!match) return null;
|
|
23
|
+
if (match[2].length !== HEX_LENGTH[match[1]]) return null;
|
|
24
|
+
return { algo: match[1], value: match[2] };
|
|
25
|
+
}
|
|
26
|
+
export function formatIdentity(algo, hex) {
|
|
27
|
+
const length = HEX_LENGTH[algo];
|
|
28
|
+
if (!length) throw new TypeError("未知身份算法: " + algo);
|
|
29
|
+
if (typeof hex !== "string" || !new RegExp("^[0-9a-f]{" + length + "}$").test(hex)) {
|
|
30
|
+
throw new TypeError("身份摘要非法: " + algo + ":" + hex);
|
|
31
|
+
}
|
|
32
|
+
return algo + ":" + hex;
|
|
33
|
+
}
|
|
34
|
+
export function identityEquals(left, right) {
|
|
35
|
+
const a = parseIdentity(left);
|
|
36
|
+
const b = parseIdentity(right);
|
|
37
|
+
if (!a || !b) return left === right;
|
|
38
|
+
return a.algo === b.algo && a.value === b.value;
|
|
39
|
+
}
|
|
40
|
+
export function sha256Identity(bytes) {
|
|
41
|
+
return formatIdentity(SHA256, createHash("sha256").update(bytes).digest("hex"));
|
|
42
|
+
}
|
|
43
|
+
export function treeDigest(entries, algo = SHA256) {
|
|
44
|
+
const digest = createHash(algo === GIT_SHA1 ? "sha1" : "sha256");
|
|
45
|
+
const sorted = [...entries].sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
|
|
46
|
+
for (const entry of sorted) {
|
|
47
|
+
digest.update(entry.path).update("\0").update(entry.kind).update("\0").update(entry.identity).update("\0");
|
|
48
|
+
}
|
|
49
|
+
return formatIdentity(algo, digest.digest("hex"));
|
|
50
|
+
}
|
|
51
|
+
export function treeFiles(directory, prefix = "") {
|
|
52
|
+
if (!existsSync(directory)) return [];
|
|
53
|
+
const collected = [];
|
|
54
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
55
|
+
if (SKIP_NAMES.has(entry.name)) continue;
|
|
56
|
+
const absolute = path.join(directory, entry.name);
|
|
57
|
+
const rel = prefix ? prefix + "/" + entry.name : entry.name;
|
|
58
|
+
if (SKIP_FILE.test(rel)) continue;
|
|
59
|
+
if (entry.isDirectory()) collected.push(...treeFiles(absolute, rel));
|
|
60
|
+
else if (entry.isFile() || entry.isSymbolicLink()) collected.push([rel, absolute]);
|
|
61
|
+
}
|
|
62
|
+
return collected;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function modeKind(mode) {
|
|
66
|
+
if (mode === "120000") return "symlink";
|
|
67
|
+
if (mode === "160000") return "gitlink";
|
|
68
|
+
if (mode === "100755") return "exec";
|
|
69
|
+
return "file";
|
|
70
|
+
}
|
|
71
|
+
function statKind(info) {
|
|
72
|
+
if (info.isSymbolicLink()) return "symlink";
|
|
73
|
+
return info.mode & 0o111 ? "exec" : "file";
|
|
74
|
+
}
|
|
75
|
+
// Mark a path and every ancestor directory. A directory may only trust the
|
|
76
|
+
// index when neither it nor any descendant is dirty, untracked or ignored —
|
|
77
|
+
// otherwise the index view would silently omit files the worktree has.
|
|
78
|
+
function markDirectories(target, ref) {
|
|
79
|
+
target.add(ref);
|
|
80
|
+
let cursor = ref;
|
|
81
|
+
while (cursor.includes("/")) {
|
|
82
|
+
cursor = cursor.slice(0, cursor.lastIndexOf("/"));
|
|
83
|
+
if (!cursor) break;
|
|
84
|
+
target.add(cursor);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function createIdentityProvider(root, { spawn = spawnSync } = {}) {
|
|
89
|
+
// Compare against the canonical root: on macOS a /tmp path is really
|
|
90
|
+
// /private/tmp, and a link inside the repository would otherwise look external.
|
|
91
|
+
const realRoot = realpathOrResolve(root);
|
|
92
|
+
const run = (args) => spawn("git", ["-C", root, ...args], { encoding: "buffer", maxBuffer: 128 * 1024 * 1024 });
|
|
93
|
+
let available = false;
|
|
94
|
+
let algo = SHA256;
|
|
95
|
+
const index = new Map();
|
|
96
|
+
const ignoredDirs = new Set();
|
|
97
|
+
let dirty = null;
|
|
98
|
+
let dirtyDirs = null;
|
|
99
|
+
const visiting = new Set();
|
|
100
|
+
|
|
101
|
+
function load() {
|
|
102
|
+
index.clear();
|
|
103
|
+
ignoredDirs.clear();
|
|
104
|
+
visiting.clear();
|
|
105
|
+
dirty = null;
|
|
106
|
+
dirtyDirs = null;
|
|
107
|
+
const probe = run(["rev-parse", "--is-inside-work-tree"]);
|
|
108
|
+
available = probe.status === 0 && probe.stdout.toString("utf8").trim() === "true";
|
|
109
|
+
algo = SHA256;
|
|
110
|
+
if (!available) return;
|
|
111
|
+
const format = run(["rev-parse", "--show-object-format"]);
|
|
112
|
+
const name = format.status === 0 ? format.stdout.toString("utf8").trim() : "sha1";
|
|
113
|
+
algo = name === "sha256" ? GIT_SHA256 : GIT_SHA1;
|
|
114
|
+
const listed = run(["ls-files", "--stage", "-z"]);
|
|
115
|
+
if (listed.status !== 0) { available = false; return; }
|
|
116
|
+
for (const record of listed.stdout.toString("utf8").split("\0")) {
|
|
117
|
+
if (!record) continue;
|
|
118
|
+
const separator = record.indexOf("\t");
|
|
119
|
+
if (separator < 0) continue;
|
|
120
|
+
const [mode, sha] = record.slice(0, separator).split(" ");
|
|
121
|
+
index.set(record.slice(separator + 1), { mode, sha });
|
|
122
|
+
}
|
|
123
|
+
const ignored = run(["ls-files", "-z", "--others", "--ignored", "--exclude-standard"]);
|
|
124
|
+
if (ignored.status === 0) {
|
|
125
|
+
for (const ref of ignored.stdout.toString("utf8").split("\0")) {
|
|
126
|
+
if (ref) markDirectories(ignoredDirs, ref);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
load();
|
|
131
|
+
|
|
132
|
+
function dirtySet() {
|
|
133
|
+
if (dirty) return dirty;
|
|
134
|
+
dirty = new Set();
|
|
135
|
+
dirtyDirs = new Set();
|
|
136
|
+
if (available) {
|
|
137
|
+
const status = run(["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
|
|
138
|
+
if (status.status === 0) {
|
|
139
|
+
const records = status.stdout.toString("utf8").split("\0");
|
|
140
|
+
for (let cursor = 0; cursor < records.length; cursor += 1) {
|
|
141
|
+
const record = records[cursor];
|
|
142
|
+
if (record.length < 4) continue;
|
|
143
|
+
const code = record.slice(0, 2);
|
|
144
|
+
const ref = record.slice(3);
|
|
145
|
+
if (code[0] === "?" || code[1] !== " ") { dirty.add(ref); markDirectories(dirtyDirs, ref); }
|
|
146
|
+
if (code[0] === "R" || code[0] === "C") {
|
|
147
|
+
cursor += 1;
|
|
148
|
+
if (records[cursor]) { dirty.add(records[cursor]); markDirectories(dirtyDirs, records[cursor]); }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return dirty;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function hashObject(absolute) {
|
|
157
|
+
const result = spawn("git", ["-C", root, "hash-object", "--", absolute], { encoding: "utf8" });
|
|
158
|
+
if (result.status !== 0) return null;
|
|
159
|
+
const hex = result.stdout.trim();
|
|
160
|
+
return new RegExp("^[0-9a-f]{" + HEX_LENGTH[algo] + "}$").test(hex) ? formatIdentity(algo, hex) : null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function indexIdentity(ref) {
|
|
164
|
+
const record = ref ? index.get(ref) : null;
|
|
165
|
+
if (!record || dirtySet().has(ref)) return null;
|
|
166
|
+
return formatIdentity(algo, record.sha);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function fileFromAbsolute(absolute, ref) {
|
|
170
|
+
const fromIndex = indexIdentity(ref);
|
|
171
|
+
if (fromIndex) return fromIndex;
|
|
172
|
+
if (available) {
|
|
173
|
+
const hashed = hashObject(absolute);
|
|
174
|
+
if (hashed) return hashed;
|
|
175
|
+
}
|
|
176
|
+
try { return sha256Identity(readFileSync(absolute)); } catch { return null; }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function symlinkIdentity(absolute) {
|
|
180
|
+
let resolved;
|
|
181
|
+
try { resolved = realpathSync(absolute); } catch { return null; }
|
|
182
|
+
if (visiting.has(resolved)) return null;
|
|
183
|
+
visiting.add(resolved);
|
|
184
|
+
try {
|
|
185
|
+
const info = lstatSync(resolved);
|
|
186
|
+
const rel = path.relative(realRoot, resolved).split(path.sep).join("/");
|
|
187
|
+
// A link that leaves the repository (or points at the root itself) is never
|
|
188
|
+
// enumerated: walking it would be unbounded. A directory legitimately named
|
|
189
|
+
// like "..data" is still inside, so only the ".." path segment is rejected.
|
|
190
|
+
const inside = rel !== "" && rel !== ".." && !rel.startsWith("../") && !path.isAbsolute(rel);
|
|
191
|
+
if (!inside) return null;
|
|
192
|
+
if (info.isDirectory()) return directoryIdentity(rel, resolved).identity;
|
|
193
|
+
return fileFromAbsolute(resolved, rel);
|
|
194
|
+
} finally {
|
|
195
|
+
visiting.delete(resolved);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function unresolvedEntry(rel, info) {
|
|
200
|
+
return { path: rel, kind: info.isSymbolicLink() ? "symlink" : "file", identity: UNRESOLVED };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function directoryEntries(absolute, ref) {
|
|
204
|
+
dirtySet();
|
|
205
|
+
const complete = ref && !dirtyDirs.has(ref) && !ignoredDirs.has(ref);
|
|
206
|
+
if (complete) {
|
|
207
|
+
const candidates = [];
|
|
208
|
+
for (const [candidate, record] of index) {
|
|
209
|
+
if (candidate.startsWith(ref + "/")) candidates.push([candidate, record]);
|
|
210
|
+
}
|
|
211
|
+
if (candidates.length) {
|
|
212
|
+
const entries = candidates.map(([candidate, record]) => {
|
|
213
|
+
const rel = candidate.slice(ref.length + 1);
|
|
214
|
+
const kind = modeKind(record.mode);
|
|
215
|
+
if (kind === "symlink") {
|
|
216
|
+
const resolvedIdentity = symlinkIdentity(path.join(root, candidate));
|
|
217
|
+
return resolvedIdentity ? { path: rel, kind, identity: resolvedIdentity } : { path: rel, kind, identity: UNRESOLVED };
|
|
218
|
+
}
|
|
219
|
+
return { path: rel, kind, identity: formatIdentity(algo, record.sha) };
|
|
220
|
+
});
|
|
221
|
+
return { entries, source: "index" };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const entries = treeFiles(absolute).map(([rel, file]) => {
|
|
225
|
+
const info = lstatSync(file);
|
|
226
|
+
if (info.isSymbolicLink()) {
|
|
227
|
+
const identity = symlinkIdentity(file);
|
|
228
|
+
return identity ? { path: rel, kind: "symlink", identity } : unresolvedEntry(rel, info);
|
|
229
|
+
}
|
|
230
|
+
const identity = fileFromAbsolute(file, ref ? ref + "/" + rel : null);
|
|
231
|
+
return identity ? { path: rel, kind: statKind(info), identity } : unresolvedEntry(rel, info);
|
|
232
|
+
});
|
|
233
|
+
return { entries, source: available ? "worktree" : "sha256-fallback" };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function directoryIdentity(ref, absolute = path.join(root, ref)) {
|
|
237
|
+
const { entries, source } = directoryEntries(absolute, ref);
|
|
238
|
+
return { identity: treeDigest(entries, available ? algo : SHA256), kind: "dir", source };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function identityFor(ref) {
|
|
242
|
+
const absolute = path.isAbsolute(ref) ? ref : path.join(root, ref);
|
|
243
|
+
const info = lstatSafe(absolute);
|
|
244
|
+
if (!info) return { identity: null, kind: "missing", source: available ? "index" : "sha256-fallback" };
|
|
245
|
+
if (info.isSymbolicLink()) {
|
|
246
|
+
const identity = symlinkIdentity(absolute);
|
|
247
|
+
return { identity, kind: "symlink", source: identity ? (available ? "worktree" : "sha256-fallback") : "unresolved" };
|
|
248
|
+
}
|
|
249
|
+
if (info.isDirectory()) return directoryIdentity(ref, absolute);
|
|
250
|
+
const identity = fileFromAbsolute(absolute, ref);
|
|
251
|
+
return { identity, kind: statKind(info), source: indexIdentity(ref) ? "index" : (available ? "worktree" : "sha256-fallback") };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
get available() { return available; },
|
|
256
|
+
get algo() { return available ? algo : SHA256; },
|
|
257
|
+
get root() { return root; },
|
|
258
|
+
indexSize: () => index.size,
|
|
259
|
+
refresh: () => { load(); },
|
|
260
|
+
identityFor,
|
|
261
|
+
file: (ref) => identityFor(ref).identity,
|
|
262
|
+
directory: (ref) => directoryIdentity(ref).identity,
|
|
263
|
+
equals: (left, right) => identityEquals(identityFor(left).identity, identityFor(right).identity),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function realpathOrResolve(target) {
|
|
268
|
+
try { return realpathSync(target); } catch { return path.resolve(target); }
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function lstatSafe(target) {
|
|
272
|
+
try { return lstatSync(target); } catch (error) { if (error.code === "ENOENT") return null; throw error; }
|
|
273
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {approvalExpectationForBoundAsset} from './approval-consumption.mjs';
|
|
1
2
|
import { normalizeSliceContract, sourceSliceContract, parseSliceYaml } from './slice-contract.mjs';
|
|
2
3
|
import { assertExistingSliceStructure, createApprovedExecutionContext, verifySliceContractApproval } from './approved-execution-context.mjs';
|
|
3
4
|
import path from 'node:path';
|
|
@@ -122,7 +123,7 @@ async function approved(root,binding,gates) {
|
|
|
122
123
|
ensure(binding.approval_ref&&binding.id&&binding.version,'缺少当前资产 id/version/approval_ref');
|
|
123
124
|
const record=read(safe(root,binding.approval_ref));
|
|
124
125
|
const roles=sourceApprovalPolicy(read(safe(root,'.template-spec/agents/digital-human-roles.yaml')));
|
|
125
|
-
validateApprovalRecord(record,{rolesDoc:roles,requireApproved:true,root,read:ref=>readFileSync(safe(root,path.relative(root,ref).split(path.sep).join('/')))});
|
|
126
|
+
validateApprovalRecord(record,{rolesDoc:roles,requireApproved:true,root,read:ref=>readFileSync(safe(root,path.relative(root,ref).split(path.sep).join('/'))),expected:approvalExpectationForBoundAsset(record.gate_id,binding,{root})});
|
|
126
127
|
ensure(gates.includes(record.gate_id),'资产批准使用错误门禁');
|
|
127
128
|
ensure(record.artifact_bindings?.some(x=>x.id===binding.id&&x.version===binding.version&&x.digest===binding.digest),'stale: 批准未绑定当前资产身份、版本及字节');
|
|
128
129
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateReviewCapabilityPolicy } from './review-capabilities.mjs';
|
|
1
2
|
import { readFileSync } from './validation-phase.mjs';
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { parseDocument } from "../vendor/yaml.mjs";
|
|
@@ -230,8 +231,11 @@ export function countersignRuleForGate(policy, gateId) {
|
|
|
230
231
|
return { bucket: "biological_human", gate: gateId, countersigners: [BIOLOGICAL_ROLE_ID] };
|
|
231
232
|
}
|
|
232
233
|
if ((policy?.evidence_only || []).includes(gateId) || (policy?.orchestrator || []).includes(gateId)) return null;
|
|
233
|
-
if (policy?.
|
|
234
|
-
|
|
234
|
+
if ((policy?.automatic_checks || []).includes(gateId)) return null;
|
|
235
|
+
if (policy?.default_if_unlisted === 'reject-unlisted') {
|
|
236
|
+
const error = new TypeError(`GATE_POLICY_REQUIRED: 未分类门禁或检查 ${gateId}`);
|
|
237
|
+
error.code = 'GATE_POLICY_REQUIRED';
|
|
238
|
+
throw error;
|
|
235
239
|
}
|
|
236
240
|
return null;
|
|
237
241
|
}
|
|
@@ -253,7 +257,7 @@ export function taskPackageDefaults(roleId, doc) {
|
|
|
253
257
|
};
|
|
254
258
|
}
|
|
255
259
|
|
|
256
|
-
export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, artifactIds, evidenceIds, workUnitIds, skillRegistry } = {}) {
|
|
260
|
+
export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, artifactIds, evidenceIds, workUnitIds, skillRegistry, checkIds: suppliedCheckIds } = {}) {
|
|
257
261
|
if (!doc || typeof doc !== "object" || Array.isArray(doc)) fail("数字人角色注册表必须是对象");
|
|
258
262
|
if (doc.schema_version !== 1) fail("schema_version 必须为 1");
|
|
259
263
|
if (doc.registry_id !== "yss.digital-human-roles") fail("registry_id 必须为 yss.digital-human-roles");
|
|
@@ -323,7 +327,7 @@ export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, ar
|
|
|
323
327
|
|
|
324
328
|
const policy = doc.gate_policy;
|
|
325
329
|
if (!policy || typeof policy !== "object") fail("缺少 gate_policy");
|
|
326
|
-
if (policy.default_if_unlisted !== "
|
|
330
|
+
if (policy.default_if_unlisted !== "reject-unlisted") fail("GATE_POLICY_REQUIRED: default_if_unlisted 必须为 reject-unlisted");
|
|
327
331
|
if (policy.runtime_side_effect_approval !== "biological-human") fail("runtime_side_effect_approval 必须为 biological-human");
|
|
328
332
|
if (policy.commercial_contract !== "biological-human") fail("commercial_contract 必须为 biological-human");
|
|
329
333
|
if (policy.unlisted_kept_biological) {
|
|
@@ -348,7 +352,7 @@ export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, ar
|
|
|
348
352
|
if (typeof rule === "string") fail("digital_human_review 必须是含 gate 与 countersigners 的规则");
|
|
349
353
|
validateSignRule(rule, { actors, gateIds, claimed, field: `digital_human_review[${index}]` });
|
|
350
354
|
}
|
|
351
|
-
const checkIds = new Set(loadRegistry().checks.map(check => check.id));
|
|
355
|
+
const checkIds = suppliedCheckIds || new Set(loadRegistry().checks.map(check => check.id));
|
|
352
356
|
const checkClaimed = new Set();
|
|
353
357
|
for (const id of policy.automatic_checks || []) {
|
|
354
358
|
if (!checkIds.has(id) || checkClaimed.has(id)) fail(`未知或重复自动检查: ${id}`);
|
|
@@ -387,6 +391,8 @@ export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, ar
|
|
|
387
391
|
if (claimed.has(gate)) fail(`unlisted_kept_biological 与会签桶重复: ${gate}`);
|
|
388
392
|
}
|
|
389
393
|
|
|
394
|
+
validateReviewCapabilityPolicy(doc, { skillIds, gateIds, checkIds });
|
|
395
|
+
|
|
390
396
|
const decisions = doc.user_decision_policy;
|
|
391
397
|
if (decisions?.continuation) {
|
|
392
398
|
const continuation = decisions.continuation;
|
|
@@ -425,6 +431,7 @@ export function validateDefaultDigitalHumanRoles() {
|
|
|
425
431
|
skillIds: skillIdsFromRegistry(skills),
|
|
426
432
|
stageIds: idsFromCollection(lifecycle.stages, "stages"),
|
|
427
433
|
gateIds: idsFromCollection(lifecycle.gates, "gates"),
|
|
434
|
+
checkIds: idsFromCollection(lifecycle.checks, "checks"),
|
|
428
435
|
artifactIds: idsFromCollection(lifecycle.artifacts, "artifacts"),
|
|
429
436
|
evidenceIds: idsFromCollection(lifecycle.evidence, "evidence"),
|
|
430
437
|
workUnitIds: idsFromCollection(lifecycle.work_units, "work_units"),
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { SHA256, createIdentityProvider, identityEquals, parseIdentity, sha256Identity } from "./content-identity.mjs";
|
|
4
|
+
|
|
5
|
+
// Records written by create-yss-spec historically store a bare sha256 hex in
|
|
6
|
+
// contentHash. Normalize bare digests to their algorithm-tagged identity so the
|
|
7
|
+
// comparison is by algorithm and value, never by string shape alone.
|
|
8
|
+
export function normalizeRecordedIdentity(value) {
|
|
9
|
+
if (typeof value !== "string") return null;
|
|
10
|
+
if (parseIdentity(value)) return value;
|
|
11
|
+
if (/^[0-9a-f]{64}$/.test(value)) return "sha256:" + value;
|
|
12
|
+
if (/^[0-9a-f]{40}$/.test(value)) return "git-sha1:" + value;
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const DRIFT_EXIT = { clean: 0, drift: 1, usage: 2, environment: 3 };
|
|
17
|
+
|
|
18
|
+
// Classify every recorded managed asset. "not-installed" means nothing was ever
|
|
19
|
+
// recorded for an expected asset, "missing" means it was recorded and is now
|
|
20
|
+
// gone, "drifted" means it was recorded and its content changed.
|
|
21
|
+
export function classifyManagedFiles({ root, managedFiles = {}, expected = [], provider = null, allowCustomizations = false } = {}) {
|
|
22
|
+
const identity = provider || createIdentityProvider(root);
|
|
23
|
+
const entries = [];
|
|
24
|
+
const recorded = new Set(Object.keys(managedFiles));
|
|
25
|
+
for (const [ref, record] of Object.entries(managedFiles).sort(([left], [right]) => (left < right ? -1 : 1))) {
|
|
26
|
+
const info = lstatSafe(path.join(root, ref));
|
|
27
|
+
const customizable = allowCustomizations && record.ownership === "managed-customizable";
|
|
28
|
+
const expectedIdentity = customizable ? null : normalizeRecordedIdentity(record.identity ?? record.contentHash ?? null);
|
|
29
|
+
if (!info) { entries.push({ ref, kind: "missing", expected: expectedIdentity, actual: null }); continue; }
|
|
30
|
+
// Customization permits different file content, not missing, unreadable or
|
|
31
|
+
// replaced paths. Generated assets continue to require their recorded hash.
|
|
32
|
+
if (customizable && !info.isFile()) {
|
|
33
|
+
entries.push({ ref, kind: "drifted", expected: null, actual: null, error: "customizable-asset-must-be-file" });
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Compare like with like: a recorded sha256 digest must be matched against a
|
|
37
|
+
// freshly computed sha256, never against a differently-versioned Git identity.
|
|
38
|
+
const parsed = parseIdentity(expectedIdentity);
|
|
39
|
+
// A directory, a broken symlink or an unreadable path must surface as drift,
|
|
40
|
+
// never as an uncaught exception.
|
|
41
|
+
let actual = null;
|
|
42
|
+
let error = null;
|
|
43
|
+
try {
|
|
44
|
+
// A cached Git identity cannot prove that a permitted custom file is
|
|
45
|
+
// currently readable. Read its actual bytes before accepting it.
|
|
46
|
+
actual = customizable || (parsed && parsed.algo === SHA256) ? sha256Identity(readFileSync(path.join(root, ref))) : identity.identityFor(ref).identity;
|
|
47
|
+
} catch (cause) { actual = null; error = cause.message; }
|
|
48
|
+
if (!expectedIdentity) { entries.push({ ref, kind: error || (customizable && actual === null) ? "drifted" : "ok", expected: null, actual, ...(error ? { error } : {}) }); continue; }
|
|
49
|
+
const kind = identityEquals(expectedIdentity, actual) ? "ok" : "drifted";
|
|
50
|
+
const diagnosis = error ?? (actual === null ? "unreadable-or-unresolved" : null);
|
|
51
|
+
entries.push({ ref, kind, expected: expectedIdentity, actual, ...(diagnosis ? { error: diagnosis } : {}) });
|
|
52
|
+
}
|
|
53
|
+
for (const ref of [...expected].sort()) {
|
|
54
|
+
if (recorded.has(ref) || existsSync(path.join(root, ref))) continue;
|
|
55
|
+
entries.push({ ref, kind: "not-installed", expected: null, actual: null });
|
|
56
|
+
}
|
|
57
|
+
const summary = { ok: 0, not_installed: 0, missing: 0, drifted: 0, obsolete: 0 };
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const key = entry.kind === "not-installed" ? "not_installed" : entry.kind;
|
|
60
|
+
summary[key] += 1;
|
|
61
|
+
}
|
|
62
|
+
return { entries, summary };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function buildDriftReport({ scope, root, provider = null, managedFiles = {}, expected = [], asOf = new Date().toISOString(), allowCustomizations = false } = {}) {
|
|
66
|
+
if (!["template-source", "project-instance"].includes(scope)) throw new TypeError("未知 drift-report scope: " + scope);
|
|
67
|
+
const identity = provider || createIdentityProvider(root);
|
|
68
|
+
const { entries, summary } = classifyManagedFiles({ root, managedFiles, expected, provider: identity, allowCustomizations: scope === "project-instance" && allowCustomizations });
|
|
69
|
+
return {
|
|
70
|
+
schema_version: 1,
|
|
71
|
+
kind: "drift-report",
|
|
72
|
+
as_of: asOf,
|
|
73
|
+
scope,
|
|
74
|
+
identity: { algo: identity.algo, source: identity.available ? "index" : "sha256-fallback" },
|
|
75
|
+
entries,
|
|
76
|
+
summary,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function driftReportExit(report) {
|
|
81
|
+
return report.summary.missing || report.summary.drifted || report.summary.obsolete || report.summary.not_installed
|
|
82
|
+
? DRIFT_EXIT.drift
|
|
83
|
+
: DRIFT_EXIT.clean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function short(value) {
|
|
87
|
+
return typeof value === "string" ? value.slice(0, 18) : String(value);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function formatDriftReport(report) {
|
|
91
|
+
const lines = ["drift-report [" + report.scope + "] identity=" + report.identity.algo + "/" + report.identity.source];
|
|
92
|
+
for (const entry of report.entries) {
|
|
93
|
+
if (entry.kind === "ok") continue;
|
|
94
|
+
const detail = entry.expected ? " (expected " + short(entry.expected) + ", actual " + short(entry.actual) + ")" : "";
|
|
95
|
+
lines.push(" " + entry.kind + ": " + entry.ref + detail);
|
|
96
|
+
}
|
|
97
|
+
lines.push(" summary: ok=" + report.summary.ok + " not-installed=" + report.summary.not_installed + " missing=" + report.summary.missing + " drifted=" + report.summary.drifted + " obsolete=" + report.summary.obsolete);
|
|
98
|
+
return lines.join("\n");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Expected assets the distribution says should exist but that were never recorded.
|
|
102
|
+
export function expectedFromDistribution(metadata = {}) {
|
|
103
|
+
const expected = [];
|
|
104
|
+
for (const skill of metadata.distribution?.installedSkills ?? []) expected.push(".agents/skills/" + skill);
|
|
105
|
+
return expected;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function lstatSafe(target) {
|
|
109
|
+
try { return lstatSync(target); } catch (error) { if (error.code === "ENOENT") return null; throw error; }
|
|
110
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {countersignRuleForGate} from './digital-human-roles.mjs';
|
|
2
|
+
import {approvalExpectationForBoundAsset} from './approval-consumption.mjs';
|
|
1
3
|
import {assertApprovedExecutionContext} from './approved-execution-context.mjs';
|
|
2
4
|
import {createHash} from 'node:crypto';
|
|
3
5
|
import { realpathSync } from 'node:fs';
|
|
@@ -113,7 +115,8 @@ export function verifyExistingArchitecture(identity,bindings,{root,registry,exec
|
|
|
113
115
|
const review=bound(root,baseline.boundary_review);
|
|
114
116
|
const rolesFile=path.join(root,'.template-spec/agents/digital-human-roles.yaml');
|
|
115
117
|
const roles=parse(readFileSync(rolesFile));
|
|
116
|
-
|
|
118
|
+
const reviewBoundary=['check.architecture-reviewed','gate.technical-design-approved'].find(boundary=>countersignRuleForGate(roles.gate_policy,boundary));
|
|
119
|
+
validateApprovalRecord(review,{rolesDoc:roles,requireApproved:true,root,expected:approvalExpectationForBoundAsset(reviewBoundary,bindings.manifest,{root})});
|
|
117
120
|
requireThat(['check.architecture-reviewed','gate.technical-design-approved'].includes(review.gate_id)&&text(baseline.id)&&text(baseline.version),'ARCH_REVIEW_MISSING','需要架构边界审查');
|
|
118
121
|
const basis=existingArchitectureDigest(Object.fromEntries(Object.entries(baseline).filter(([k])=>k!=='boundary_review')));
|
|
119
122
|
requireThat(review.artifact_bindings?.some(x=>x.id===baseline.id&&x.version===baseline.version&&x.digest===basis),'ARCH_REVIEW_STALE','架构审查未绑定当前基线');
|