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
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
3
|
+
import { mkdir, mkdtemp, writeFile, readFile } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import test from "node:test";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { drift, hashSources, sha256, unmappedCandidates } from "./inventory.mjs";
|
|
9
|
-
|
|
10
9
|
const inventoryCli = fileURLToPath(new URL("./inventory.mjs", import.meta.url));
|
|
11
|
-
|
|
12
10
|
async function seed() {
|
|
13
11
|
const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-inv-"));
|
|
14
12
|
const wiki = path.join(repo, "wiki-root");
|
|
15
13
|
await mkdir(path.join(wiki, "raw"), { recursive: true });
|
|
14
|
+
await mkdir(path.join(wiki, "wiki"));
|
|
15
|
+
await writeFile(path.join(wiki, "raw/api.md"), "v1\n");
|
|
16
|
+
for (const id of ["API契约", "人工页"]) await writeFile(path.join(wiki, `wiki/${id}.md`), `# ${id}
|
|
17
|
+
|
|
18
|
+
Summary.
|
|
19
|
+
|
|
20
|
+
## 来源
|
|
21
|
+
- api.md
|
|
22
|
+
`);
|
|
16
23
|
const liveRel = "docs/api.md";
|
|
17
24
|
const live = path.join(repo, liveRel);
|
|
18
25
|
await mkdir(path.dirname(live), { recursive: true });
|
|
@@ -29,28 +36,31 @@ async function seed() {
|
|
|
29
36
|
kind: "document",
|
|
30
37
|
livePath: liveRel,
|
|
31
38
|
rawPath: "raw/api.md",
|
|
32
|
-
sha256: "",
|
|
33
|
-
role: "copy"
|
|
34
|
-
}
|
|
39
|
+
sha256: sha256("v1\n"),
|
|
40
|
+
role: "copy"
|
|
41
|
+
}
|
|
35
42
|
],
|
|
36
43
|
articles: [
|
|
37
44
|
{ id: "API契约", file: "wiki/API契约.md", sourceIds: ["api.md"], humanOwned: false },
|
|
38
|
-
{ id: "人工页", file: "wiki/人工页.md", sourceIds: ["api.md"], humanOwned: true }
|
|
39
|
-
]
|
|
45
|
+
{ id: "人工页", file: "wiki/人工页.md", sourceIds: ["api.md"], humanOwned: true }
|
|
46
|
+
]
|
|
40
47
|
}),
|
|
41
|
-
"utf8"
|
|
48
|
+
"utf8"
|
|
42
49
|
);
|
|
43
50
|
return { repo, wiki, live, liveRel };
|
|
44
51
|
}
|
|
45
|
-
|
|
46
|
-
test("hash-sources fills sha256; drift is empty until live file changes", async () => {
|
|
52
|
+
test("hash-sources only observes; v1 remains unverified until compiled", async () => {
|
|
47
53
|
const { repo, wiki, live } = await seed();
|
|
54
|
+
const before = await readFile(path.join(wiki, ".wiki-manifest.json"));
|
|
48
55
|
const hashed = await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
|
|
49
56
|
assert.equal(hashed.missing.length, 0);
|
|
57
|
+
assert.deepEqual(await readFile(path.join(wiki, ".wiki-manifest.json")), before);
|
|
58
|
+
assert.equal(hashed.observations[0].originalDigest, sha256("v1\n"));
|
|
50
59
|
assert.equal(hashed.manifest.sources[0].sha256, sha256(Buffer.from("v1\n")));
|
|
51
60
|
const clean = await drift({ wikiRoot: wiki, repoRoot: repo });
|
|
52
61
|
assert.deepEqual(clean.changed, []);
|
|
53
|
-
assert.deepEqual(clean.articles, []);
|
|
62
|
+
assert.deepEqual(clean.articles, ["API契约", "人工页"]);
|
|
63
|
+
assert.equal(clean.articleStates.every((a) => a.state === "unverified"), true);
|
|
54
64
|
await writeFile(live, "v2\n", "utf8");
|
|
55
65
|
const dirty = await drift({ wikiRoot: wiki, repoRoot: repo });
|
|
56
66
|
assert.deepEqual(dirty.changed, ["api.md"]);
|
|
@@ -58,20 +68,18 @@ test("hash-sources fills sha256; drift is empty until live file changes", async
|
|
|
58
68
|
assert.deepEqual(dirty.humanOwned, ["人工页"]);
|
|
59
69
|
assert.deepEqual(dirty.unmapped, []);
|
|
60
70
|
});
|
|
61
|
-
|
|
62
71
|
test("unmapped candidates are listed without scanning the tree", () => {
|
|
63
72
|
const sources = [{ livePath: "docs/api.md" }];
|
|
64
73
|
assert.deepEqual(unmappedCandidates(sources, ["docs/api.md", "docs/new.md", "./docs/new.md"]), [
|
|
65
|
-
"docs/new.md"
|
|
74
|
+
"docs/new.md"
|
|
66
75
|
]);
|
|
67
76
|
});
|
|
68
|
-
|
|
69
77
|
test("drift CLI exits 0 when sources changed and prints JSON", async () => {
|
|
70
78
|
const { repo, wiki, live } = await seed();
|
|
71
79
|
await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
|
|
72
80
|
await writeFile(live, "v2\n", "utf8");
|
|
73
81
|
const ran = spawnSync(process.execPath, [inventoryCli, "drift", "--wiki", wiki, "--repo", repo], {
|
|
74
|
-
encoding: "utf8"
|
|
82
|
+
encoding: "utf8"
|
|
75
83
|
});
|
|
76
84
|
assert.equal(ran.status, 0, ran.stderr);
|
|
77
85
|
const report = JSON.parse(ran.stdout);
|
|
@@ -80,7 +88,6 @@ test("drift CLI exits 0 when sources changed and prints JSON", async () => {
|
|
|
80
88
|
assert.deepEqual(report.humanOwned, ["人工页"]);
|
|
81
89
|
assert.deepEqual(report.unmapped, []);
|
|
82
90
|
});
|
|
83
|
-
|
|
84
91
|
test("status CLI exits 0 and lists unmapped candidates", async () => {
|
|
85
92
|
const { repo, wiki, live } = await seed();
|
|
86
93
|
await hashSources({ wikiRoot: wiki, repoRoot: repo, now: "2026-01-01T00:00:00Z" });
|
|
@@ -88,7 +95,7 @@ test("status CLI exits 0 and lists unmapped candidates", async () => {
|
|
|
88
95
|
const ran = spawnSync(
|
|
89
96
|
process.execPath,
|
|
90
97
|
[inventoryCli, "status", "--wiki", wiki, "--repo", repo, "--candidate", "docs/extra.md"],
|
|
91
|
-
{ encoding: "utf8" }
|
|
98
|
+
{ encoding: "utf8" }
|
|
92
99
|
);
|
|
93
100
|
assert.equal(ran.status, 0, ran.stderr);
|
|
94
101
|
const report = JSON.parse(ran.stdout);
|
|
@@ -2,31 +2,28 @@
|
|
|
2
2
|
import { readFile, readdir } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
export const INFRA = new Set([
|
|
5
|
+
import { exists, safePath, frontmatter, sourceSection, validateManifest, checkPaths, ownership, transactionState, cliError } from "./core.mjs";
|
|
6
|
+
import { drift } from "./inventory.mjs";
|
|
7
|
+
const INFRA = /* @__PURE__ */ new Set([
|
|
9
8
|
"index.md",
|
|
10
9
|
"log.md",
|
|
11
10
|
"claude.md",
|
|
12
11
|
"agents.md",
|
|
13
12
|
"soul.md",
|
|
14
|
-
"concept-table.md"
|
|
13
|
+
"concept-table.md"
|
|
15
14
|
]);
|
|
16
15
|
const WIKILINK_RE = /\[\[([^\]|#]+)(?:[|#][^\]]*)?\]\]/g;
|
|
17
16
|
const SOURCE_HEADING_RE = /^##\s+来源\s*$/m;
|
|
18
17
|
const H1_RE = /^#\s+(.+?)\s*$/m;
|
|
19
|
-
|
|
20
|
-
export function articlesDir(wikiRoot) {
|
|
18
|
+
function articlesDir(wikiRoot) {
|
|
21
19
|
return path.join(wikiRoot, "wiki");
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
export function extractLinks(text) {
|
|
21
|
+
function extractLinks(text) {
|
|
25
22
|
const ids = [];
|
|
26
23
|
const invalid = [];
|
|
27
24
|
WIKILINK_RE.lastIndex = 0;
|
|
28
25
|
let match;
|
|
29
|
-
while (
|
|
26
|
+
while (match = WIKILINK_RE.exec(text)) {
|
|
30
27
|
const target = match[1].trim();
|
|
31
28
|
if (!target) continue;
|
|
32
29
|
if (target.startsWith("../") || target.includes("/")) {
|
|
@@ -37,34 +34,61 @@ export function extractLinks(text) {
|
|
|
37
34
|
}
|
|
38
35
|
return { ids, invalid };
|
|
39
36
|
}
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
async function lintWiki(wikiRoot, { repoRoot = process.cwd(), structureOnly = false } = {}) {
|
|
38
|
+
const errors = [];
|
|
39
|
+
let manifest;
|
|
40
|
+
try {
|
|
41
|
+
const mf = await safePath(wikiRoot, ".wiki-manifest.json");
|
|
42
|
+
if (await exists(mf)) {
|
|
43
|
+
manifest = JSON.parse(await readFile(mf, "utf8"));
|
|
44
|
+
errors.push(...validateManifest(manifest));
|
|
45
|
+
if (!errors.length) await checkPaths(manifest, { wikiRoot, repoRoot });
|
|
46
|
+
}
|
|
47
|
+
await safePath(wikiRoot, "wiki/index.md");
|
|
48
|
+
} catch (error) {
|
|
49
|
+
errors.push(error.message);
|
|
50
|
+
}
|
|
51
|
+
if (errors.length) {
|
|
52
|
+
try {
|
|
53
|
+
const files = await readdir(await safePath(wikiRoot, "wiki"));
|
|
54
|
+
for (const file of files.filter((f) => f.endsWith(".md") && !INFRA.has(f.toLowerCase())))
|
|
55
|
+
if (!manifest?.articles?.some((a) => a.file === `wiki/${file}`)) errors.push(`UNLISTED ARTICLE: ${file}`);
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
return { ok: false, errors, counts: {} };
|
|
59
|
+
}
|
|
42
60
|
const dir = articlesDir(wikiRoot);
|
|
43
|
-
if (!
|
|
61
|
+
if (!await exists(path.join(dir, "index.md"))) {
|
|
44
62
|
return { ok: false, errors: [`missing ${path.join(dir, "index.md")}`], counts: {} };
|
|
45
63
|
}
|
|
46
64
|
const names = (await readdir(dir)).filter((name) => name.endsWith(".md"));
|
|
47
65
|
const articleFiles = names.filter((name) => !INFRA.has(name.toLowerCase()));
|
|
48
66
|
const articleIds = new Set(articleFiles.map((name) => name.slice(0, -3)));
|
|
49
|
-
const errors = [];
|
|
50
67
|
let linkCount = 0;
|
|
51
|
-
|
|
52
|
-
const indexText = await readFile(path.join(dir, "index.md"), "utf8");
|
|
68
|
+
const indexText = await readFile(await safePath(wikiRoot, "wiki/index.md"), "utf8");
|
|
53
69
|
const indexLinks = extractLinks(indexText);
|
|
54
70
|
linkCount += indexLinks.ids.length;
|
|
55
71
|
for (const target of indexLinks.invalid) errors.push(`CROSS-WIKI (index): [[${target}]]`);
|
|
56
|
-
const indexed = new Set();
|
|
72
|
+
const indexed = /* @__PURE__ */ new Set();
|
|
57
73
|
for (const id of indexLinks.ids) {
|
|
58
74
|
indexed.add(id);
|
|
59
75
|
if (!articleIds.has(id)) errors.push(`MISSING (index): [[${id}]]`);
|
|
60
76
|
}
|
|
61
|
-
|
|
62
77
|
for (const file of articleFiles) {
|
|
63
78
|
const id = file.slice(0, -3);
|
|
64
|
-
|
|
79
|
+
let text;
|
|
80
|
+
try {
|
|
81
|
+
text = await readFile(await safePath(wikiRoot, `wiki/${file}`), "utf8");
|
|
82
|
+
frontmatter(text);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
errors.push(error.message);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
65
87
|
const heading = text.match(H1_RE);
|
|
66
88
|
if (!heading || heading[1] !== id) errors.push(`H1 MISMATCH: ${file} expected # ${id}`);
|
|
67
|
-
if (!
|
|
89
|
+
if (!sourceSection(text)) errors.push(`NO SOURCE SECTION: ${file}`);
|
|
90
|
+
const article = manifest?.articles.find((a) => a.id === id);
|
|
91
|
+
if (article && ownership(article, text).conflict) errors.push(`OWNERSHIP_CONFLICT: ${id}`);
|
|
68
92
|
if (!indexed.has(id)) errors.push(`ORPHAN: ${file}`);
|
|
69
93
|
const links = extractLinks(text);
|
|
70
94
|
for (const target of links.invalid) errors.push(`CROSS-WIKI: ${file} -> [[${target}]]`);
|
|
@@ -73,76 +97,25 @@ export async function lintWiki(wikiRoot, { repoRoot = process.cwd() } = {}) {
|
|
|
73
97
|
if (!articleIds.has(target)) errors.push(`MISSING: ${file} -> [[${target}]]`);
|
|
74
98
|
}
|
|
75
99
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const manifest
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for (const article of manifest.articles || []) {
|
|
86
|
-
const rel = path.posix.normalize(article.file || "");
|
|
87
|
-
listedFiles.add(rel);
|
|
88
|
-
const expectedId = path.posix.basename(rel, ".md");
|
|
89
|
-
if (article.id !== expectedId) {
|
|
90
|
-
errors.push(`MANIFEST ID MISMATCH: ${article.file} id=${article.id} expected ${expectedId}`);
|
|
91
|
-
}
|
|
92
|
-
const file = path.resolve(wikiRoot, article.file);
|
|
93
|
-
if (!(await exists(file))) errors.push(`MANIFEST ARTICLE MISSING: ${article.file}`);
|
|
94
|
-
for (const sourceId of article.sourceIds || []) {
|
|
95
|
-
if (!sourceById.has(sourceId)) {
|
|
96
|
-
errors.push(`UNKNOWN SOURCE ID: ${article.id} -> ${sourceId}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
for (const file of articleFiles) {
|
|
101
|
-
const rel = path.posix.join("wiki", file);
|
|
102
|
-
if (!listedFiles.has(rel)) errors.push(`UNLISTED ARTICLE: ${file}`);
|
|
103
|
-
}
|
|
104
|
-
for (const source of manifest.sources || []) {
|
|
105
|
-
if (manifest.profile === "documents" && source.kind === "code-surface") {
|
|
106
|
-
errors.push(`PROFILE KIND: documents forbids code-surface (${source.id})`);
|
|
107
|
-
}
|
|
108
|
-
if (source.kind === "document" || source.kind === "derived") {
|
|
109
|
-
if (!source.rawPath) {
|
|
110
|
-
errors.push(`RAW PATH REQUIRED: ${source.id} (${source.kind})`);
|
|
111
|
-
} else {
|
|
112
|
-
const raw = path.resolve(wikiRoot, source.rawPath);
|
|
113
|
-
if (!(await exists(raw))) errors.push(`RAW MISSING: ${source.id} (${source.rawPath})`);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (source.kind === "derived") {
|
|
117
|
-
const extractKind = source.extract?.kind;
|
|
118
|
-
if (!extractKind) errors.push(`EXTRACT REQUIRED: ${source.id}`);
|
|
119
|
-
else if (!EXTRACT_KINDS.includes(extractKind)) {
|
|
120
|
-
errors.push(`EXTRACT KIND: ${source.id} (${extractKind})`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (source.kind === "code-surface" && source.rawPath != null) {
|
|
124
|
-
errors.push(`RAW PATH FORBIDDEN: ${source.id} (code-surface)`);
|
|
125
|
-
}
|
|
126
|
-
if (!source.livePath) continue;
|
|
127
|
-
const live = path.resolve(repoRoot, source.livePath);
|
|
128
|
-
if (!(await exists(live))) {
|
|
129
|
-
errors.push(`MANIFEST SOURCE MISSING: ${source.id} (${source.livePath})`);
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
const current = sha256(await readFile(live));
|
|
133
|
-
if (!source.sha256 || current !== source.sha256) {
|
|
134
|
-
errors.push(`STALE HASH: ${source.id} (${source.livePath})`);
|
|
135
|
-
}
|
|
100
|
+
if (manifest) {
|
|
101
|
+
const listed = new Set(manifest.articles.map((a) => a.file));
|
|
102
|
+
for (const file of articleFiles) if (!listed.has(`wiki/${file}`)) errors.push(`UNLISTED ARTICLE: ${file}`);
|
|
103
|
+
for (const a of manifest.articles) if (!await exists(await safePath(wikiRoot, a.file))) errors.push(`MANIFEST ARTICLE MISSING: ${a.file}`);
|
|
104
|
+
for (const s of manifest.sources) if (s.rawPath && !await exists(await safePath(wikiRoot, s.rawPath))) errors.push(`RAW MISSING: ${s.id} (${s.rawPath})`);
|
|
105
|
+
if (!structureOnly) {
|
|
106
|
+
const report = await drift({ wikiRoot, repoRoot });
|
|
107
|
+
for (const s of report.sourceStates) if (!["current", "archived"].includes(s.state)) errors.push(`STALE HASH / ${s.state}: ${s.id} (${s.reason})`);
|
|
108
|
+
for (const a of report.articleStates) if (!["current", "archived"].includes(a.state)) errors.push(`ARTICLE ${a.state}: ${a.id} (${a.reason})`);
|
|
136
109
|
}
|
|
137
110
|
}
|
|
138
|
-
|
|
111
|
+
const tx = await transactionState(wikiRoot);
|
|
112
|
+
if (tx.incomplete || tx.state === "locked") errors.push("TRANSACTION_INCOMPLETE");
|
|
139
113
|
return {
|
|
140
114
|
ok: errors.length === 0,
|
|
141
115
|
errors,
|
|
142
|
-
counts: { articles: articleFiles.length, links: linkCount }
|
|
116
|
+
counts: { articles: articleFiles.length, links: linkCount }
|
|
143
117
|
};
|
|
144
118
|
}
|
|
145
|
-
|
|
146
119
|
async function main(argv = process.argv.slice(2)) {
|
|
147
120
|
let wikiArg;
|
|
148
121
|
let repoRoot = process.cwd();
|
|
@@ -155,23 +128,27 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
155
128
|
throw new Error("usage: lint-wikilinks.mjs <wiki-root> [--repo <repo-root>]");
|
|
156
129
|
}
|
|
157
130
|
const wikiRoot = path.resolve(repoRoot, wikiArg);
|
|
158
|
-
const result = await lintWiki(wikiRoot, { repoRoot });
|
|
159
|
-
for (const error of result.errors) process.stdout.write(`${error}
|
|
131
|
+
const result = await lintWiki(wikiRoot, { repoRoot, structureOnly: argv.includes("--structure-only") });
|
|
132
|
+
for (const error of result.errors) process.stdout.write(`${error}
|
|
133
|
+
`);
|
|
160
134
|
process.stdout.write(
|
|
161
|
-
`校验完成:${result.counts.articles || 0} 篇文章,${result.counts.links || 0} 条 wikilink
|
|
135
|
+
`校验完成:${result.counts.articles || 0} 篇文章,${result.counts.links || 0} 条 wikilink
|
|
136
|
+
`
|
|
162
137
|
);
|
|
163
138
|
if (result.ok) process.stdout.write("通过:所有 wikilink / 来源 / 索引检查通过\n");
|
|
164
139
|
else {
|
|
165
140
|
process.stdout.write(
|
|
166
|
-
"失败:存在缺失的 wikilink、孤儿页、来源小节、跨路径链接、H1 或 manifest 闭合问题\n"
|
|
141
|
+
"失败:存在缺失的 wikilink、孤儿页、来源小节、跨路径链接、H1 或 manifest 闭合问题\n"
|
|
167
142
|
);
|
|
168
143
|
process.exitCode = 1;
|
|
169
144
|
}
|
|
170
145
|
}
|
|
171
|
-
|
|
172
146
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
173
|
-
main().catch(
|
|
174
|
-
process.stderr.write(`${error.message}\n`);
|
|
175
|
-
process.exitCode = 2;
|
|
176
|
-
});
|
|
147
|
+
main().catch(cliError);
|
|
177
148
|
}
|
|
149
|
+
export {
|
|
150
|
+
INFRA,
|
|
151
|
+
articlesDir,
|
|
152
|
+
extractLinks,
|
|
153
|
+
lintWiki
|
|
154
|
+
};
|
|
@@ -6,16 +6,13 @@ import test from "node:test";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { sha256 } from "./inventory.mjs";
|
|
8
8
|
import { lintWiki } from "./lint-wikilinks.mjs";
|
|
9
|
-
|
|
10
9
|
const skillRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
10
|
const broken = path.join(skillRoot, "assets/fixtures/broken-wiki");
|
|
12
|
-
|
|
13
11
|
test("broken fixture fails on dangling wikilink", async () => {
|
|
14
12
|
const result = await lintWiki(broken);
|
|
15
13
|
assert.equal(result.ok, false);
|
|
16
14
|
assert.ok(result.errors.some((line) => line.includes("[[不存在的页]]")));
|
|
17
15
|
});
|
|
18
|
-
|
|
19
16
|
test("complete wiki passes wikilink, index, and source-section checks", async () => {
|
|
20
17
|
const root = await mkdtemp(path.join(tmpdir(), "llm-wiki-lint-"));
|
|
21
18
|
const wiki = path.join(root, "wiki");
|
|
@@ -23,19 +20,18 @@ test("complete wiki passes wikilink, index, and source-section checks", async ()
|
|
|
23
20
|
await writeFile(
|
|
24
21
|
path.join(wiki, "index.md"),
|
|
25
22
|
"# index\n\n## 分类\n\n- [[Alpha]]\n",
|
|
26
|
-
"utf8"
|
|
23
|
+
"utf8"
|
|
27
24
|
);
|
|
28
25
|
await writeFile(
|
|
29
26
|
path.join(wiki, "Alpha.md"),
|
|
30
27
|
"# Alpha\n\nSee [[Alpha]].\n\n## 来源\n\n- live\n",
|
|
31
|
-
"utf8"
|
|
28
|
+
"utf8"
|
|
32
29
|
);
|
|
33
30
|
await writeFile(path.join(wiki, "CLAUDE.md"), "# schema\n", "utf8");
|
|
34
31
|
const result = await lintWiki(root);
|
|
35
32
|
assert.equal(result.ok, true, result.errors.join("\n"));
|
|
36
33
|
assert.equal(result.counts.articles, 1);
|
|
37
34
|
});
|
|
38
|
-
|
|
39
35
|
test("cross-path wikilink fails instead of being ignored", async () => {
|
|
40
36
|
const root = await mkdtemp(path.join(tmpdir(), "llm-wiki-cross-"));
|
|
41
37
|
const wiki = path.join(root, "wiki");
|
|
@@ -44,13 +40,12 @@ test("cross-path wikilink fails instead of being ignored", async () => {
|
|
|
44
40
|
await writeFile(
|
|
45
41
|
path.join(wiki, "Alpha.md"),
|
|
46
42
|
"# Alpha\n\nSee [[../other]]\n\n## 来源\n\n- live\n",
|
|
47
|
-
"utf8"
|
|
43
|
+
"utf8"
|
|
48
44
|
);
|
|
49
45
|
const result = await lintWiki(root);
|
|
50
46
|
assert.equal(result.ok, false);
|
|
51
47
|
assert.ok(result.errors.some((line) => line.includes("CROSS-WIKI") && line.includes("[[../other]]")));
|
|
52
48
|
});
|
|
53
|
-
|
|
54
49
|
test("manifest sha256 mismatch is stale", async () => {
|
|
55
50
|
const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-hash-"));
|
|
56
51
|
const wikiRoot = path.join(repo, "wiki-root");
|
|
@@ -73,18 +68,17 @@ test("manifest sha256 mismatch is stale", async () => {
|
|
|
73
68
|
kind: "document",
|
|
74
69
|
livePath: liveRel,
|
|
75
70
|
rawPath: "raw/api.md",
|
|
76
|
-
sha256: sha256(Buffer.from("v1\n"))
|
|
77
|
-
}
|
|
71
|
+
sha256: sha256(Buffer.from("v1\n"))
|
|
72
|
+
}
|
|
78
73
|
],
|
|
79
|
-
articles: [{ id: "API", file: "wiki/API.md", sourceIds: ["api.md"] }]
|
|
74
|
+
articles: [{ id: "API", file: "wiki/API.md", sourceIds: ["api.md"] }]
|
|
80
75
|
}),
|
|
81
|
-
"utf8"
|
|
76
|
+
"utf8"
|
|
82
77
|
);
|
|
83
78
|
const result = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
84
79
|
assert.equal(result.ok, false);
|
|
85
80
|
assert.ok(result.errors.some((line) => line.includes("STALE HASH") && line.includes("api.md")));
|
|
86
81
|
});
|
|
87
|
-
|
|
88
82
|
async function seedClosedWiki() {
|
|
89
83
|
const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-closed-"));
|
|
90
84
|
const wikiRoot = path.join(repo, "wiki-root");
|
|
@@ -99,7 +93,7 @@ async function seedClosedWiki() {
|
|
|
99
93
|
await writeFile(
|
|
100
94
|
path.join(wiki, "Alpha.md"),
|
|
101
95
|
"# Alpha\n\nSee [[Alpha]].\n\n## 来源\n\n- live\n",
|
|
102
|
-
"utf8"
|
|
96
|
+
"utf8"
|
|
103
97
|
);
|
|
104
98
|
const manifest = {
|
|
105
99
|
schemaVersion: 1,
|
|
@@ -110,21 +104,19 @@ async function seedClosedWiki() {
|
|
|
110
104
|
kind: "document",
|
|
111
105
|
livePath: liveRel,
|
|
112
106
|
rawPath: "raw/api.md",
|
|
113
|
-
sha256: sha256(Buffer.from("v1\n"))
|
|
114
|
-
}
|
|
107
|
+
sha256: sha256(Buffer.from("v1\n"))
|
|
108
|
+
}
|
|
115
109
|
],
|
|
116
|
-
articles: [{ id: "Alpha", file: "wiki/Alpha.md", sourceIds: ["api.md"] }]
|
|
110
|
+
articles: [{ id: "Alpha", file: "wiki/Alpha.md", sourceIds: ["api.md"] }]
|
|
117
111
|
};
|
|
118
112
|
await writeFile(path.join(wikiRoot, ".wiki-manifest.json"), JSON.stringify(manifest), "utf8");
|
|
119
113
|
return { repo, wikiRoot, wiki, manifest };
|
|
120
114
|
}
|
|
121
|
-
|
|
122
115
|
test("closed manifest passes listing, id, sourceIds, profile, and rawPath checks", async () => {
|
|
123
116
|
const { repo, wikiRoot } = await seedClosedWiki();
|
|
124
|
-
const result = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
117
|
+
const result = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
125
118
|
assert.equal(result.ok, true, result.errors.join("\n"));
|
|
126
119
|
});
|
|
127
|
-
|
|
128
120
|
test("open manifest fails unlisted article, id mismatch, unknown source, profile kind, and rawPath", async () => {
|
|
129
121
|
const repo = await mkdtemp(path.join(tmpdir(), "llm-wiki-open-"));
|
|
130
122
|
const wikiRoot = path.join(repo, "wiki-root");
|
|
@@ -146,27 +138,27 @@ test("open manifest fails unlisted article, id mismatch, unknown source, profile
|
|
|
146
138
|
kind: "code-surface",
|
|
147
139
|
livePath: "docs/api.md",
|
|
148
140
|
rawPath: "raw/should-not-exist.md",
|
|
149
|
-
sha256: sha256(Buffer.from("v1\n"))
|
|
141
|
+
sha256: sha256(Buffer.from("v1\n"))
|
|
150
142
|
},
|
|
151
143
|
{
|
|
152
144
|
id: "note",
|
|
153
145
|
kind: "document",
|
|
154
146
|
livePath: "docs/api.md",
|
|
155
147
|
rawPath: "",
|
|
156
|
-
sha256: sha256(Buffer.from("v1\n"))
|
|
157
|
-
}
|
|
148
|
+
sha256: sha256(Buffer.from("v1\n"))
|
|
149
|
+
}
|
|
158
150
|
],
|
|
159
151
|
articles: [
|
|
160
152
|
{
|
|
161
153
|
id: "WrongId",
|
|
162
154
|
file: "wiki/Alpha.md",
|
|
163
|
-
sourceIds: ["api.md", "ghost"]
|
|
164
|
-
}
|
|
165
|
-
]
|
|
155
|
+
sourceIds: ["api.md", "ghost"]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
166
158
|
}),
|
|
167
|
-
"utf8"
|
|
159
|
+
"utf8"
|
|
168
160
|
);
|
|
169
|
-
const result = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
161
|
+
const result = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
170
162
|
assert.equal(result.ok, false);
|
|
171
163
|
assert.ok(result.errors.some((line) => line.includes("UNLISTED ARTICLE") && line.includes("Beta.md")));
|
|
172
164
|
assert.ok(result.errors.some((line) => line.includes("MANIFEST ID MISMATCH") && line.includes("WrongId")));
|
|
@@ -175,7 +167,6 @@ test("open manifest fails unlisted article, id mismatch, unknown source, profile
|
|
|
175
167
|
assert.ok(result.errors.some((line) => line.includes("RAW PATH REQUIRED") && line.includes("note")));
|
|
176
168
|
assert.ok(result.errors.some((line) => line.includes("RAW PATH FORBIDDEN") && line.includes("api.md")));
|
|
177
169
|
});
|
|
178
|
-
|
|
179
170
|
test("derived source requires a known extract.kind", async () => {
|
|
180
171
|
const { repo, wikiRoot, manifest } = await seedClosedWiki();
|
|
181
172
|
manifest.sources.push({
|
|
@@ -183,30 +174,27 @@ test("derived source requires a known extract.kind", async () => {
|
|
|
183
174
|
kind: "derived",
|
|
184
175
|
livePath: "docs/api.md",
|
|
185
176
|
rawPath: "raw/api.md",
|
|
186
|
-
sha256: sha256(Buffer.from("v1\n"))
|
|
177
|
+
sha256: sha256(Buffer.from("v1\n"))
|
|
187
178
|
});
|
|
188
179
|
await writeFile(path.join(wikiRoot, ".wiki-manifest.json"), JSON.stringify(manifest), "utf8");
|
|
189
|
-
const missing = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
180
|
+
const missing = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
190
181
|
assert.equal(missing.ok, false);
|
|
191
182
|
assert.ok(missing.errors.some((line) => line.includes("EXTRACT REQUIRED") && line.includes("lock")));
|
|
192
|
-
|
|
193
183
|
manifest.sources.at(-1).extract = { kind: "whole-file" };
|
|
194
184
|
await writeFile(path.join(wikiRoot, ".wiki-manifest.json"), JSON.stringify(manifest), "utf8");
|
|
195
|
-
const unknown = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
185
|
+
const unknown = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
196
186
|
assert.equal(unknown.ok, false);
|
|
197
187
|
assert.ok(unknown.errors.some((line) => line.includes("EXTRACT KIND") && line.includes("whole-file")));
|
|
198
|
-
|
|
199
188
|
manifest.sources.at(-1).extract = { kind: "skill-names" };
|
|
200
189
|
await writeFile(path.join(wikiRoot, ".wiki-manifest.json"), JSON.stringify(manifest), "utf8");
|
|
201
|
-
const ok = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
190
|
+
const ok = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
202
191
|
assert.equal(ok.ok, true, ok.errors.join("\n"));
|
|
203
192
|
});
|
|
204
|
-
|
|
205
193
|
test("document rawPath must exist on disk", async () => {
|
|
206
194
|
const { repo, wikiRoot, manifest } = await seedClosedWiki();
|
|
207
195
|
manifest.sources[0].rawPath = "raw/missing.md";
|
|
208
196
|
await writeFile(path.join(wikiRoot, ".wiki-manifest.json"), JSON.stringify(manifest), "utf8");
|
|
209
|
-
const result = await lintWiki(wikiRoot, { repoRoot: repo });
|
|
197
|
+
const result = await lintWiki(wikiRoot, { repoRoot: repo, structureOnly: true });
|
|
210
198
|
assert.equal(result.ok, false);
|
|
211
199
|
assert.ok(result.errors.some((line) => line.includes("RAW MISSING") && line.includes("raw/missing.md")));
|
|
212
200
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { loadManifest, safePath, digestFile, sha256, json, ownership, fail, args, cliError } from "./core.mjs";
|
|
6
|
+
import { createPlan, applyPlan } from "./transaction.mjs";
|
|
7
|
+
async function migrate({ wikiRoot, repoRoot = process.cwd(), apply = false }) {
|
|
8
|
+
const prior = await loadManifest(wikiRoot, { repoRoot });
|
|
9
|
+
if (prior.schemaVersion === 2) return { schemaVersion: 2, changed: false, readOnly: !apply };
|
|
10
|
+
const original = await readFile(await safePath(wikiRoot, ".wiki-manifest.json"), "utf8");
|
|
11
|
+
const manifest = structuredClone(prior);
|
|
12
|
+
manifest.schemaVersion = 2;
|
|
13
|
+
manifest.profile ||= "mixed";
|
|
14
|
+
manifest.feedback = [];
|
|
15
|
+
for (const s of manifest.sources) {
|
|
16
|
+
s.originalDigest = s.sha256 || null;
|
|
17
|
+
s.effectiveDigest = s.kind === "derived" ? null : s.sha256 || null;
|
|
18
|
+
s.rawDigest = s.rawPath ? await digestFile(await safePath(wikiRoot, s.rawPath)) : null;
|
|
19
|
+
s.location = s.livePath || s.url || `snapshot:${s.rawPath}`;
|
|
20
|
+
if (s.kind === "derived") {
|
|
21
|
+
s.extract = { ...s.extract, version: "1", inputs: s.extract?.inputs || [s.livePath].filter(Boolean) };
|
|
22
|
+
if (s.extract.kind === "prose-note") {
|
|
23
|
+
s.extract.inputDigests = {};
|
|
24
|
+
s.extract.rules ||= "legacy-unknown; explicit recipe required before recompilation";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const a of manifest.articles) {
|
|
29
|
+
a.articleDigest = null;
|
|
30
|
+
a.compiledFrom = {};
|
|
31
|
+
a.compiledDependencies = {};
|
|
32
|
+
a.verification = null;
|
|
33
|
+
a.dependsOnArticles ||= [];
|
|
34
|
+
a.aliases ||= [];
|
|
35
|
+
const text = await readFile(await safePath(wikiRoot, a.file), "utf8");
|
|
36
|
+
a.humanOwned = ownership(a, text).protected;
|
|
37
|
+
}
|
|
38
|
+
const backup = `.wiki-backups/manifest-v1-${sha256(original)}.json`;
|
|
39
|
+
const plan = await createPlan({ wikiRoot, repoRoot, request: { operation: "migrate", manifest, writes: [{ path: backup, content: original }], authorization: { confirmed: true, paths: [backup, ".wiki-manifest.json", "wiki/log.md"] } } });
|
|
40
|
+
if (!apply) return { changed: true, readOnly: true, backup, plan };
|
|
41
|
+
return { ...await applyPlan({ wikiRoot, repoRoot, plan }), changed: true, backup, remaining: "unverified; migration does not compile articles" };
|
|
42
|
+
}
|
|
43
|
+
async function main() {
|
|
44
|
+
const a = args(process.argv.slice(2));
|
|
45
|
+
if (!a.wiki) fail("USAGE", "migrate.mjs --wiki <root> [--repo <root>] [--apply]");
|
|
46
|
+
process.stdout.write(json(await migrate({ wikiRoot: path.resolve(a.repo, a.wiki), repoRoot: path.resolve(a.repo), apply: a.apply === true })));
|
|
47
|
+
}
|
|
48
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main().catch(cliError);
|
|
49
|
+
export {
|
|
50
|
+
migrate
|
|
51
|
+
};
|