create-yss-spec 3.5.2 → 3.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/template/asset-runtime.js +3 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/codebase-design/SKILL.md +4 -0
- package/template/{.codex/skills/improve-codebase-architecture/SKILL.md → .agents/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.agents/skills/frontend-commit/SKILL.md +4 -93
- package/template/.agents/skills/git-commit-core/SKILL.md +18 -0
- package/template/.agents/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.agents/skills/llm-wiki/SKILL.md +12 -13
- package/template/.agents/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.agents/skills/llm-wiki/references/compile.md +21 -114
- package/template/.agents/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.agents/skills/llm-wiki/references/lint.md +9 -46
- package/template/.agents/skills/llm-wiki/references/query.md +9 -18
- package/template/.agents/skills/llm-wiki/references/schema.md +56 -29
- package/template/.agents/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.agents/skills/llm-wiki/references/writing.md +4 -4
- package/template/.agents/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.agents/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.agents/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.agents/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.agents/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.agents/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.agents/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.agents/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.agents/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.agents/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.agents/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.agents/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.agents/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.agents/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.agents/skills/prototype/LOGIC.md +1 -1
- package/template/.agents/skills/prototype/SKILL.md +5 -19
- package/template/.agents/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.agents/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.agents/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.agents/skills/yss-research/SKILL.md +4 -0
- package/template/.codex/skills/codebase-design/SKILL.md +4 -0
- package/template/{.pi/skills/improve-codebase-architecture/SKILL.md → .codex/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.codex/skills/frontend-commit/SKILL.md +4 -93
- package/template/.codex/skills/git-commit-core/SKILL.md +18 -0
- package/template/.codex/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.codex/skills/llm-wiki/SKILL.md +12 -13
- package/template/.codex/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.codex/skills/llm-wiki/references/compile.md +21 -114
- package/template/.codex/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.codex/skills/llm-wiki/references/lint.md +9 -46
- package/template/.codex/skills/llm-wiki/references/query.md +9 -18
- package/template/.codex/skills/llm-wiki/references/schema.md +56 -29
- package/template/.codex/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.codex/skills/llm-wiki/references/writing.md +4 -4
- package/template/.codex/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.codex/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.codex/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.codex/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.codex/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.codex/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.codex/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.codex/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.codex/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.codex/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.codex/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.codex/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.codex/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.codex/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.codex/skills/prototype/LOGIC.md +1 -1
- package/template/.codex/skills/prototype/SKILL.md +5 -19
- package/template/.codex/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.codex/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.codex/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.codex/skills/yss-research/SKILL.md +4 -0
- package/template/.cursor/skills/codebase-design/SKILL.md +4 -0
- package/template/.cursor/skills/{improve-codebase-architecture/SKILL.md → codebase-design/references/architecture-audit.md} +3 -9
- package/template/.cursor/skills/frontend-commit/SKILL.md +4 -93
- package/template/.cursor/skills/git-commit-core/SKILL.md +18 -0
- package/template/.cursor/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.cursor/skills/llm-wiki/SKILL.md +12 -13
- package/template/.cursor/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.cursor/skills/llm-wiki/references/compile.md +21 -114
- package/template/.cursor/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.cursor/skills/llm-wiki/references/lint.md +9 -46
- package/template/.cursor/skills/llm-wiki/references/query.md +9 -18
- package/template/.cursor/skills/llm-wiki/references/schema.md +56 -29
- package/template/.cursor/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.cursor/skills/llm-wiki/references/writing.md +4 -4
- package/template/.cursor/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.cursor/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.cursor/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.cursor/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.cursor/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.cursor/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.cursor/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.cursor/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.cursor/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.cursor/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.cursor/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.cursor/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.cursor/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.cursor/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.cursor/skills/prototype/LOGIC.md +1 -1
- package/template/.cursor/skills/prototype/SKILL.md +5 -19
- package/template/.cursor/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.cursor/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.cursor/skills/yss-research/SKILL.md +4 -0
- package/template/.pi/skills/codebase-design/SKILL.md +4 -0
- package/template/{.agents/skills/improve-codebase-architecture/SKILL.md → .pi/skills/codebase-design/references/architecture-audit.md} +3 -9
- package/template/.pi/skills/frontend-commit/SKILL.md +4 -93
- package/template/.pi/skills/git-commit-core/SKILL.md +18 -0
- package/template/.pi/skills/java-backend-commit/SKILL.md +4 -96
- package/template/.pi/skills/llm-wiki/SKILL.md +12 -13
- package/template/.pi/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
- package/template/.pi/skills/llm-wiki/references/compile.md +21 -114
- package/template/.pi/skills/llm-wiki/references/ingest.md +8 -33
- package/template/.pi/skills/llm-wiki/references/lint.md +9 -46
- package/template/.pi/skills/llm-wiki/references/query.md +9 -18
- package/template/.pi/skills/llm-wiki/references/schema.md +56 -29
- package/template/.pi/skills/llm-wiki/references/transactions.md +48 -0
- package/template/.pi/skills/llm-wiki/references/writing.md +4 -4
- package/template/.pi/skills/llm-wiki/scripts/advise.mjs +46 -58
- package/template/.pi/skills/llm-wiki/scripts/advise.test.mjs +11 -16
- package/template/.pi/skills/llm-wiki/scripts/core.mjs +262 -0
- package/template/.pi/skills/llm-wiki/scripts/extract.mjs +35 -18
- package/template/.pi/skills/llm-wiki/scripts/extract.test.mjs +5 -8
- package/template/.pi/skills/llm-wiki/scripts/feedback.mjs +51 -0
- package/template/.pi/skills/llm-wiki/scripts/inventory.mjs +43 -171
- package/template/.pi/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
- package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
- package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
- package/template/.pi/skills/llm-wiki/scripts/migrate.mjs +51 -0
- package/template/.pi/skills/llm-wiki/scripts/query.mjs +149 -0
- package/template/.pi/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
- package/template/.pi/skills/llm-wiki/scripts/sources.mjs +166 -0
- package/template/.pi/skills/llm-wiki/scripts/transaction.mjs +384 -0
- package/template/.pi/skills/llm-wiki/scripts/v2.test.mjs +354 -0
- package/template/.pi/skills/prototype/LOGIC.md +1 -1
- package/template/.pi/skills/prototype/SKILL.md +5 -19
- package/template/.pi/skills/setup-matt-pocock-skills/SKILL.md +3 -3
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
- package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +8 -8
- package/template/.pi/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +20 -4
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.pi/skills/yss-product-lifecycle/references/plan-requirements.md +10 -0
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.pi/skills/yss-research/SKILL.md +4 -0
- package/template/.template-spec/agents/README.md +1 -1
- package/template/.template-spec/agents/digital-human-roles.yaml +1 -1
- package/template/.template-spec/agents/skill-migrations.md +15 -0
- package/template/.template-spec/agents/yss-skill-registry.yaml +10 -29
- package/template/.template-spec/architecture/README.md +3 -34
- package/template/.template-spec/plan/templates/competitive-analysis-template.md +2 -2
- package/template/.template-spec/process/contract-reading.md +24 -0
- package/template/.template-spec/process/lifecycle-registry-baseline.json +3 -1
- package/template/.template-spec/process/lifecycle-registry.yaml +6 -0
- package/template/.template-spec/process/research-completion.md +23 -0
- package/template/.template-spec/process/schemas/digital-human-task-package.schema.json +202 -12
- package/template/.template-spec/process/schemas/frontend-implementation-evidence.schema.json +7 -15
- package/template/.template-spec/process/subagent-collaboration.md +8 -0
- package/template/.template-spec/process/templates/frontend-implementation-verification-template.yaml +15 -1
- package/template/AGENTS.md +1 -1
- package/template/CONTEXT.md +5 -1
- package/template/README.md +12 -24
- package/template/scripts/contract +5 -5
- package/template/scripts/lib/contract-views.mjs +57 -2
- package/template/scripts/lib/execution-evidence.mjs +51 -0
- package/template/scripts/lib/harness-execution-scope.mjs +1 -1
- package/template/scripts/lib/implementation-contract-compiler.mjs +2 -0
- package/template/scripts/lib/lifecycle-context-query.mjs +15 -3
- package/template/scripts/lib/lifecycle-status.mjs +32 -6
- package/template/scripts/lib/lifecycle-transition.mjs +19 -1
- package/template/scripts/lib/maintenance-research.mjs +63 -0
- package/template/scripts/lib/read-only-intake.mjs +132 -0
- package/template/scripts/lib/skill-registry.mjs +2 -1
- package/template/scripts/lib/skill-supply-chain.mjs +4 -0
- package/template/scripts/lib/slice-task-package.mjs +1 -1
- package/template/scripts/lib/task-package.mjs +9 -2
- package/template/scripts/lifecycle-status +2 -2
- package/template/scripts/prepare-read-only-intake +16 -0
- package/template/scripts/run-read-only-intake +14 -0
- package/template/scripts/verify-digital-human-task-package +2 -2
- package/template/scripts/verify-frontend-implementation-evidence +24 -1
- package/template/scripts/verify-maintenance-research +13 -0
- package/template/skills-lock.json +19 -76
- package/template.manifest.json +118 -29
- package/template.snapshot.json +5 -6
- package/template/.agents/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.agents/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.agents/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.agents/skills/prototype/UI.md +0 -112
- package/template/.agents/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.agents/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.agents/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.agents/skills/wait-what/SKILL.md +0 -7
- package/template/.agents/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.codex/skills/data-analytics/.app.json +0 -84
- package/template/.codex/skills/data-analytics/.codex-plugin/plugin.json +0 -66
- package/template/.codex/skills/data-analytics/.mcp.json +0 -30
- package/template/.codex/skills/data-analytics/AGENTS.md +0 -20
- package/template/.codex/skills/data-analytics/DEPENDENCIES.MD +0 -27
- package/template/.codex/skills/data-analytics/README.md +0 -60
- package/template/.codex/skills/data-analytics/__yss_dotfile__.gitignore +0 -2
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part005 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part006 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part005 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part006 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part007 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-small.svg +0 -5
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html +0 -16
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part001 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part002 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part003 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part004 +0 -1
- package/template/.codex/skills/data-analytics/assets/datascience.png +0 -0
- package/template/.codex/skills/data-analytics/assets/datascience.svg +0 -10
- package/template/.codex/skills/data-analytics/mcp/server.cjs +0 -2964
- package/template/.codex/skills/data-analytics/package-lock.json +0 -3048
- package/template/.codex/skills/data-analytics/package.json +0 -43
- package/template/.codex/skills/data-analytics/scripts/normalize-widget-assets.mjs +0 -75
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +0 -137
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/analyze-data-quality/references/quality-checks.md +0 -29
- package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +0 -148
- package/template/.codex/skills/data-analytics/skills/build-dashboard/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/bi-platform-dashboard.md +0 -18
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/html-dashboard.md +0 -24
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/mcp-artifact-dashboard.md +0 -71
- package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/streamlit-dashboard.md +0 -85
- package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +0 -207
- package/template/.codex/skills/data-analytics/skills/build-report/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/assets/executive-report-shell.html +0 -70
- package/template/.codex/skills/data-analytics/skills/build-report/assets/technical-report-shell.html +0 -66
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/SKILL.md +0 -108
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/__init__.py +0 -1
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/cli.py +0 -52
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/constants.py +0 -61
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/docx_writer.py +0 -362
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/html_parser.py +0 -829
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/model.py +0 -30
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/plan.py +0 -127
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/quality.py +0 -374
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/rendering.py +0 -613
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/table_utils.py +0 -54
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/utils.py +0 -16
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc_plan.py +0 -9
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/tests/test_delivery_plan.py +0 -45
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/SKILL.md +0 -77
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/scripts/report_to_google_slides.py +0 -2379
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/SKILL.md +0 -88
- package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/executive-report.md +0 -97
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/mcp-app-report.md +0 -59
- package/template/.codex/skills/data-analytics/skills/build-report/specifications/technical-report.md +0 -75
- package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +0 -103
- package/template/.codex/skills/data-analytics/skills/design-kpis/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +0 -68
- package/template/.codex/skills/data-analytics/skills/gather-business-context/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/index/SKILL.md +0 -251
- package/template/.codex/skills/data-analytics/skills/index/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +0 -131
- package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +0 -141
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/kpi-reporting/references/report-templates.md +0 -32
- package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +0 -106
- package/template/.codex/skills/data-analytics/skills/market-sizing/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +0 -130
- package/template/.codex/skills/data-analytics/skills/metric-diagnostics/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +0 -141
- package/template/.codex/skills/data-analytics/skills/product-business-analysis/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +0 -178
- package/template/.codex/skills/data-analytics/skills/spreadsheets/agents/openai.yaml +0 -9
- package/template/.codex/skills/data-analytics/skills/spreadsheets/assets/file-spreadsheet.png +0 -0
- package/template/.codex/skills/data-analytics/skills/spreadsheets/charts.md +0 -31
- package/template/.codex/skills/data-analytics/skills/spreadsheets/references/artifact_tool_api.md +0 -466
- package/template/.codex/skills/data-analytics/skills/spreadsheets/style_guidelines.md +0 -99
- package/template/.codex/skills/data-analytics/skills/user-context/SKILL.md +0 -197
- package/template/.codex/skills/data-analytics/skills/user-context/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/automation-config.md +0 -26
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/source-category-config.json +0 -51
- package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/user-context-config.md +0 -66
- package/template/.codex/skills/data-analytics/skills/user-context/references/automation.md +0 -69
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-examples.md +0 -204
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-state-template.json +0 -87
- package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding.md +0 -497
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/connector-playbook.md +0 -74
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/setup.md +0 -65
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/skill-template.md +0 -160
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/source-intake.md +0 -75
- package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/weekly-polling-automation.md +0 -96
- package/template/.codex/skills/data-analytics/skills/user-context/references/source-category-runtime.md +0 -263
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/data_analytics_preflight.py +0 -1462
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/init_user_context_state.py +0 -128
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/reset_user_context_state.py +0 -101
- package/template/.codex/skills/data-analytics/skills/user-context/scripts/validate_user_context_preflight.py +0 -499
- package/template/.codex/skills/data-analytics/skills/user-context/tests/test_state_helpers.py +0 -978
- package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +0 -126
- package/template/.codex/skills/data-analytics/skills/validate-data/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/validate-data/references/validation-methods.md +0 -70
- package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +0 -157
- package/template/.codex/skills/data-analytics/skills/visualize-data/agents/openai.yaml +0 -6
- package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md +0 -774
- package/template/.codex/skills/data-analytics/src/DESIGN.md +0 -222
- package/template/.codex/skills/data-analytics/src/analytics-app/App.tsx +0 -3666
- package/template/.codex/skills/data-analytics/src/analytics-app/analytics-layout.test.mjs +0 -136
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartFrame.tsx +0 -54
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartLegend.tsx +0 -96
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartRenderer.tsx +0 -1647
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartTooltip.tsx +0 -245
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-app-helpers.tsx +0 -462
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-capabilities.ts +0 -107
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-compatibility.ts +0 -164
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-contract.ts +0 -192
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-theme.ts +0 -203
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-tokens.css +0 -619
- package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-transforms.ts +0 -402
- package/template/.codex/skills/data-analytics/src/analytics-app/fonts/SystemSansVariableVF.woff2 +0 -0
- package/template/.codex/skills/data-analytics/src/analytics-app/imageExport.ts +0 -370
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/AnalyticsLayoutCanvas.tsx +0 -536
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/RichMarkdown.tsx +0 -681
- package/template/.codex/skills/data-analytics/src/analytics-app/layout/analyticsLayoutCore.ts +0 -164
- package/template/.codex/skills/data-analytics/src/analytics-app/main.tsx +0 -21
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/chart_contract.py +0 -472
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/check_analytics_app_runtime_links.py +0 -75
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/design_contract.py +0 -142
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/package_utils.py +0 -142
- package/template/.codex/skills/data-analytics/src/analytics-app/scripts/tests/test_package_utils.py +0 -377
- package/template/.codex/skills/data-analytics/src/analytics-app/styles.css +0 -3468
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.d.ts +0 -44
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.jsx +0 -639
- package/template/.codex/skills/data-analytics/src/analytics-app/tables/data-table.css +0 -327
- package/template/.codex/skills/data-analytics/src/analytics-app/tokens.css +0 -225
- package/template/.codex/skills/data-analytics/src/analytics-app/types.ts +0 -204
- package/template/.codex/skills/data-analytics/src/analytics-app-core.md +0 -85
- package/template/.codex/skills/data-analytics/src/codex-style-contract.md +0 -30
- package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.html +0 -12
- package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.jsx +0 -1008
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.css +0 -2117
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.html +0 -122
- package/template/.codex/skills/data-analytics/src/datascience-chart-widget.js +0 -3588
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.css +0 -483
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.html +0 -32
- package/template/.codex/skills/data-analytics/src/datascience-table-widget.js +0 -333
- package/template/.codex/skills/data-analytics/src/mcp-host.js +0 -153
- package/template/.codex/skills/data-analytics/src/recharts-config.js +0 -315
- package/template/.codex/skills/data-analytics/src/recharts-renderer.jsx +0 -294
- package/template/.codex/skills/data-analytics/src/sql-source-view.css +0 -33
- package/template/.codex/skills/data-analytics/src/sql-source-view.js +0 -157
- package/template/.codex/skills/data-analytics/src/styles/codex-theme.css +0 -121
- package/template/.codex/skills/data-analytics/src/table-renderer.jsx +0 -28
- package/template/.codex/skills/data-analytics/tests/chart-transforms.test.mjs +0 -87
- package/template/.codex/skills/data-analytics/tests/funnel-smoke.html +0 -105
- package/template/.codex/skills/data-analytics/tests/inline-widget-compare.html +0 -233
- package/template/.codex/skills/data-analytics/tests/mcp-server.test.mjs +0 -1500
- package/template/.codex/skills/data-analytics/tests/native-style-contract.test.mjs +0 -219
- package/template/.codex/skills/data-analytics/tests/recharts-config.test.mjs +0 -144
- package/template/.codex/skills/data-analytics/tests/recharts-renderer.test.mjs +0 -11
- package/template/.codex/skills/data-analytics/tests/rich-markdown.test.mjs +0 -54
- package/template/.codex/skills/data-analytics/tests/widget-render-harness.html +0 -321
- package/template/.codex/skills/data-analytics/tsconfig.json +0 -19
- package/template/.codex/skills/data-analytics/vite.config.ts +0 -46
- package/template/.codex/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.codex/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.codex/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.codex/skills/prototype/UI.md +0 -112
- package/template/.codex/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.codex/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.codex/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.codex/skills/wait-what/SKILL.md +0 -7
- package/template/.codex/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.cursor/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.cursor/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.cursor/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.cursor/skills/prototype/UI.md +0 -112
- package/template/.cursor/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.cursor/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.cursor/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.cursor/skills/wait-what/SKILL.md +0 -7
- package/template/.cursor/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.pi/skills/grill-with-docs/SKILL.md +0 -20
- package/template/.pi/skills/grill-with-docs/agents/openai.yaml +0 -5
- package/template/.pi/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
- package/template/.pi/skills/prototype/UI.md +0 -112
- package/template/.pi/skills/setup-matt-pocock-skills/domain.md +0 -37
- package/template/.pi/skills/to-questionnaire/SKILL.md +0 -55
- package/template/.pi/skills/to-questionnaire/agents/openai.yaml +0 -5
- package/template/.pi/skills/wait-what/SKILL.md +0 -7
- package/template/.pi/skills/wait-what/agents/openai.yaml +0 -5
- package/template/.template-spec/agents/domain.md +0 -31
- /package/template/.agents/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.codex/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.cursor/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
- /package/template/.pi/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {readFileSync,existsSync} from './validation-phase.mjs';
|
|
2
|
+
import {safe, hash} from './strategic-handoff-io.mjs';
|
|
3
|
+
|
|
4
|
+
/** Checks binding, not the truth of arbitrary prose. Owner tests/review remain mandatory. */
|
|
5
|
+
export function executionEvidenceBlockers(result, contract, current) {
|
|
6
|
+
const blockers=[];
|
|
7
|
+
if(result.evidence_binding_version!==1)return ['legacy-evidence-binding-missing'];
|
|
8
|
+
const unit=contract.work_units.find(u=>u.id===result.work_unit_id);
|
|
9
|
+
if(!unit)return ['work-unit-mismatch'];
|
|
10
|
+
try {
|
|
11
|
+
const approved=current.approved_slice;
|
|
12
|
+
if(!approved || result.consumed_contract?.contract_digest!==approved.digest || hash(readFileSync(safe(current.root,approved.ref)))!==approved.digest)blockers.push('evidence-contract-digest-mismatch');
|
|
13
|
+
const evidence=result.evidence_files||[];
|
|
14
|
+
const checks=unit.work_unit.verification;
|
|
15
|
+
const evidenceRoot=contract.repositories?unit.project_root:current.root;
|
|
16
|
+
for(const check of checks) {
|
|
17
|
+
const rows=(result.verification_results||[]).filter(r=>r.verification_id===check.id);
|
|
18
|
+
if(rows.length!==1){blockers.push('verification-id-missing-or-duplicate');continue;}
|
|
19
|
+
const row=rows[0];
|
|
20
|
+
if(row.command!==check.command||row.cwd!==check.cwd||row.exit_code!==0||!Number.isFinite(Date.parse(row.executed_at)))blockers.push('verification-binding-mismatch');
|
|
21
|
+
if(!Array.isArray(row.acceptance_refs)||row.acceptance_refs.length!==new Set(row.acceptance_refs).size||JSON.stringify([...row.acceptance_refs].sort())!==JSON.stringify([...check.acceptance_refs].sort()))blockers.push('acceptance-evidence-coverage-missing');
|
|
22
|
+
if(!Array.isArray(row.evidence_refs)||!check.expected_evidence.every(ref=>row.evidence_refs.includes(ref)))blockers.push('verification-evidence-link-missing');
|
|
23
|
+
const covered=new Set();
|
|
24
|
+
for(const ref of row.evidence_refs||[]) {
|
|
25
|
+
const matches=evidence.filter(e=>typeof e==='object'&&e.path===ref&&(!contract.repositories||e.project_root===unit.project_root));
|
|
26
|
+
if(!matches.length)blockers.push('verification-evidence-link-missing');
|
|
27
|
+
for(const entry of matches) {
|
|
28
|
+
if(!check.acceptance_refs.includes(entry.behavior_ref))blockers.push('evidence-behavior-unrelated');
|
|
29
|
+
else covered.add(entry.behavior_ref);
|
|
30
|
+
if(hash(readFileSync(safe(evidenceRoot,ref)))!==entry.digest)blockers.push('evidence-digest-mismatch');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if(check.acceptance_refs.some(id=>!covered.has(id)))blockers.push('acceptance-evidence-coverage-missing');
|
|
34
|
+
}
|
|
35
|
+
// Bind declared execution inputs too: changed source bytes cannot reuse an earlier result.
|
|
36
|
+
if(!Array.isArray(result.source_bindings)||!result.source_bindings.length)blockers.push('execution-source-bindings-missing');
|
|
37
|
+
for(const entry of result.source_bindings||[]) {
|
|
38
|
+
const root=entry.project_root||unit.project_root;
|
|
39
|
+
const allowedRoots=new Set([unit.project_root,...checks.flatMap(check=>check.dependency_roots||[])]);
|
|
40
|
+
if(!allowedRoots.has(root)||(contract.repositories&&!contract.repositories[root])){blockers.push('execution-source-repository-mismatch');continue;}
|
|
41
|
+
if(entry.deleted===true) {
|
|
42
|
+
if(existsSync(safe(root,entry.path,{missing:true})) || entry.digest!==null)blockers.push('execution-source-drift');
|
|
43
|
+
} else if(hash(readFileSync(safe(root,entry.path)))!==entry.digest)blockers.push('execution-source-drift');
|
|
44
|
+
}
|
|
45
|
+
for(const changed of result.changed_files||[]) {
|
|
46
|
+
const ref=typeof changed==='string'?changed:changed.path;
|
|
47
|
+
if(!result.source_bindings?.some(b=>b.path===ref&&(b.project_root||unit.project_root)===(typeof changed==='object'&&changed.project_root||unit.project_root)))blockers.push('changed-source-binding-missing');
|
|
48
|
+
}
|
|
49
|
+
} catch(error) {blockers.push(`execution-evidence-unreadable: ${error.message}`);}
|
|
50
|
+
return [...new Set(blockers)];
|
|
51
|
+
}
|
|
@@ -33,7 +33,7 @@ function activeProfile(root) {
|
|
|
33
33
|
export function enforceHarnessTaskScope(task,{root=ROOT}={}) {
|
|
34
34
|
const scope=loadExecutionScope(root);
|
|
35
35
|
if(scope) {
|
|
36
|
-
assertScopeWorkUnit(task.contract?.kind==='slice-implementation'?'work-unit.slice-implementation':task.work_unit_id,{root});
|
|
36
|
+
assertScopeWorkUnit(task.contract?.kind==='slice-implementation'?'work-unit.slice-implementation':task.work_unit_id,{root,readOnly:task.contract?.kind==='read-only-intake'});
|
|
37
37
|
ensure(task.role_id!=='role.frontend-engineer','后端职责不允许派发前端实现');
|
|
38
38
|
ensure(task.allowed_write_paths.every(ref=>!/^apps\/frontend(?:\/|$)/.test(ref)),'禁止写入前端工程');
|
|
39
39
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveBackendPlatform, resolveComponentCapabilities } from "./backend-platform.mjs";
|
|
2
|
+
import { executionEvidenceBlockers } from './execution-evidence.mjs';
|
|
2
3
|
import { safe } from './strategic-handoff-io.mjs';
|
|
3
4
|
import { selectSliceWorkUnit, normalizeSliceContract, withinSlicePath } from './slice-contract.mjs';
|
|
4
5
|
import { createApprovedExecutionContext, createApprovedRecompilationContext, assertApprovedExecutionContext } from './approved-execution-context.mjs';
|
|
@@ -349,6 +350,7 @@ export function validateExecutionResult(result, contract, current) {
|
|
|
349
350
|
else if (item.exit_code !== 0) blockers.push("verification-failed");
|
|
350
351
|
}
|
|
351
352
|
if(contract.schema_version===3) {
|
|
353
|
+
blockers.push(...executionEvidenceBlockers(result, contract, {...current, root: current.root || ROOT}));
|
|
352
354
|
const unit=contract.work_units.find(item=>item.id===result.work_unit_id);
|
|
353
355
|
if(!unit)blockers.push('work-unit-mismatch');
|
|
354
356
|
else {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadExecutionScope, assertScopeWorkUnit, scopedNextRoutes } from './lifecycle-execution-scope.mjs';
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { readFileSync } from "
|
|
3
|
+
import { readFileSync, withValidationPhase, validationDependencies } from "./validation-phase.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parseDocument } from "../vendor/yaml.mjs";
|
|
6
6
|
import { ROOT, loadRegistry, semanticDigest, validateRegistry } from "./lifecycle-registry.mjs";
|
|
@@ -63,11 +63,19 @@ function selectedSkills(route, skillRegistry) {
|
|
|
63
63
|
return skillRegistry.skills.filter((skill) => ids.has(skill.id));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function queryLifecycleContext(
|
|
66
|
+
export function queryLifecycleContext(options = {}) {
|
|
67
|
+
return withValidationPhase({ root: ROOT, purpose: "lifecycle-context-query", readOnly: true }, () => querySnapshot(options));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function querySnapshot({ mode, stageId, workUnitId, include = [] } = {}) {
|
|
67
71
|
if (!mode && !stageId && !workUnitId && include.length === 0) {
|
|
68
72
|
throw new TypeError("至少提供 --mode、--stage、--work-unit 或 --include 之一");
|
|
69
73
|
}
|
|
70
74
|
|
|
75
|
+
const identity = loadYaml("yss-project.yaml", "仓库身份");
|
|
76
|
+
if (identity.schema_version !== 1 || !["template-source", "project-instance"].includes(identity.repository_mode)) {
|
|
77
|
+
throw new TypeError("仓库身份或版本无效");
|
|
78
|
+
}
|
|
71
79
|
const scope = loadExecutionScope();
|
|
72
80
|
if (workUnitId) assertScopeWorkUnit(workUnitId, { readOnly: true });
|
|
73
81
|
const lifecycle = validateRegistry(loadRegistry());
|
|
@@ -114,9 +122,11 @@ export function queryLifecycleContext({ mode, stageId, workUnitId, include = []
|
|
|
114
122
|
work_unit: workUnitId ?? null,
|
|
115
123
|
},
|
|
116
124
|
sources: {
|
|
125
|
+
repository_identity: { ref: "yss-project.yaml", sha256: sha256(read("yss-project.yaml")) },
|
|
117
126
|
lifecycle_registry: {
|
|
118
127
|
ref: LIFECYCLE_REGISTRY_REF,
|
|
119
128
|
semantic_sha256: semanticDigest(lifecycle),
|
|
129
|
+
sha256: sha256(read(LIFECYCLE_REGISTRY_REF)),
|
|
120
130
|
status: lifecycle.status,
|
|
121
131
|
},
|
|
122
132
|
orchestration_contract: {
|
|
@@ -152,5 +162,7 @@ export function queryLifecycleContext({ mode, stageId, workUnitId, include = []
|
|
|
152
162
|
result.references = [...collectPathReferences(result), LIFECYCLE_REGISTRY_REF, ORCHESTRATION_CONTRACT_REF, SKILL_REGISTRY_REF]
|
|
153
163
|
.filter((value, index, all) => all.indexOf(value) === index)
|
|
154
164
|
.sort();
|
|
155
|
-
|
|
165
|
+
result.sources.read_set = validationDependencies().files.map(row=>({ref:path.relative(ROOT,row.file).split(path.sep).join("/"),sha256:row.digest})).sort((a,b)=>a.ref.localeCompare(b.ref,"en"));
|
|
166
|
+
const canonical = canonicalize(result);
|
|
167
|
+
return { ...canonical, context_sha256: sha256(JSON.stringify(canonical)) };
|
|
156
168
|
}
|
|
@@ -16,7 +16,7 @@ function source(root, ref) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/** Read-only projection; checkpoint, registry and orchestration remain authoritative. */
|
|
19
|
-
export function lifecycleStatus({ root, checkpointRef }) {
|
|
19
|
+
export function lifecycleStatus({ root, checkpointRef, taskPackageRef }) {
|
|
20
20
|
if (!root || !checkpointRef) throw new TypeError('root and checkpoint are required');
|
|
21
21
|
root = path.resolve(root);
|
|
22
22
|
const identity = source(root, 'yss-project.yaml').value;
|
|
@@ -76,10 +76,36 @@ export function lifecycleStatus({ root, checkpointRef }) {
|
|
|
76
76
|
check('stage-tracking', 'not-checked', [checkpointRef], '未登记追踪;按实例既有兼容或显式迁移入口处理,不自动补建');
|
|
77
77
|
}
|
|
78
78
|
if (value.status === 'blocked' && !diagnostics.some(x => x.severity === 'error')) issue('reason-missing', 'checkpoint 已标 blocked,原因未登记', checkpointRef, '补齐真实阻塞原因');
|
|
79
|
+
let taskSource, task, contractSource;
|
|
80
|
+
const recovery = {sequence: ['read-status', 'inspect-actual-result', 'verify-current-inputs', 'continue-or-reroute'], task_package_ref: taskPackageRef ?? null, contract_view: null, result_refs: [], prechecks: [], verification_items: [], checks: 'read-only; execution and approval not evaluated'};
|
|
81
|
+
if(taskPackageRef) {
|
|
82
|
+
try {
|
|
83
|
+
taskSource=source(root,taskPackageRef);task=taskSource.value;
|
|
84
|
+
if(task.work_unit_id!==value.next_work_unit && task.convergence?.parent_work_unit!==value.next_work_unit)throw Error('任务包与 checkpoint 工作单元不一致');
|
|
85
|
+
if(!['not-started','active','paused','resolved','failed'].includes(task.workflow_status))throw Error('任务运行状态未知');
|
|
86
|
+
recovery.prechecks.push({status:'not-checked',cwd:root,command:['node','scripts/verify-digital-human-task-package',taskPackageRef]});
|
|
87
|
+
if(task.contract?.kind==='slice-implementation') {
|
|
88
|
+
contractSource=source(root,task.contract.slice_contract_ref);
|
|
89
|
+
const c=contractSource.value.slice_contract||contractSource.value;
|
|
90
|
+
if(c.contract_id!==task.contract.contract_id||c.contract_version!==task.contract.contract_version)throw Error('任务与当前合同版本不一致');
|
|
91
|
+
recovery.contract_view={cwd:root,command:['node','scripts/contract','view',task.contract.slice_contract_ref,'--kind','slice','--profile','task','--unit',task.work_unit_id]};
|
|
92
|
+
const approval=task.contract.gate_refs?.[0];
|
|
93
|
+
recovery.prechecks.push({status:'not-checked',cwd:root,command:['node','scripts/slice-contract','verify',task.contract.slice_contract_ref,'--unit',task.work_unit_id,...(approval?['--approval-ref',approval]:[])],approval_scope:approval?'current-approval-required':'not-checked: approval reference missing'});
|
|
94
|
+
if(c.schema_version===3){
|
|
95
|
+
const unit=c.work_units?.find(x=>x.id===task.work_unit_id);
|
|
96
|
+
if(!unit)throw Error('当前合同不存在该工作单元');
|
|
97
|
+
recovery.verification_items=Object.entries(c.verification||{}).filter(([id,check])=>unit.verification_refs?.includes(id)||check.required_for_all===true).map(([id,check])=>({id,...check,status:'not-checked'}));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
recovery.result_refs=[...new Set([...(task.result?.evidence_refs||[]),...(task.verification_results||[]).map(x=>x.evidence_ref)].filter(Boolean))];
|
|
101
|
+
for(const ref of recovery.result_refs)readFileSync(safeTrackingPath(root,ref));
|
|
102
|
+
check('task-recovery','passed',[taskPackageRef,...recovery.result_refs],'仅读取任务身份、状态和结果引用;继续前仍须正式验收');
|
|
103
|
+
} catch(error) {issue('task-recovery-invalid',error.message,taskPackageRef,'核对任务身份与实际结果,再执行适用预检');}
|
|
104
|
+
}
|
|
79
105
|
const blockers = [...new Set(diagnostics.filter(x => x.severity === 'error').map(x => x.message))];
|
|
80
106
|
const next_step = {
|
|
81
107
|
action_type: 'verify', work_unit: value.next_work_unit ?? null, cwd: root,
|
|
82
|
-
command: null, input_refs: [checkpointRef],
|
|
108
|
+
command: null, input_refs: [checkpointRef,...(taskPackageRef?[taskPackageRef]:[])],
|
|
83
109
|
prerequisites: ['核验当前来源、Context、适用门禁与决定或延续', '核对当前范围、任务结果和允许写路径;输入变化时重验'],
|
|
84
110
|
};
|
|
85
111
|
let next_action;
|
|
@@ -89,10 +115,10 @@ export function lifecycleStatus({ root, checkpointRef }) {
|
|
|
89
115
|
} else if (value.status === 'paused-human-gate') {
|
|
90
116
|
next_step.action_type = 'wait';
|
|
91
117
|
next_action = '核对当前会签责任方、资产与决定范围;满足已登记恢复条件后复验';
|
|
92
|
-
} else if (activeItems.some(item => item.progress === 'running')) {
|
|
118
|
+
} else if (activeItems.some(item => item.progress === 'running') || task?.workflow_status === 'active') {
|
|
93
119
|
next_step.action_type = 'inspect';
|
|
94
120
|
next_action = '核对运行中任务身份与实际结果;状态未知时不得重复派发';
|
|
95
|
-
} else if (activeItems.length && activeItems.every(item => item.progress === 'completed')) {
|
|
121
|
+
} else if ((activeItems.length && activeItems.every(item => item.progress === 'completed')) || task?.workflow_status === 'resolved') {
|
|
96
122
|
next_step.action_type = 'inspect';
|
|
97
123
|
next_action = '核验已有完成证据并重算下一工作单元,不直接重做';
|
|
98
124
|
} else {
|
|
@@ -105,7 +131,7 @@ export function lifecycleStatus({ root, checkpointRef }) {
|
|
|
105
131
|
return {
|
|
106
132
|
schema_version: 1, read_only: true, stage: value.stage, checkpoint_status: value.status,
|
|
107
133
|
work_unit: value.next_work_unit ?? null, owner, blockers, next_action,
|
|
108
|
-
execution_authorization: 'not-evaluated', verification_scope, diagnostics, next_step,
|
|
109
|
-
source_digests: { checkpoint: { ref: checkpointRef, digest: checkpoint.digest }, registry: { ref: registryRef, digest: registry.digest }, orchestration: { ref: contractRef, digest: contract.digest } },
|
|
134
|
+
execution_authorization: 'not-evaluated', verification_scope, diagnostics, next_step, recovery,
|
|
135
|
+
source_digests: { checkpoint: { ref: checkpointRef, digest: checkpoint.digest }, registry: { ref: registryRef, digest: registry.digest }, orchestration: { ref: contractRef, digest: contract.digest }, ...(taskSource?{task:{ref:taskPackageRef,digest:taskSource.digest}}:{}), ...(contractSource?{slice_contract:{ref:task.contract.slice_contract_ref,digest:contractSource.digest}}:{}) },
|
|
110
136
|
};
|
|
111
137
|
}
|
|
@@ -14,6 +14,8 @@ import { loadApprovalRecord, validateApprovalRecord } from "./approval-record.mj
|
|
|
14
14
|
import { validateBackendReview } from "./backend-review.mjs";
|
|
15
15
|
import { validateJsonSchema } from "./json-schema.mjs";
|
|
16
16
|
import { ROOT } from "./lifecycle-registry.mjs";
|
|
17
|
+
import { readRepositoryMode } from './repository-mode.mjs';
|
|
18
|
+
import { validateResearchCompletion } from './maintenance-research.mjs';
|
|
17
19
|
|
|
18
20
|
const IMPLEMENTATION_WORK_UNIT = "work-unit.slice-implementation";
|
|
19
21
|
const TICKET_DECOMPOSITION_WORK_UNIT = "work-unit.ticket-decomposition";
|
|
@@ -28,6 +30,7 @@ function deepFreeze(value) {
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const NEXT_ROUTES = deepFreeze({
|
|
33
|
+
"work-unit.maintenance-research": ["work-unit.ssot-update"],
|
|
31
34
|
"work-unit.entry-triage": ["work-unit.plan-opportunity", "work-unit.plan-requirements"],
|
|
32
35
|
"work-unit.ssot-update": ["work-unit.skill-projection-sync", "work-unit.intensity-aware-verification-v2"],
|
|
33
36
|
"work-unit.skill-projection-sync": ["work-unit.template-snapshot-build", "work-unit.intensity-aware-verification-v2"],
|
|
@@ -303,6 +306,21 @@ function validateTicketReference(ref, trackerKind) {
|
|
|
303
306
|
* by `validateWorkflowExecutionResult` before this function is called.
|
|
304
307
|
*/
|
|
305
308
|
export function validateNextRoute(currentWorkUnit, nextRoute, decisionState, options = {}) {
|
|
309
|
+
let entryRoutes;
|
|
310
|
+
if (currentWorkUnit === 'work-unit.entry-triage' || currentWorkUnit === 'work-unit.maintenance-research' || nextRoute === 'work-unit.maintenance-research') {
|
|
311
|
+
try {
|
|
312
|
+
const mode = readRepositoryMode(options.root || ROOT);
|
|
313
|
+
if (currentWorkUnit === 'work-unit.entry-triage') entryRoutes = mode === 'template-source'
|
|
314
|
+
? ['work-unit.maintenance-research', 'work-unit.ssot-update'] : NEXT_ROUTES[currentWorkUnit];
|
|
315
|
+
if ((currentWorkUnit === 'work-unit.maintenance-research' || nextRoute === 'work-unit.maintenance-research') && mode !== 'template-source') throw Error('template-research-requires-template-source');
|
|
316
|
+
if (currentWorkUnit === 'work-unit.maintenance-research') {
|
|
317
|
+
assertScopeTransition(currentWorkUnit, nextRoute, decisionState, options);
|
|
318
|
+
if (nextRoute !== null && nextRoute !== 'work-unit.ssot-update') return blockedResult([BLOCKING_SIGNALS.invalidRoute]);
|
|
319
|
+
validateResearchCompletion(decisionState, {root: options.root || ROOT, continuing: nextRoute !== null});
|
|
320
|
+
return allowedResult(decisionState.evidence_refs);
|
|
321
|
+
}
|
|
322
|
+
} catch (error) { return blockedResult(['maintenance-research-boundary'], [error.message]); }
|
|
323
|
+
}
|
|
306
324
|
try { assertTrackingTransition(currentWorkUnit, nextRoute, decisionState, { root: options.root || ROOT }); }
|
|
307
325
|
catch (error) { return blockedResult(['stage-tracking-blocked'], [error.message]); }
|
|
308
326
|
try { assertScopeTransition(currentWorkUnit, nextRoute, decisionState, options); }
|
|
@@ -320,7 +338,7 @@ export function validateNextRoute(currentWorkUnit, nextRoute, decisionState, opt
|
|
|
320
338
|
try { enforceFrontendDelivery(decisionState, { root: options.root, phase: nextRoute === IMPLEMENTATION_WORK_UNIT ? "implementation" : "inputs" }); }
|
|
321
339
|
catch (error) { return blockedResult(["frontend-delivery-blocked"], [error.message]); }
|
|
322
340
|
}
|
|
323
|
-
const routes = NEXT_ROUTES[currentWorkUnit] && scopedNextRoutes(currentWorkUnit, NEXT_ROUTES[currentWorkUnit], options);
|
|
341
|
+
const routes = NEXT_ROUTES[currentWorkUnit] && scopedNextRoutes(currentWorkUnit, entryRoutes || NEXT_ROUTES[currentWorkUnit], options);
|
|
324
342
|
if (!routes) return blockedResult([BLOCKING_SIGNALS.invalidRoute], ["known_current_work_unit"]);
|
|
325
343
|
if (nextRoute === REPOSITORY_PREPARATION_WORK_UNIT && !["work-unit.technical-analysis", SERVICE_INITIALIZATION_WORK_UNIT].includes(currentWorkUnit)) {
|
|
326
344
|
return blockedResult([BLOCKING_SIGNALS.technicalAnalysisRequired], ["work-unit.technical-analysis predecessor"]);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {spawnSync} from 'node:child_process';
|
|
4
|
+
import {safe, hash, parse, ensure} from './strategic-handoff-io.mjs';
|
|
5
|
+
import {assertUserDecisionRequirement} from './user-decision.mjs';
|
|
6
|
+
|
|
7
|
+
export const RESEARCH_VALIDATOR = '.agents/skills/yss-research/scripts/validate-research-package.mjs';
|
|
8
|
+
const binding = (root, ref) => ({ref, digest: hash(fs.readFileSync(safe(root, ref)))});
|
|
9
|
+
function readBound(root, bound) {
|
|
10
|
+
ensure(bound && binding(root, bound.ref).digest === bound.digest, 'research-evidence-stale');
|
|
11
|
+
return fs.readFileSync(safe(root, bound.ref));
|
|
12
|
+
}
|
|
13
|
+
function execute(root, brief, evidence) {
|
|
14
|
+
return spawnSync(process.execPath, [safe(root, RESEARCH_VALIDATOR), safe(root, brief), safe(root, evidence)], {
|
|
15
|
+
cwd: root, encoding: 'utf8', timeout: 30000, maxBuffer: 2 * 1024 * 1024,
|
|
16
|
+
env: {...process.env, NODE_OPTIONS: '', NODE_PATH: ''},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Capture actual validator output; never overwrite a historical run. */
|
|
21
|
+
export function recordResearchVerification(root, brief, evidence, output) {
|
|
22
|
+
const inputs = {brief: binding(root, brief), evidence: binding(root, evidence), validator: binding(root, RESEARCH_VALIDATOR)};
|
|
23
|
+
const dir = safe(root, output, {missing: true});
|
|
24
|
+
ensure(!fs.existsSync(dir), '研究验证输出目录必须不存在');
|
|
25
|
+
const started_at = new Date().toISOString(), result = execute(root, brief, evidence);
|
|
26
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
27
|
+
fs.writeFileSync(path.join(dir, 'stdout.log'), result.stdout || '');
|
|
28
|
+
fs.writeFileSync(path.join(dir, 'stderr.log'), result.stderr || result.error?.message || '');
|
|
29
|
+
const record = {schema_version: 1, kind: 'maintenance-research-verification', inputs,
|
|
30
|
+
command: ['node', RESEARCH_VALIDATOR, brief, evidence], started_at, completed_at: new Date().toISOString(),
|
|
31
|
+
exit_code: result.status, stdout: binding(root, `${output}/stdout.log`), stderr: binding(root, `${output}/stderr.log`)};
|
|
32
|
+
for (const value of Object.values(inputs)) readBound(root, value);
|
|
33
|
+
fs.writeFileSync(path.join(dir, 'verification.json'), JSON.stringify(record, null, 2) + '\n');
|
|
34
|
+
return {binding: binding(root, `${output}/verification.json`), exit_code: result.status};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function validateResearchCompletion(state, {root, continuing = false}) {
|
|
38
|
+
ensure(state?.context_reconciliation?.status === 'not-applicable' && state.context_reconciliation.reason?.trim(), 'research-context-reason-missing');
|
|
39
|
+
fs.readFileSync(safe(root, state.context_reconciliation.ref));
|
|
40
|
+
for (const key of ['blocking_signals', 'drift', 'violation', 'new_impacts', 'stale_candidates']) {
|
|
41
|
+
ensure(Array.isArray(state[key]) && state[key].length === 0, `research-${key}-unresolved`);
|
|
42
|
+
}
|
|
43
|
+
const record = parse(readBound(root, state.research_verification));
|
|
44
|
+
ensure(record.schema_version === 1 && record.kind === 'maintenance-research-verification', 'research-verification-invalid');
|
|
45
|
+
for (const key of ['brief', 'evidence', 'validator']) readBound(root, record.inputs?.[key]);
|
|
46
|
+
ensure(record.inputs.validator.ref === RESEARCH_VALIDATOR, 'research-validator-mismatch');
|
|
47
|
+
ensure(record.exit_code === 0 && Number.isFinite(Date.parse(record.started_at)) && Date.parse(record.completed_at) >= Date.parse(record.started_at), 'research-verification-not-passed');
|
|
48
|
+
ensure(JSON.stringify(record.command) === JSON.stringify(['node', RESEARCH_VALIDATOR, record.inputs.brief.ref, record.inputs.evidence.ref]), 'research-command-mismatch');
|
|
49
|
+
readBound(root, record.stdout); readBound(root, record.stderr);
|
|
50
|
+
for (const ref of [state.context_reconciliation.ref, state.research_verification.ref, record.inputs.brief.ref, record.inputs.evidence.ref]) {
|
|
51
|
+
ensure(state.evidence_refs?.includes(ref), `research-evidence-unreferenced: ${ref}`);
|
|
52
|
+
}
|
|
53
|
+
const current = execute(root, record.inputs.brief.ref, record.inputs.evidence.ref);
|
|
54
|
+
ensure(!current.error && current.status === 0, 'research-current-validation-failed');
|
|
55
|
+
readBound(root, state.research_verification);
|
|
56
|
+
for(const value of Object.values(record.inputs))readBound(root,value);
|
|
57
|
+
if (continuing) {
|
|
58
|
+
const authorization = parse(readBound(root, state.maintenance_authorization));
|
|
59
|
+
ensure(authorization.boundary === 'template-maintenance-scope' && authorization.scope?.includes('work-unit.ssot-update'), 'maintenance-authorization-required');
|
|
60
|
+
assertUserDecisionRequirement(authorization, {root});
|
|
61
|
+
}
|
|
62
|
+
return record;
|
|
63
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { parse } from '../vendor/yaml.mjs';
|
|
6
|
+
import { runCommand } from './command-runner.mjs';
|
|
7
|
+
|
|
8
|
+
const ensure = (ok, message) => { if (!ok) throw new TypeError(`read-only-intake: ${message}`); };
|
|
9
|
+
export const digest = value => `sha256:${createHash('sha256').update(value).digest('hex')}`;
|
|
10
|
+
const inside = (root, file) => { const rel = path.relative(root, file); return rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel); };
|
|
11
|
+
export function intakeEvidencePath(ref, { root, runDir }) {
|
|
12
|
+
const runtime = ref.startsWith('run:');
|
|
13
|
+
const base = runtime ? runDir : root;
|
|
14
|
+
ensure(base && path.isAbsolute(base), '运行证据必须显式提供绝对 run-dir');
|
|
15
|
+
const relative = runtime ? ref.slice(4) : ref;
|
|
16
|
+
ensure(relative && !path.isAbsolute(relative) && !relative.split(/[\\/]/).includes('..'), '证据路径越界');
|
|
17
|
+
const resolvedBase = fs.realpathSync(base), file = path.resolve(base, relative);
|
|
18
|
+
ensure(inside(path.resolve(base), file) && inside(resolvedBase, fs.realpathSync(file)), '证据符号链接越界');
|
|
19
|
+
ensure(fs.statSync(file).isFile(), '证据必须为文件');
|
|
20
|
+
return file;
|
|
21
|
+
}
|
|
22
|
+
// Stream large preserved evidence archives instead of allocating the whole file.
|
|
23
|
+
export function fileDigest(file) {
|
|
24
|
+
const hash = createHash('sha256'), buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
25
|
+
const fd = fs.openSync(file, 'r');
|
|
26
|
+
try {
|
|
27
|
+
let size;
|
|
28
|
+
while ((size = fs.readSync(fd, buffer, 0, buffer.length, null)) !== 0) hash.update(buffer.subarray(0, size));
|
|
29
|
+
return `sha256:${hash.digest('hex')}`;
|
|
30
|
+
} finally { fs.closeSync(fd); }
|
|
31
|
+
}
|
|
32
|
+
/** Final observable repository files, including ignored and untracked files; never follow links. */
|
|
33
|
+
export function intakeSnapshot(root) {
|
|
34
|
+
const result = spawnSync('git', ['ls-files', '-z', '--cached', '--others'], { cwd: root, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
35
|
+
ensure(result.status === 0, result.stderr || '无法观察仓库');
|
|
36
|
+
const rows = {};
|
|
37
|
+
for (const ref of [...new Set(result.stdout.split('\0').filter(Boolean))].sort()) {
|
|
38
|
+
const file = path.join(root, ref);
|
|
39
|
+
try {
|
|
40
|
+
const stat = fs.lstatSync(file);
|
|
41
|
+
if (stat.isDirectory()) {
|
|
42
|
+
const nested = spawnSync('git', ['rev-parse', '--show-toplevel'], { cwd: file, encoding: 'utf8' });
|
|
43
|
+
ensure(nested.status === 0 && fs.realpathSync(nested.stdout.trim()) === fs.realpathSync(file), `子仓未初始化: ${ref}`);
|
|
44
|
+
const head = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: file, encoding: 'utf8' });
|
|
45
|
+
ensure(nested.status === 0 && head.status === 0, `子仓不可观测: ${ref}`);
|
|
46
|
+
rows[ref] = { kind: 'gitlink', head: head.stdout.trim(), files: intakeSnapshot(file) };
|
|
47
|
+
} else rows[ref] = { kind: stat.isSymbolicLink() ? 'link' : 'file', mode: stat.mode, digest: stat.isSymbolicLink() ? digest(fs.readlinkSync(file)) : fileDigest(file) };
|
|
48
|
+
} catch (error) { if (error.code === 'ENOENT') rows[ref] = null; else throw error; }
|
|
49
|
+
}
|
|
50
|
+
const head=spawnSync('git',['rev-parse','--verify','HEAD'],{cwd:root,encoding:'utf8'});
|
|
51
|
+
const index=spawnSync('git',['ls-files','--stage','-z'],{cwd:root,encoding:'utf8',maxBuffer:16*1024*1024});
|
|
52
|
+
ensure(index.status===0,'无法观察 Git index');
|
|
53
|
+
return {git:{head:head.status===0?head.stdout.trim():null,index_digest:digest(index.stdout)},files:rows};
|
|
54
|
+
}
|
|
55
|
+
export function validateReadOnlyIntake(value, { root, runDir, roles, lifecycle }) {
|
|
56
|
+
const identity = parse(fs.readFileSync(path.join(root, 'yss-project.yaml'), 'utf8'));
|
|
57
|
+
ensure(identity.schema_version === 1 && ['template-source', 'project-instance'].includes(identity.repository_mode), '仓库身份无效');
|
|
58
|
+
ensure(value.contract.kind === 'read-only-intake' && value.schema_version === 2 && value.execution_state === 'Explorer' && value.allowed_write_paths.length === 0, '只读合同不授予写权限');
|
|
59
|
+
ensure(lifecycle.work_units.some(x => x.id === value.work_unit_id) && ['work-unit.entry-triage', 'work-unit.harness-entry'].includes(value.work_unit_id), '只允许已登记分诊入口');
|
|
60
|
+
ensure(roles.runtimes.some(x => x.id === value.runtime_id), '未知运行时');
|
|
61
|
+
ensure(value.contract.status === 'issued' || value.workflow_status === 'paused', '过期合同必须暂停');
|
|
62
|
+
for (const ref of [value.contract.contract_ref, ...value.inputs, ...value.expected_evidence_files]) intakeEvidencePath(ref, { root, runDir });
|
|
63
|
+
if (value.result) {
|
|
64
|
+
ensure(value.result.work_unit===value.work_unit_id && value.result.workflow_reference===value.contract.contract_ref,'结果必须绑定原分诊工作单元和合同来源');
|
|
65
|
+
ensure(!value.result.changed_files?.length && !value.result.changed_artifacts?.length, '只读结果包含变更');
|
|
66
|
+
ensure(value.result.next_route == null && !value.result.checkpoint_ref, '只读结果不得流转或修改 checkpoint');
|
|
67
|
+
for (const ref of value.result.evidence_refs || []) intakeEvidencePath(ref, { root, runDir });
|
|
68
|
+
}
|
|
69
|
+
const commands = new Set(value.verification_commands);
|
|
70
|
+
ensure((value.verification_status === 'not-executed') === (value.verification_results.length === 0), '执行状态与实际结果不一致');
|
|
71
|
+
for (const row of value.verification_results) {
|
|
72
|
+
ensure(commands.has(row.command) && row.evidence_ref.startsWith('run:'), '运行结果必须绑定声明的命令及真实运行日志');
|
|
73
|
+
const evidence = fs.readFileSync(intakeEvidencePath(row.evidence_ref, { root, runDir }));
|
|
74
|
+
ensure(row.evidence_digest === digest(evidence), '运行证据摘要不一致');
|
|
75
|
+
const record = JSON.parse(evidence);
|
|
76
|
+
for (const key of ['command','exit_code','duration_ms','executed_at']) ensure(record[key] === row[key], `运行记录 ${key} 不一致`);
|
|
77
|
+
for (const stream of ['stdout','stderr']) {
|
|
78
|
+
const ref = row[`${stream}_ref`];
|
|
79
|
+
ensure(ref?.startsWith('run:'), '运行日志无效');
|
|
80
|
+
ensure(record[`${stream}_digest`] === digest(fs.readFileSync(intakeEvidencePath(ref, { root, runDir }))), '运行日志摘要不一致');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (value.workflow_status === 'resolved' || value.result?.result === 'completed') {
|
|
84
|
+
ensure(value.workflow_status === 'resolved' && value.result?.result === 'completed', '完成状态不一致');
|
|
85
|
+
ensure(value.result.evidence_refs?.length && value.result.context_reconciliation?.status === 'not-applicable' && value.result.context_reconciliation?.reason, '只读结论缺少来源或不流转说明');
|
|
86
|
+
for (const key of ['drift','violation','new_impacts','stale_candidates','blocking_signals','deferred_seams']) ensure(Array.isArray(value.result[key]) && !value.result[key].length, `完成结果 ${key} 必须为空`);
|
|
87
|
+
ensure(value.verification_results.every(x => x.exit_code === 0) && [...commands].every(c => value.verification_results.some(x => x.command === c)), '实际验证缺失或失败');
|
|
88
|
+
ensure(value.observation_ref?.startsWith('run:'), '完成结果缺少执行器仓库观测');
|
|
89
|
+
const observation = JSON.parse(fs.readFileSync(intakeEvidencePath(value.observation_ref, { root, runDir }), 'utf8'));
|
|
90
|
+
const dispatchedBytes=fs.readFileSync(intakeEvidencePath(observation.task_ref,{root,runDir}));
|
|
91
|
+
ensure(observation.task_digest===digest(dispatchedBytes),'原派发任务摘要不一致');
|
|
92
|
+
const dispatched=JSON.parse(dispatchedBytes);
|
|
93
|
+
for(const key of ['task_id','work_unit_id','actor_id','role_id','runtime_id','contract','inputs','allowed_write_paths','objective','forbidden_actions','expected_outputs','expected_evidence_files','skill_source','downstream_consumers','convergence'])ensure(JSON.stringify(dispatched[key])===JSON.stringify(value[key]),`结果替换原任务 ${key}`);
|
|
94
|
+
ensure(!dispatched.verification_commands.length || JSON.stringify(dispatched.verification_commands)===JSON.stringify(value.verification_commands),'结果替换验证要求');
|
|
95
|
+
ensure(observation.kind === 'read-only-intake-observation' && observation.task_id === value.task_id && observation.root === fs.realpathSync(root), '观测身份不匹配');
|
|
96
|
+
ensure(JSON.stringify(observation.before) === JSON.stringify(observation.after) && JSON.stringify(observation.after) === JSON.stringify(intakeSnapshot(root)), '仓库实际差异与只读声明冲突');
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
/** Runner-owned evidence is outside the repository; the child receives no new repository permissions. */
|
|
101
|
+
export async function observeReadOnlyIntake(task, { root, runDir, command, args = [], timeoutMs = 0 }) {
|
|
102
|
+
const label = command ? JSON.stringify([command,...args]) : null;
|
|
103
|
+
ensure(!command || !task.verification_commands.length || task.verification_commands.length===1 && task.verification_commands[0]===label,'执行命令与声明不一致,不得替换要求的验证');
|
|
104
|
+
root = fs.realpathSync(root);
|
|
105
|
+
ensure(path.isAbsolute(runDir) && !inside(root, path.resolve(runDir)), '运行目录必须位于仓库外');
|
|
106
|
+
ensure(!inside(root, fs.realpathSync(path.dirname(runDir))), '运行目录父路径符号链接进入仓库');
|
|
107
|
+
fs.mkdirSync(runDir, { recursive: false });
|
|
108
|
+
runDir = fs.realpathSync(runDir);
|
|
109
|
+
fs.writeFileSync(path.join(runDir,'task.json'),JSON.stringify(task,null,2)+'\n',{flag:'wx'});
|
|
110
|
+
const before = intakeSnapshot(root), started = new Date().toISOString();
|
|
111
|
+
const result = command ? await runCommand(command, args, { cwd: root, timeoutMs, stdoutFile: path.join(runDir, 'stdout.log'), stderrFile: path.join(runDir, 'stderr.log') }) : null;
|
|
112
|
+
const after = intakeSnapshot(root);
|
|
113
|
+
const observation = { schema_version: 1, kind: 'read-only-intake-observation', task_id: task.task_id, task_ref:'run:task.json', task_digest:digest(fs.readFileSync(path.join(runDir,'task.json'))), root, started_at: started, before, after };
|
|
114
|
+
fs.writeFileSync(path.join(runDir, 'observation.json'), JSON.stringify(observation, null, 2)+'\n');
|
|
115
|
+
const changed = JSON.stringify(before) !== JSON.stringify(after);
|
|
116
|
+
const completed = !changed && (!result || result.status === 0);
|
|
117
|
+
const output = structuredClone(task);
|
|
118
|
+
output.observation_ref = 'run:observation.json';
|
|
119
|
+
output.verification_status = result ? 'executed' : 'not-executed';
|
|
120
|
+
output.verification_results = [];
|
|
121
|
+
if (result) {
|
|
122
|
+
const label = JSON.stringify([command, ...args]);
|
|
123
|
+
const record = { command: label, exit_code: result.status ?? 1, duration_ms: Math.round(result.duration_ms), executed_at: started, termination: result.termination ?? null, stdout_digest: digest(fs.readFileSync(path.join(runDir,'stdout.log'))), stderr_digest: digest(fs.readFileSync(path.join(runDir,'stderr.log'))) };
|
|
124
|
+
const bytes = JSON.stringify(record, null, 2)+'\n'; fs.writeFileSync(path.join(runDir, 'execution.json'), bytes);
|
|
125
|
+
output.verification_commands = [label];
|
|
126
|
+
output.verification_results = [{command:label,exit_code:record.exit_code,duration_ms:record.duration_ms,executed_at:started,evidence_ref:'run:execution.json',evidence_digest:digest(bytes),stdout_ref:'run:stdout.log',stderr_ref:'run:stderr.log'}];
|
|
127
|
+
}
|
|
128
|
+
output.workflow_status = completed ? 'resolved' : 'failed';
|
|
129
|
+
output.result = { result_schema: 'workflow-execution-result-v1', work_unit: task.work_unit_id, workflow_reference: task.contract.contract_ref, result: completed ? 'completed' : 'failed', skill: 'yss-research', changed_files: [], changed_artifacts: [], evidence_refs: [...task.inputs, 'run:observation.json'], context_reconciliation: {status:'not-applicable',ref:'CONTEXT.md',reason:'只读分诊,不批准资产或流转阶段'}, deferred_seams: [], drift: [], violation: changed ? ['repository-changed'] : [], new_impacts: [], stale_candidates: [], next_route: null, blocking_signals: completed ? [] : ['read-only-intake-failed'] };
|
|
130
|
+
fs.writeFileSync(path.join(runDir, 'task-result.json'), JSON.stringify(output, null, 2)+'\n');
|
|
131
|
+
return output;
|
|
132
|
+
}
|
|
@@ -65,7 +65,8 @@ export function loadSkillRegistry(filePath = DEFAULT_REGISTRY) {
|
|
|
65
65
|
export function resolveSkillForNewUse(registry, requestedId) {
|
|
66
66
|
requireString(requestedId, "requested skill id");
|
|
67
67
|
if (OBSOLETE.has(requestedId)) {
|
|
68
|
-
const
|
|
68
|
+
const lifecycleOwner = ["harness-orchestrator", "yss-strategic-design", "yss-product-lifecycle"].find(id => registry.skills?.some(skill => skill.id === id));
|
|
69
|
+
const replacementSkill = ({ "grill-me": "grilling", "wait-what": "i-have-adhd", "grill-with-docs": lifecycleOwner, "to-questionnaire": lifecycleOwner, "improve-codebase-architecture": "codebase-design" })[requestedId] ?? null;
|
|
69
70
|
throw new SkillLifecycleError(
|
|
70
71
|
SKILL_LIFECYCLE_FAILURE_CODES.retired,
|
|
71
72
|
replacementSkill
|
|
@@ -12,6 +12,10 @@ const STRATEGIC_DESIGN_MANIFEST_PATH = path.join(SOURCE_ROOT, ".strategic-design
|
|
|
12
12
|
export const PROJECTION_ROOTS = [".codex/skills", ".cursor/skills", ".pi/skills"];
|
|
13
13
|
export const OBSOLETE = new Set(["yss-antd-design", "yss-antdv-next-design", "to-" + "prd", "to-" + "issues", "design-an-interface", "qa", "request-refactor-plan", "ubiquitous-language", "edit-article", "obsidian-vault", "writing-great-skills", "code-review-process", "yss-domain-modeling", "yss-dir", "yss-duckdb", "yss-file", "yss-filerunner", "yss-db2mybatis", "yss-mail", "yss-mapper-dynamic", "yss-quality", "yss-sql-condition", "yss-sql-tpl", "yss-valuation", "yss-variable", "yss-openapi", "web-design-engineer", "web-video-presentation", "wireframe-prototype", "wizard", "git-guardrails-claude-code", "claude-handoff", "batch-grill-me", "grill-me", "product-design-prototype", "research", "ask-matt", "dispatching-parallel-agents", "loop-me", "migrate-to-shoehorn", "prototype-page-acceptance", "scaffold-exercises", "setup-pre-commit", "setup-ts-deep-modules", "teach", "writing-beats", "writing-fragments", "writing-shape", "yss-microapp-commit", "yss-page-module-development", "yss-dictionary", "yss-jdbc", "yss-log", "yss-taskflow", "yss-backend-scaffold-application", "yss-backend-scaffold-domain", "yss-backend-scaffold-infrastructure", "yss-backend-scaffold-web", "yss-router", "yss-source-index"]);
|
|
14
14
|
for (const id of ["component-selection-imports", "page-form-module", "page-list-module", "page-skeleton", "vue3-best-practices", "yss-use-table-height", "yss-use-tree-height", "yss-components", "yss-mvc-scaffold-generator", "yss-mvc-design", "yss-mvc-data-analysis-project-initializer", "yss-backend-scaffold-parent", "yss-backend-scaffold-adapter", "yss-application-layer-reference", "yss-domain-layer-reference", "yss-infrastructure-layer-reference", "yss-web-layer-reference"]) OBSOLETE.add(id);
|
|
15
|
+
OBSOLETE.add("grill-with-docs");
|
|
16
|
+
OBSOLETE.add("to-questionnaire");
|
|
17
|
+
OBSOLETE.add("improve-codebase-architecture");
|
|
18
|
+
OBSOLETE.add("wait-what");
|
|
15
19
|
export function obsoleteCanonicalResidues(names, obsolete = OBSOLETE) {
|
|
16
20
|
return names.filter((name) => obsolete.has(name)).sort();
|
|
17
21
|
}
|
|
@@ -31,7 +31,7 @@ function compile(binding,{root=ROOT,work_unit_id,task_id,actor_id,runtime_id,exe
|
|
|
31
31
|
task_id,work_unit_id,actor_id,runtime_id,execution_state,workflow_status:'not-started',stage_id:'stage.vertical-slice-implementation',
|
|
32
32
|
contract:{kind:'slice-implementation',contract_id:contract.contract_id,contract_version:contract.contract_version,status:'issued',contract_ref:binding.ref,slice_contract_ref:binding.ref,gate_refs:[binding.approval_ref]},
|
|
33
33
|
inputs:[binding.ref,...new Set(Object.values(contract.lifecycle_refs))],
|
|
34
|
-
objective:`${unit.behavior}(执行目录:${unit.project_root}
|
|
34
|
+
objective:`${unit.behavior}(执行目录:${unit.project_root};默认消费 ${binding.ref} 的 task 视图并指定 ${work_unit_id},追溯时展开 full)`,
|
|
35
35
|
allowed_write_paths:unit.allowed_write_paths,forbidden_actions:[...unit.work_unit.forbidden_patterns,'来源过期、越界、缺证据、验证失败或新增影响时停止并回交'],
|
|
36
36
|
expected_outputs:[unit.behavior],expected_evidence_files:unit.work_unit.expected_evidence,verification_commands:unit.work_unit.verification_commands,verification_results:[],
|
|
37
37
|
downstream_consumers:unit.downstream_consumers||['role.lifecycle-orchestrator'],convergence:{parent_work_unit:'work-unit.slice-implementation',convergence_ref:unit.convergence_ref||binding.approval_ref,conflict_escalation:'返回生命周期主控'},user_decisions:decisions
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateReadOnlyIntake } from './read-only-intake.mjs';
|
|
1
2
|
import { assertTrackingEntry } from './stage-tracking.mjs';
|
|
2
3
|
import { normalizeSliceContract } from './slice-contract.mjs';
|
|
3
4
|
import { assertSliceV3TaskPackage } from './slice-task-package.mjs';
|
|
@@ -17,7 +18,7 @@ import { LEGACY_TASK_PACKAGE_SCHEMA, TASK_PACKAGE_SCHEMA, validateTaskPackageSch
|
|
|
17
18
|
|
|
18
19
|
export { LEGACY_TASK_PACKAGE_SCHEMA, TASK_PACKAGE_SCHEMA, validateTaskPackageSchema };
|
|
19
20
|
export const TASK_PACKAGE_REGISTRY_REF = ".template-spec/agents/digital-human-roles.yaml";
|
|
20
|
-
export const CONTRACT_KINDS = new Set(["lifecycle-work-unit", "slice-implementation", "template-maintenance"]);
|
|
21
|
+
export const CONTRACT_KINDS = new Set(["lifecycle-work-unit", "slice-implementation", "template-maintenance", "read-only-intake"]);
|
|
21
22
|
export const EXECUTION_STATES = new Set(["Explorer", "Drafter", "Worker", "Reviewer", "Verifier"]);
|
|
22
23
|
export const WORKFLOW_STATUSES = new Set(["not-started", "active", "paused", "resolved", "failed"]);
|
|
23
24
|
|
|
@@ -203,8 +204,14 @@ function validateContract(value, registry, lifecycle) {
|
|
|
203
204
|
if (value.execution_state === "Worker") assertImplementationDecision({ slice_contract_ref: contract.slice_contract_ref, vertical_slice_ticket_ref: slice.lifecycle_refs.ticket, user_decisions: value.user_decisions });
|
|
204
205
|
}
|
|
205
206
|
|
|
206
|
-
export function validateTaskPackage(value, { rolesDoc, lifecycleDoc } = {}) {
|
|
207
|
+
export function validateTaskPackage(value, { rolesDoc, lifecycleDoc, root = ROOT, runDir } = {}) {
|
|
207
208
|
validateTaskPackageSchema(value);
|
|
209
|
+
if (value.schema_version === 2) {
|
|
210
|
+
enforceHarnessTaskScope(value, { root });
|
|
211
|
+
const registry = rolesDoc || loadDigitalHumanRoles();
|
|
212
|
+
validateSkillSource(value, registry);
|
|
213
|
+
return validateReadOnlyIntake(value, { root, runDir, roles: registry, lifecycle: lifecycleDoc || loadRegistry() });
|
|
214
|
+
}
|
|
208
215
|
enforceHarnessTaskScope(value);
|
|
209
216
|
const intake = value.execution_state === "Explorer" && value.allowed_write_paths.length === 0 && ["work-unit.entry-triage", "work-unit.harness-entry"].includes(value.work_unit_id);
|
|
210
217
|
if (!intake) {
|
|
@@ -4,8 +4,8 @@ import path from 'node:path';
|
|
|
4
4
|
import { lifecycleStatus } from './lib/lifecycle-status.mjs';
|
|
5
5
|
|
|
6
6
|
try {
|
|
7
|
-
const { values } = parseArgs({ strict: true, options: { root: { type: 'string' }, checkpoint: { type: 'string' } } });
|
|
8
|
-
const result = lifecycleStatus({ root: path.resolve(values.root ?? '.'), checkpointRef: values.checkpoint });
|
|
7
|
+
const { values } = parseArgs({ strict: true, options: { root: { type: 'string' }, checkpoint: { type: 'string' }, task: {type: 'string'} } });
|
|
8
|
+
const result = lifecycleStatus({ root: path.resolve(values.root ?? '.'), checkpointRef: values.checkpoint, taskPackageRef: values.task });
|
|
9
9
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
10
10
|
if (result.blockers.length) process.exitCode = 1;
|
|
11
11
|
} catch (error) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {parseArgs} from 'node:util';
|
|
5
|
+
import {ROOT} from './lib/lifecycle-registry.mjs';
|
|
6
|
+
import {loadTaskPackage,generateTaskPackageDefaults,validateTaskPackage} from './lib/task-package.mjs';
|
|
7
|
+
try {
|
|
8
|
+
const {values}=parseArgs({options:{input:{type:'string'},output:{type:'string'}}});
|
|
9
|
+
if(!values.input||!values.output)throw Error('用法: prepare-read-only-intake --input <来源选择.json|yaml> --output <仓库外/task.json>');
|
|
10
|
+
const {value:input}=loadTaskPackage(values.input);
|
|
11
|
+
const output=path.resolve(values.output),parent=fs.realpathSync(path.dirname(output)),root=fs.realpathSync(ROOT);
|
|
12
|
+
if(parent===root||parent.startsWith(root+path.sep))throw Error('任务包必须保存于仓库外运行目录');
|
|
13
|
+
const task=generateTaskPackageDefaults(input.role_id,{...input,schema_version:2,execution_state:'Explorer',workflow_status:'active',allowed_write_paths:[],expected_evidence_files:[],verification_commands:input.verification_commands||[],verification_results:[],verification_status:'not-executed',contract:{...input.contract,kind:'read-only-intake',status:'issued'}});
|
|
14
|
+
validateTaskPackage(task);
|
|
15
|
+
fs.writeFileSync(output,JSON.stringify(task,null,2)+'\n',{flag:'wx'});process.stdout.write(output+'\n');
|
|
16
|
+
}catch(error){process.stderr.write(error.message+'\n');process.exitCode=1;}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { ROOT } from './lib/lifecycle-registry.mjs';
|
|
4
|
+
import { loadTaskPackage, validateTaskPackage } from './lib/task-package.mjs';
|
|
5
|
+
import { observeReadOnlyIntake } from './lib/read-only-intake.mjs';
|
|
6
|
+
try {
|
|
7
|
+
const {values,positionals} = parseArgs({options:{task:{type:'string'},'run-dir':{type:'string'},'timeout-ms':{type:'string',default:'0'}},allowPositionals:true});
|
|
8
|
+
if(!values.task||!values['run-dir'])throw Error('需要 --task 和仓库外新目录 --run-dir;命令放在 -- 之后');
|
|
9
|
+
const {value}=loadTaskPackage(values.task);validateTaskPackage(value);
|
|
10
|
+
if(value.schema_version!==2||value.workflow_status!=='active')throw Error('只接受 active 的只读 v2 任务');
|
|
11
|
+
const result=await observeReadOnlyIntake(value,{root:ROOT,runDir:values['run-dir'],command:positionals[0],args:positionals.slice(1),timeoutMs:Number(values['timeout-ms'])});
|
|
12
|
+
validateTaskPackage(result,{runDir:values['run-dir']});
|
|
13
|
+
process.stdout.write(JSON.stringify(result,null,2)+'\n');if(result.workflow_status!=='resolved')process.exitCode=1;
|
|
14
|
+
}catch(error){process.stderr.write(error.message+'\n');process.exitCode=1;}
|
|
@@ -3,10 +3,10 @@ import { parseArgs } from "node:util";
|
|
|
3
3
|
import { loadTaskPackage, validateTaskPackage } from "./lib/task-package.mjs";
|
|
4
4
|
|
|
5
5
|
try {
|
|
6
|
-
const { positionals } = parseArgs({ allowPositionals: true, strict: true });
|
|
6
|
+
const { positionals, values } = parseArgs({ options: { "run-dir": { type: "string" } }, allowPositionals: true, strict: true });
|
|
7
7
|
if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-digital-human-task-package <task-package.yaml|task-package.json>");
|
|
8
8
|
const { value } = loadTaskPackage(positionals[0]);
|
|
9
|
-
validateTaskPackage(value);
|
|
9
|
+
validateTaskPackage(value, { runDir: values["run-dir"] });
|
|
10
10
|
process.stdout.write("数字人任务包验证通过\n");
|
|
11
11
|
} catch (error) {
|
|
12
12
|
process.stderr.write(`数字人任务包验证失败: ${error.message}\n`);
|