project-tiny-context-harness 0.2.84 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -428
- package/assets/README.md +283 -455
- package/assets/README.zh-CN.md +199 -123
- package/assets/agents/AGENTS_CORE.md +54 -67
- package/assets/context_templates/context.toml +3 -0
- package/assets/context_templates/global.md +6 -6
- package/assets/github/harness.yml +2 -2
- package/assets/skills/context_development_engineer/SKILL.md +91 -107
- package/assets/skills/context_product_plan/SKILL.md +18 -28
- package/assets/skills/context_surface_contract/SKILL.md +35 -38
- package/assets/skills/context_uiux_design/SKILL.md +31 -30
- package/assets/skills/long-task-workflow/SKILL.md +76 -0
- package/assets/skills/long-task-workflow/agents/openai.yaml +4 -0
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +41 -0
- package/assets/skills/long-task-workflow/references/contract-authoring.md +62 -0
- package/assets/skills/long-task-workflow/references/evidence-design.md +45 -0
- package/assets/skills/normal-long-task/SKILL.md +12 -489
- package/assets/skills/source-plan-authoring/SKILL.md +379 -0
- package/assets/tools/validate_context.py +293 -127
- package/dist/cli.js +3 -1
- package/dist/commands/check-modularity.js +33 -10
- package/dist/commands/composite-campaign.d.ts +1 -0
- package/dist/commands/composite-campaign.js +8 -0
- package/dist/commands/composite-long-task.d.ts +1 -6
- package/dist/commands/composite-long-task.js +7 -157
- package/dist/commands/delivery-set.d.ts +1 -0
- package/dist/commands/delivery-set.js +8 -0
- package/dist/commands/disable.d.ts +1 -0
- package/dist/commands/disable.js +15 -0
- package/dist/commands/enable.d.ts +1 -0
- package/dist/commands/enable.js +14 -0
- package/dist/commands/export-context-args.js +13 -4
- package/dist/commands/export-context.js +18 -7
- package/dist/commands/index.js +42 -30
- package/dist/commands/init.js +12 -6
- package/dist/commands/long-task-authoring.d.ts +3 -0
- package/dist/commands/long-task-authoring.js +92 -0
- package/dist/commands/long-task-explain.d.ts +1 -0
- package/dist/commands/long-task-explain.js +52 -0
- package/dist/commands/long-task.d.ts +1 -0
- package/dist/commands/long-task.js +226 -0
- package/dist/commands/package-source.js +2 -2
- package/dist/commands/upgrade.js +10 -10
- package/dist/index.d.ts +11 -1
- package/dist/index.js +8 -0
- package/dist/lib/config.js +34 -8
- package/dist/lib/context-default-footprint.d.ts +16 -0
- package/dist/lib/context-default-footprint.js +107 -0
- package/dist/lib/context-export.js +105 -41
- package/dist/lib/context-graph-snapshot.d.ts +18 -0
- package/dist/lib/context-graph-snapshot.js +171 -0
- package/dist/lib/context-manifest-schema.d.ts +28 -0
- package/dist/lib/context-manifest-schema.js +150 -0
- package/dist/lib/context-manifest.js +28 -20
- package/dist/lib/context-templates.js +5 -5
- package/dist/lib/design-md.js +1 -1
- package/dist/lib/doctor.js +54 -1
- package/dist/lib/harness-root.js +25 -8
- package/dist/lib/init.js +6 -3
- package/dist/lib/legacy-managed-scan.js +23 -7
- package/dist/lib/legacy-sdlc-migration.js +21 -11
- package/dist/lib/long-task-acceptance-reference.d.ts +22 -0
- package/dist/lib/long-task-acceptance-reference.js +46 -0
- package/dist/lib/long-task-acceptance-shape.d.ts +5 -0
- package/dist/lib/long-task-acceptance-shape.js +131 -0
- package/dist/lib/long-task-activation-validation.d.ts +21 -0
- package/dist/lib/long-task-activation-validation.js +136 -0
- package/dist/lib/long-task-artifacts.d.ts +5 -0
- package/dist/lib/long-task-artifacts.js +34 -0
- package/dist/lib/long-task-assertions-v2.d.ts +22 -0
- package/dist/lib/long-task-assertions-v2.js +212 -0
- package/dist/lib/long-task-authoring-authority-preview.d.ts +5 -0
- package/dist/lib/long-task-authoring-authority-preview.js +85 -0
- package/dist/lib/long-task-authoring-preflight-diagnostics.d.ts +8 -0
- package/dist/lib/long-task-authoring-preflight-diagnostics.js +179 -0
- package/dist/lib/long-task-authoring-preflight-repair-order.d.ts +8 -0
- package/dist/lib/long-task-authoring-preflight-repair-order.js +95 -0
- package/dist/lib/long-task-authoring-preflight-types.d.ts +46 -0
- package/dist/lib/long-task-authoring-preflight-types.js +38 -0
- package/dist/lib/long-task-authoring-preflight.d.ts +3 -0
- package/dist/lib/long-task-authoring-preflight.js +44 -0
- package/dist/lib/long-task-authority-material-diff.d.ts +17 -0
- package/dist/lib/long-task-authority-material-diff.js +152 -0
- package/dist/lib/long-task-authority-materials.d.ts +7 -0
- package/dist/lib/long-task-authority-materials.js +83 -0
- package/dist/lib/long-task-authority-policy.d.ts +168 -0
- package/dist/lib/long-task-authority-policy.js +181 -0
- package/dist/lib/long-task-authority-revision-details.d.ts +19 -0
- package/dist/lib/long-task-authority-revision-details.js +192 -0
- package/dist/lib/long-task-authority-revision-enforcement.d.ts +3 -0
- package/dist/lib/long-task-authority-revision-enforcement.js +41 -0
- package/dist/lib/long-task-authority-revision-types.d.ts +50 -0
- package/dist/lib/long-task-authority-revision-types.js +1 -0
- package/dist/lib/long-task-authority-revision.d.ts +4 -0
- package/dist/lib/long-task-authority-revision.js +188 -0
- package/dist/lib/long-task-authority-transition-policy.d.ts +62 -0
- package/dist/lib/long-task-authority-transition-policy.js +62 -0
- package/dist/lib/long-task-authority-types.d.ts +96 -0
- package/dist/lib/long-task-authority-types.js +1 -0
- package/dist/lib/long-task-authority.d.ts +7 -0
- package/dist/lib/long-task-authority.js +142 -0
- package/dist/lib/long-task-boundary-check.d.ts +15 -0
- package/dist/lib/long-task-boundary-check.js +9 -0
- package/dist/lib/long-task-check-evidence-decoder.d.ts +3 -0
- package/dist/lib/long-task-check-evidence-decoder.js +74 -0
- package/dist/lib/long-task-check-execution-policy.d.ts +18 -0
- package/dist/lib/long-task-check-execution-policy.js +36 -0
- package/dist/lib/long-task-check-runner.d.ts +2 -0
- package/dist/lib/long-task-check-runner.js +181 -0
- package/dist/lib/long-task-check-shape.d.ts +2 -0
- package/dist/lib/long-task-check-shape.js +136 -0
- package/dist/lib/long-task-claim-definitions.d.ts +7 -0
- package/dist/lib/long-task-claim-definitions.js +78 -0
- package/dist/lib/long-task-claim-proof-policy.d.ts +4 -0
- package/dist/lib/long-task-claim-proof-policy.js +57 -0
- package/dist/lib/long-task-claims.d.ts +10 -0
- package/dist/lib/long-task-claims.js +187 -0
- package/dist/lib/long-task-context-authority-topology.d.ts +7 -0
- package/dist/lib/long-task-context-authority-topology.js +37 -0
- package/dist/lib/long-task-context-authority.d.ts +14 -0
- package/dist/lib/long-task-context-authority.js +66 -0
- package/dist/lib/long-task-contract-types.d.ts +203 -0
- package/dist/lib/long-task-contract-types.js +1 -0
- package/dist/lib/long-task-counterfactual-claim-policy.d.ts +10 -0
- package/dist/lib/long-task-counterfactual-claim-policy.js +57 -0
- package/dist/lib/long-task-counterfactual-sandbox.d.ts +6 -0
- package/dist/lib/long-task-counterfactual-sandbox.js +87 -0
- package/dist/lib/long-task-counterfactual-types.d.ts +24 -0
- package/dist/lib/long-task-counterfactual-types.js +1 -0
- package/dist/lib/long-task-delivery-compiler.d.ts +10 -0
- package/dist/lib/long-task-delivery-compiler.js +129 -0
- package/dist/lib/long-task-delivery-parser.d.ts +13 -0
- package/dist/lib/long-task-delivery-parser.js +90 -0
- package/dist/lib/long-task-delivery-preflight.d.ts +5 -0
- package/dist/lib/long-task-delivery-preflight.js +151 -0
- package/dist/lib/long-task-delivery-shape.d.ts +5 -0
- package/dist/lib/long-task-delivery-shape.js +5 -0
- package/dist/lib/long-task-delivery-types.d.ts +8 -0
- package/dist/lib/long-task-delivery-types.js +8 -0
- package/dist/lib/long-task-delivery-validation.d.ts +3 -0
- package/dist/lib/long-task-delivery-validation.js +175 -0
- package/dist/lib/long-task-evidence-adapter-policy.d.ts +4 -0
- package/dist/lib/long-task-evidence-adapter-policy.js +15 -0
- package/dist/lib/long-task-evidence-adapter-types.d.ts +1 -0
- package/dist/lib/long-task-evidence-adapter-types.js +1 -0
- package/dist/lib/long-task-evidence-findings.d.ts +5 -0
- package/dist/lib/long-task-evidence-findings.js +113 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.d.ts +4 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.js +98 -0
- package/dist/lib/long-task-evidence-v2.d.ts +5 -0
- package/dist/lib/long-task-evidence-v2.js +226 -0
- package/dist/lib/long-task-explain-acceptance-link.d.ts +46 -0
- package/dist/lib/long-task-explain-acceptance-link.js +96 -0
- package/dist/lib/long-task-explain-claim-links.d.ts +45 -0
- package/dist/lib/long-task-explain-claim-links.js +88 -0
- package/dist/lib/long-task-explain-source-links.d.ts +93 -0
- package/dist/lib/long-task-explain-source-links.js +51 -0
- package/dist/lib/long-task-final-v2.d.ts +2 -0
- package/dist/lib/long-task-final-v2.js +124 -0
- package/dist/lib/long-task-finding-context.d.ts +3 -0
- package/dist/lib/long-task-finding-context.js +63 -0
- package/dist/lib/long-task-freshness.d.ts +3 -0
- package/dist/lib/long-task-freshness.js +80 -0
- package/dist/lib/long-task-hook-install.d.ts +9 -0
- package/dist/lib/long-task-hook-install.js +184 -0
- package/dist/lib/long-task-hook-preflight.d.ts +7 -0
- package/dist/lib/long-task-hook-preflight.js +58 -0
- package/dist/lib/long-task-observation-ownership.d.ts +2 -0
- package/dist/lib/long-task-observation-ownership.js +22 -0
- package/dist/lib/long-task-outcome-parser.d.ts +4 -0
- package/dist/lib/long-task-outcome-parser.js +100 -0
- package/dist/lib/long-task-paths.d.ts +49 -0
- package/dist/lib/long-task-paths.js +418 -0
- package/dist/lib/long-task-playwright-counterfactual-policy.d.ts +7 -0
- package/dist/lib/long-task-playwright-counterfactual-policy.js +125 -0
- package/dist/lib/long-task-playwright-evidence.d.ts +6 -0
- package/dist/lib/long-task-playwright-evidence.js +244 -0
- package/dist/lib/long-task-product-shape.d.ts +6 -0
- package/dist/lib/long-task-product-shape.js +73 -0
- package/dist/lib/long-task-progress.d.ts +4 -0
- package/dist/lib/long-task-progress.js +114 -0
- package/dist/lib/long-task-protected-files.d.ts +1 -0
- package/dist/lib/long-task-protected-files.js +30 -0
- package/dist/lib/long-task-required-proof-surfaces.d.ts +2 -0
- package/dist/lib/long-task-required-proof-surfaces.js +13 -0
- package/dist/lib/long-task-requirement-shape.d.ts +2 -0
- package/dist/lib/long-task-requirement-shape.js +18 -0
- package/dist/lib/long-task-risk-surfaces.d.ts +2 -0
- package/dist/lib/long-task-risk-surfaces.js +60 -0
- package/dist/lib/long-task-risk-types.d.ts +5 -0
- package/dist/lib/long-task-risk-types.js +12 -0
- package/dist/lib/long-task-risk.d.ts +9 -0
- package/dist/lib/long-task-risk.js +132 -0
- package/dist/lib/long-task-root-shape.d.ts +4 -0
- package/dist/lib/long-task-root-shape.js +86 -0
- package/dist/lib/long-task-runner-environment.d.ts +7 -0
- package/dist/lib/long-task-runner-environment.js +57 -0
- package/dist/lib/long-task-runner-files.d.ts +3 -0
- package/dist/lib/long-task-runner-files.js +39 -0
- package/dist/lib/long-task-runner-freeze.d.ts +2 -0
- package/dist/lib/long-task-runner-freeze.js +168 -0
- package/dist/lib/long-task-runtime-types.d.ts +214 -0
- package/dist/lib/long-task-runtime-types.js +1 -0
- package/dist/lib/long-task-shape-primitives.d.ts +17 -0
- package/dist/lib/long-task-shape-primitives.js +81 -0
- package/dist/lib/long-task-source-authority-types.d.ts +13 -0
- package/dist/lib/long-task-source-authority-types.js +1 -0
- package/dist/lib/long-task-source-claim-validation.d.ts +5 -0
- package/dist/lib/long-task-source-claim-validation.js +96 -0
- package/dist/lib/long-task-source-continuity.d.ts +4 -0
- package/dist/lib/long-task-source-continuity.js +57 -0
- package/dist/lib/long-task-source-inventory.d.ts +2 -0
- package/dist/lib/long-task-source-inventory.js +21 -0
- package/dist/lib/long-task-source-item-parser.d.ts +3 -0
- package/dist/lib/long-task-source-item-parser.js +112 -0
- package/dist/lib/long-task-source-shape.d.ts +2 -0
- package/dist/lib/long-task-source-shape.js +56 -0
- package/dist/lib/long-task-source-target-continuity.d.ts +4 -0
- package/dist/lib/long-task-source-target-continuity.js +80 -0
- package/dist/lib/long-task-source-target-index.d.ts +12 -0
- package/dist/lib/long-task-source-target-index.js +76 -0
- package/dist/lib/long-task-source-validation.d.ts +3 -0
- package/dist/lib/long-task-source-validation.js +46 -0
- package/dist/lib/long-task-state.d.ts +91 -0
- package/dist/lib/long-task-state.js +611 -0
- package/dist/lib/long-task-status-projection.d.ts +21 -0
- package/dist/lib/long-task-status-projection.js +116 -0
- package/dist/lib/long-task-status-v2.d.ts +37 -0
- package/dist/lib/long-task-status-v2.js +306 -0
- package/dist/lib/long-task-technical-shape.d.ts +3 -0
- package/dist/lib/long-task-technical-shape.js +44 -0
- package/dist/lib/long-task-verifier-authority.d.ts +12 -0
- package/dist/lib/long-task-verifier-authority.js +47 -0
- package/dist/lib/long-task-verifier-identity.d.ts +2 -0
- package/dist/lib/long-task-verifier-identity.js +55 -0
- package/dist/lib/long-task-verifier-v2.d.ts +13 -0
- package/dist/lib/long-task-verifier-v2.js +266 -0
- package/dist/lib/long-task-workspace-runtime-types.d.ts +23 -0
- package/dist/lib/long-task-workspace-runtime-types.js +1 -0
- package/dist/lib/long-task-workspace.d.ts +25 -0
- package/dist/lib/long-task-workspace.js +366 -0
- package/dist/lib/managed-file.js +20 -5
- package/dist/lib/migrations.js +156 -32
- package/dist/lib/modularity.d.ts +27 -1
- package/dist/lib/modularity.js +499 -23
- package/dist/lib/package-json-config.js +14 -5
- package/dist/lib/package-source.js +15 -3
- package/dist/lib/profiles.d.ts +13 -0
- package/dist/lib/profiles.js +66 -0
- package/dist/lib/schema-guard.js +4 -2
- package/dist/lib/source-files.js +14 -7
- package/dist/lib/source-pack-classify.js +91 -19
- package/dist/lib/source-pack-config.js +25 -8
- package/dist/lib/source-pack-export.js +84 -25
- package/dist/lib/source-pack-manifest.js +18 -6
- package/dist/lib/source-pack-records.js +35 -11
- package/dist/lib/source-pack-render.js +47 -18
- package/dist/lib/stable-json.d.ts +2 -0
- package/dist/lib/stable-json.js +21 -0
- package/dist/lib/strict-codec.d.ts +4 -0
- package/dist/lib/strict-codec.js +65 -0
- package/dist/lib/sync-engine.js +76 -24
- package/dist/lib/types.d.ts +8 -1
- package/dist/lib/upgrade.js +4 -3
- package/dist/lib/validators.js +218 -191
- package/dist/long-task-hook.d.ts +2 -0
- package/dist/long-task-hook.js +55 -0
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +340 -0
- package/dist/schemas/long-task-delivery-v2/long-task-outcomes-v2.schema.json +18 -0
- package/migrations/README.md +8 -3
- package/package.json +17 -6
- package/source-mappings.yaml +0 -3
- package/assets/protected-harness-baseline.json +0 -20
- package/assets/skills/composite-long-task-workflow/SKILL.md +0 -244
- package/assets/skills/composite-long-task-workflow/assets/execution-binding.template.md +0 -57
- package/assets/skills/composite-long-task-workflow/assets/goal-objective.template.md +0 -17
- package/assets/skills/composite-long-task-workflow/references/composite-long-task-workflow-protocol.md +0 -675
- package/dist/commands/superpowers.d.ts +0 -1
- package/dist/commands/superpowers.js +0 -8
- package/dist/lib/composite-long-task-renderer.d.ts +0 -12
- package/dist/lib/composite-long-task-renderer.js +0 -109
- package/dist/lib/plan-acceptance-artifacts.d.ts +0 -1
- package/dist/lib/plan-acceptance-artifacts.js +0 -220
- package/dist/lib/plan-acceptance-evidence.d.ts +0 -2
- package/dist/lib/plan-acceptance-evidence.js +0 -108
- package/dist/lib/plan-acceptance-json.d.ts +0 -15
- package/dist/lib/plan-acceptance-json.js +0 -133
- package/dist/lib/plan-acceptance-validator.d.ts +0 -2
- package/dist/lib/plan-acceptance-validator.js +0 -209
- package/dist/lib/plan-contract-validator.d.ts +0 -2
- package/dist/lib/plan-contract-validator.js +0 -127
- package/dist/lib/plan-validator-common.d.ts +0 -24
- package/dist/lib/plan-validator-common.js +0 -196
- package/dist/lib/superpowers-task-ac010.d.ts +0 -6
- package/dist/lib/superpowers-task-ac010.js +0 -26
- package/dist/lib/superpowers-task-assertion-normalizers.d.ts +0 -3
- package/dist/lib/superpowers-task-assertion-normalizers.js +0 -74
- package/dist/lib/superpowers-task-assertions.d.ts +0 -20
- package/dist/lib/superpowers-task-assertions.js +0 -257
- package/dist/lib/superpowers-task-attempt.d.ts +0 -4
- package/dist/lib/superpowers-task-attempt.js +0 -102
- package/dist/lib/superpowers-task-command-run-correlation.d.ts +0 -8
- package/dist/lib/superpowers-task-command-run-correlation.js +0 -103
- package/dist/lib/superpowers-task-command-specs.d.ts +0 -3
- package/dist/lib/superpowers-task-command-specs.js +0 -52
- package/dist/lib/superpowers-task-compile-diagnostics.d.ts +0 -5
- package/dist/lib/superpowers-task-compile-diagnostics.js +0 -20
- package/dist/lib/superpowers-task-compile-guards.d.ts +0 -2
- package/dist/lib/superpowers-task-compile-guards.js +0 -66
- package/dist/lib/superpowers-task-compile.d.ts +0 -6
- package/dist/lib/superpowers-task-compile.js +0 -133
- package/dist/lib/superpowers-task-completion-output.d.ts +0 -52
- package/dist/lib/superpowers-task-completion-output.js +0 -228
- package/dist/lib/superpowers-task-conformance.d.ts +0 -2
- package/dist/lib/superpowers-task-conformance.js +0 -24
- package/dist/lib/superpowers-task-contradictions.d.ts +0 -6
- package/dist/lib/superpowers-task-contradictions.js +0 -126
- package/dist/lib/superpowers-task-current-evidence.d.ts +0 -3
- package/dist/lib/superpowers-task-current-evidence.js +0 -176
- package/dist/lib/superpowers-task-delivery.d.ts +0 -4
- package/dist/lib/superpowers-task-delivery.js +0 -96
- package/dist/lib/superpowers-task-derive.d.ts +0 -14
- package/dist/lib/superpowers-task-derive.js +0 -382
- package/dist/lib/superpowers-task-events.d.ts +0 -1
- package/dist/lib/superpowers-task-events.js +0 -13
- package/dist/lib/superpowers-task-evidence-kernel.d.ts +0 -19
- package/dist/lib/superpowers-task-evidence-kernel.js +0 -347
- package/dist/lib/superpowers-task-evidence-records.d.ts +0 -2
- package/dist/lib/superpowers-task-evidence-records.js +0 -55
- package/dist/lib/superpowers-task-evidence.d.ts +0 -10
- package/dist/lib/superpowers-task-evidence.js +0 -147
- package/dist/lib/superpowers-task-fields.d.ts +0 -22
- package/dist/lib/superpowers-task-fields.js +0 -276
- package/dist/lib/superpowers-task-final-card.d.ts +0 -3
- package/dist/lib/superpowers-task-final-card.js +0 -24
- package/dist/lib/superpowers-task-gates.d.ts +0 -12
- package/dist/lib/superpowers-task-gates.js +0 -155
- package/dist/lib/superpowers-task-harness-drift.d.ts +0 -11
- package/dist/lib/superpowers-task-harness-drift.js +0 -90
- package/dist/lib/superpowers-task-next-slices.d.ts +0 -1
- package/dist/lib/superpowers-task-next-slices.js +0 -12
- package/dist/lib/superpowers-task-protected-baseline.d.ts +0 -10
- package/dist/lib/superpowers-task-protected-baseline.js +0 -66
- package/dist/lib/superpowers-task-source-compile.d.ts +0 -5
- package/dist/lib/superpowers-task-source-compile.js +0 -226
- package/dist/lib/superpowers-task-source-parser.d.ts +0 -23
- package/dist/lib/superpowers-task-source-parser.js +0 -218
- package/dist/lib/superpowers-task-state-schema.d.ts +0 -440
- package/dist/lib/superpowers-task-state-schema.js +0 -66
- package/dist/lib/superpowers-task-state-shape.d.ts +0 -3
- package/dist/lib/superpowers-task-state-shape.js +0 -50
- package/dist/lib/superpowers-task-state.d.ts +0 -16
- package/dist/lib/superpowers-task-state.js +0 -246
- package/dist/lib/superpowers-task-status.d.ts +0 -2
- package/dist/lib/superpowers-task-status.js +0 -24
- package/dist/lib/superpowers-task-under-specified.d.ts +0 -7
- package/dist/lib/superpowers-task-under-specified.js +0 -61
- package/dist/lib/superpowers-task-unregistered-evidence.d.ts +0 -11
- package/dist/lib/superpowers-task-unregistered-evidence.js +0 -72
- package/dist/lib/superpowers-task-validator.d.ts +0 -5
- package/dist/lib/superpowers-task-validator.js +0 -290
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { parse } from "smol-toml";
|
|
2
|
+
const TOP_LEVEL_FIELDS = new Set(["areas", "context"]);
|
|
3
|
+
const AREA_FIELDS = new Set([
|
|
4
|
+
"id",
|
|
5
|
+
"root",
|
|
6
|
+
"context",
|
|
7
|
+
"kind",
|
|
8
|
+
"default",
|
|
9
|
+
"forbidden_runtime_dependencies",
|
|
10
|
+
]);
|
|
11
|
+
const CONTEXT_FIELDS = new Set([
|
|
12
|
+
"path",
|
|
13
|
+
"role",
|
|
14
|
+
"read_when",
|
|
15
|
+
"read_policy",
|
|
16
|
+
"triggers",
|
|
17
|
+
"default_children",
|
|
18
|
+
]);
|
|
19
|
+
export function parseContextManifest(content, file = "project_context/context.toml") {
|
|
20
|
+
const errors = [];
|
|
21
|
+
let parsed;
|
|
22
|
+
try {
|
|
23
|
+
parsed = parse(content);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
errors: [
|
|
28
|
+
`${file} is not valid TOML: ${error instanceof Error ? error.message : String(error)}`,
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
rejectUnknownFields(parsed, TOP_LEVEL_FIELDS, file, errors);
|
|
33
|
+
const rawAreas = tableArray(parsed.areas, "[[areas]]", file, errors);
|
|
34
|
+
const rawContexts = tableArray(parsed.context, "[[context]]", file, errors);
|
|
35
|
+
const areaLines = tableLines(content, "areas");
|
|
36
|
+
const contextLines = tableLines(content, "context");
|
|
37
|
+
const areas = [];
|
|
38
|
+
for (const [index, value] of rawAreas.entries()) {
|
|
39
|
+
const location = `${file} line ${areaLines[index] ?? 1}`;
|
|
40
|
+
rejectUnknownFields(value, AREA_FIELDS, location, errors);
|
|
41
|
+
const id = requiredString(value, "id", location, errors);
|
|
42
|
+
const root = requiredString(value, "root", location, errors);
|
|
43
|
+
const context = requiredString(value, "context", location, errors);
|
|
44
|
+
const kind = optionalString(value, "kind", location, errors);
|
|
45
|
+
const defaultArea = optionalBoolean(value, "default", location, errors) ?? false;
|
|
46
|
+
const forbiddenRuntimeDependencies = optionalStringArray(value, "forbidden_runtime_dependencies", location, errors);
|
|
47
|
+
if (id && root && context) {
|
|
48
|
+
areas.push({
|
|
49
|
+
line: areaLines[index] ?? 1,
|
|
50
|
+
id,
|
|
51
|
+
root,
|
|
52
|
+
context,
|
|
53
|
+
kind,
|
|
54
|
+
default: defaultArea,
|
|
55
|
+
forbidden_runtime_dependencies: forbiddenRuntimeDependencies,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const contexts = [];
|
|
60
|
+
for (const [index, value] of rawContexts.entries()) {
|
|
61
|
+
const location = `${file} line ${contextLines[index] ?? 1}`;
|
|
62
|
+
rejectUnknownFields(value, CONTEXT_FIELDS, location, errors);
|
|
63
|
+
const path = requiredString(value, "path", location, errors);
|
|
64
|
+
const role = requiredString(value, "role", location, errors);
|
|
65
|
+
const readWhen = optionalString(value, "read_when", location, errors);
|
|
66
|
+
const readPolicy = optionalString(value, "read_policy", location, errors);
|
|
67
|
+
const triggers = optionalStringArray(value, "triggers", location, errors);
|
|
68
|
+
const defaultChildren = optionalStringArray(value, "default_children", location, errors);
|
|
69
|
+
if (path && role) {
|
|
70
|
+
contexts.push({
|
|
71
|
+
line: contextLines[index] ?? 1,
|
|
72
|
+
path,
|
|
73
|
+
role,
|
|
74
|
+
read_when: readWhen,
|
|
75
|
+
read_policy: readPolicy,
|
|
76
|
+
triggers,
|
|
77
|
+
default_children: defaultChildren,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { manifest: { areas, contexts }, errors };
|
|
82
|
+
}
|
|
83
|
+
function tableArray(value, label, file, errors) {
|
|
84
|
+
if (value === undefined) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
if (!Array.isArray(value) || value.some((entry) => !isRecord(entry))) {
|
|
88
|
+
errors.push(`${file} field ${label} must be an array of TOML tables`);
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
function rejectUnknownFields(value, allowed, location, errors) {
|
|
94
|
+
for (const key of Object.keys(value)) {
|
|
95
|
+
if (!allowed.has(key)) {
|
|
96
|
+
errors.push(`${location} has unknown field ${key}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function requiredString(value, key, location, errors) {
|
|
101
|
+
const candidate = value[key];
|
|
102
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
103
|
+
return candidate;
|
|
104
|
+
}
|
|
105
|
+
errors.push(`${location} must include non-empty string field ${key}`);
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
function optionalString(value, key, location, errors) {
|
|
109
|
+
const candidate = value[key];
|
|
110
|
+
if (candidate === undefined) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
114
|
+
return candidate;
|
|
115
|
+
}
|
|
116
|
+
errors.push(`${location} field ${key} must be a non-empty string`);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
function optionalBoolean(value, key, location, errors) {
|
|
120
|
+
const candidate = value[key];
|
|
121
|
+
if (candidate === undefined || typeof candidate === "boolean") {
|
|
122
|
+
return candidate;
|
|
123
|
+
}
|
|
124
|
+
errors.push(`${location} field ${key} must be a boolean`);
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
function optionalStringArray(value, key, location, errors) {
|
|
128
|
+
const candidate = value[key];
|
|
129
|
+
if (candidate === undefined) {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
if (Array.isArray(candidate) &&
|
|
133
|
+
candidate.every((entry) => typeof entry === "string" && entry.trim())) {
|
|
134
|
+
return candidate;
|
|
135
|
+
}
|
|
136
|
+
errors.push(`${location} field ${key} must be an array of non-empty strings`);
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
function tableLines(content, table) {
|
|
140
|
+
const lines = [];
|
|
141
|
+
for (const [index, line] of content.split(/\r?\n/).entries()) {
|
|
142
|
+
if (line.trim() === `[[${table}]]`) {
|
|
143
|
+
lines.push(index + 1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return lines;
|
|
147
|
+
}
|
|
148
|
+
function isRecord(value) {
|
|
149
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
150
|
+
}
|
|
@@ -12,25 +12,25 @@ export function defaultContextManifestTemplate() {
|
|
|
12
12
|
"# every Markdown file as an [[areas]] product owner.",
|
|
13
13
|
"",
|
|
14
14
|
"[[areas]]",
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
'id = "main"',
|
|
16
|
+
'root = "."',
|
|
17
|
+
'context = "project_context/areas/main.md"',
|
|
18
|
+
'kind = "app"',
|
|
19
19
|
"default = true",
|
|
20
20
|
"",
|
|
21
21
|
"[[context]]",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
'path = "project_context/areas/main/verification.md"',
|
|
23
|
+
'role = "verification"',
|
|
24
|
+
'read_policy = "default"',
|
|
25
|
+
'triggers = ["test", "verify", "verification", "smoke", "ci"]',
|
|
26
26
|
"",
|
|
27
27
|
"# Example optional node:",
|
|
28
28
|
"# [[context]]",
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
""
|
|
29
|
+
'# path = "project_context/areas/main/deployment.md"',
|
|
30
|
+
'# role = "deployment"',
|
|
31
|
+
'# read_policy = "on-demand"',
|
|
32
|
+
'# triggers = ["deploy", "deployment", "runtime", "cloud", "docker"]',
|
|
33
|
+
"",
|
|
34
34
|
].join("\n");
|
|
35
35
|
}
|
|
36
36
|
export async function contextManifestFromExistingAreas(projectRoot) {
|
|
@@ -47,12 +47,15 @@ export async function contextManifestFromExistingAreas(projectRoot) {
|
|
|
47
47
|
"# Review deep or non-area context and move it to explicit [[context]] role entries",
|
|
48
48
|
"# such as subdomain, contract, foundation, verification, deployment, archive,",
|
|
49
49
|
"# implementation-index or decision-rationale when needed.",
|
|
50
|
-
""
|
|
50
|
+
"",
|
|
51
51
|
];
|
|
52
52
|
const areaEntries = [];
|
|
53
53
|
const contextEntries = [];
|
|
54
54
|
for (const areaPath of areas) {
|
|
55
|
-
const relativeToAreas = path
|
|
55
|
+
const relativeToAreas = path
|
|
56
|
+
.relative(areasRoot, areaPath)
|
|
57
|
+
.split(path.sep)
|
|
58
|
+
.join("/");
|
|
56
59
|
const contextPath = `project_context/areas/${relativeToAreas}`;
|
|
57
60
|
const id = contextUnitId(relativeToAreas);
|
|
58
61
|
const role = inferredRoleContext(relativeToAreas);
|
|
@@ -62,25 +65,30 @@ export async function contextManifestFromExistingAreas(projectRoot) {
|
|
|
62
65
|
role,
|
|
63
66
|
triggers: role === "verification"
|
|
64
67
|
? ["test", "verify", "verification", "smoke", "ci"]
|
|
65
|
-
: ["deploy", "deployment", "runtime", "cloud", "docker"]
|
|
68
|
+
: ["deploy", "deployment", "runtime", "cloud", "docker"],
|
|
66
69
|
});
|
|
67
70
|
}
|
|
68
71
|
else {
|
|
69
72
|
areaEntries.push({ contextPath, id });
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
|
-
const defaultId = areaEntries.some((entry) => entry.id === "main")
|
|
75
|
+
const defaultId = areaEntries.some((entry) => entry.id === "main")
|
|
76
|
+
? "main"
|
|
77
|
+
: areaEntries[0]?.id;
|
|
73
78
|
for (const { contextPath, id } of areaEntries) {
|
|
74
|
-
lines.push("[[areas]]", `id = "${id}"`,
|
|
79
|
+
lines.push("[[areas]]", `id = "${id}"`, 'root = "."', `context = "${contextPath}"`, `kind = "${id === "main" ? "app" : "context-unit"}"`, id === defaultId ? "default = true" : "default = false", "");
|
|
75
80
|
}
|
|
76
81
|
for (const context of contextEntries) {
|
|
77
|
-
lines.push("[[context]]", `path = "${context.path}"`, `role = "${context.role}"`, context.role === "verification"
|
|
82
|
+
lines.push("[[context]]", `path = "${context.path}"`, `role = "${context.role}"`, context.role === "verification"
|
|
83
|
+
? 'read_policy = "default"'
|
|
84
|
+
: 'read_policy = "on-demand"', `triggers = [${context.triggers.map((trigger) => `"${trigger}"`).join(", ")}]`, "");
|
|
78
85
|
}
|
|
79
86
|
return lines.join("\n");
|
|
80
87
|
}
|
|
81
88
|
function inferredRoleContext(relativeToAreas) {
|
|
82
89
|
const normalized = relativeToAreas.toLowerCase();
|
|
83
|
-
if (normalized.endsWith("/verification.md") ||
|
|
90
|
+
if (normalized.endsWith("/verification.md") ||
|
|
91
|
+
normalized === "verification.md") {
|
|
84
92
|
return "verification";
|
|
85
93
|
}
|
|
86
94
|
if (normalized.endsWith("/deployment.md") || normalized === "deployment.md") {
|
|
@@ -52,7 +52,7 @@ export function globalContextTemplate() {
|
|
|
52
52
|
"",
|
|
53
53
|
"- [main](areas/main.md)",
|
|
54
54
|
"- [main verification](areas/main/verification.md)",
|
|
55
|
-
""
|
|
55
|
+
"",
|
|
56
56
|
].join("\n");
|
|
57
57
|
}
|
|
58
58
|
export function architectureContextTemplate() {
|
|
@@ -88,7 +88,7 @@ export function architectureContextTemplate() {
|
|
|
88
88
|
"## Open Risks",
|
|
89
89
|
"",
|
|
90
90
|
"- List unresolved architectural risks or unknowns.",
|
|
91
|
-
""
|
|
91
|
+
"",
|
|
92
92
|
].join("\n");
|
|
93
93
|
}
|
|
94
94
|
export function areaContextTemplate(areaName) {
|
|
@@ -130,7 +130,7 @@ export function areaContextTemplate(areaName) {
|
|
|
130
130
|
"## Open Risks",
|
|
131
131
|
"",
|
|
132
132
|
"- List unresolved risks or blockers.",
|
|
133
|
-
""
|
|
133
|
+
"",
|
|
134
134
|
].join("\n");
|
|
135
135
|
}
|
|
136
136
|
export function verificationContextTemplate(areaName) {
|
|
@@ -167,7 +167,7 @@ export function verificationContextTemplate(areaName) {
|
|
|
167
167
|
"## Forbidden Content",
|
|
168
168
|
"",
|
|
169
169
|
"- Do not record one-off logs, full command output, temporary JSON, CI artifacts, test reports, secrets, tokens, cookies, device ids, raw payloads or pass/fail claims.",
|
|
170
|
-
""
|
|
170
|
+
"",
|
|
171
171
|
].join("\n");
|
|
172
172
|
}
|
|
173
173
|
export function deploymentContextTemplate(areaName) {
|
|
@@ -207,6 +207,6 @@ export function deploymentContextTemplate(areaName) {
|
|
|
207
207
|
"## Forbidden Content",
|
|
208
208
|
"",
|
|
209
209
|
"- Do not record one-off logs, full command output, CI artifacts, release ledgers, secrets, tokens, cookies, device ids, raw payloads or claims that deployment already succeeded.",
|
|
210
|
-
""
|
|
210
|
+
"",
|
|
211
211
|
].join("\n");
|
|
212
212
|
}
|
package/dist/lib/design-md.js
CHANGED
|
@@ -127,6 +127,6 @@ function designMdTemplate() {
|
|
|
127
127
|
"- When there is a scan target such as UI source, page files, build output or a local/remote URL, run `npx impeccable detect <target>` before finalizing design changes.",
|
|
128
128
|
"- Treat Impeccable findings as design-review signals: fix issues that affect clarity, consistency, accessibility or trust, and note when there is no suitable scan target.",
|
|
129
129
|
"- After design decisions stabilize, update this file with durable tokens, component rules and do/don't guidance so later UI work stays aligned.",
|
|
130
|
-
""
|
|
130
|
+
"",
|
|
131
131
|
].join("\n");
|
|
132
132
|
}
|
package/dist/lib/doctor.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { readdir } from "node:fs/promises";
|
|
5
|
+
import { DEFAULT_CONTEXT_FILE_SOFT_BUDGET_BYTES, DEFAULT_CONTEXT_TOTAL_SOFT_BUDGET_BYTES, inspectDefaultContextFootprint, } from "./context-default-footprint.js";
|
|
3
6
|
import { readConfig } from "./config.js";
|
|
4
7
|
import { harnessConfigPath, harnessRoot } from "./harness-root.js";
|
|
5
8
|
import { pathExists } from "./fs.js";
|
|
@@ -25,7 +28,12 @@ export async function runDoctor(projectRoot) {
|
|
|
25
28
|
report.errors.push(unsupportedSchema);
|
|
26
29
|
return report;
|
|
27
30
|
}
|
|
28
|
-
for (const required of [
|
|
31
|
+
for (const required of [
|
|
32
|
+
"project_context/context.toml",
|
|
33
|
+
"project_context/global.md",
|
|
34
|
+
"project_context/architecture.md",
|
|
35
|
+
"project_context/areas",
|
|
36
|
+
]) {
|
|
29
37
|
if (!(await pathExists(path.join(projectRoot, required)))) {
|
|
30
38
|
report.errors.push(`missing ${required}`);
|
|
31
39
|
}
|
|
@@ -36,6 +44,51 @@ export async function runDoctor(projectRoot) {
|
|
|
36
44
|
report.warnings.push(`managed path missing: ${managed.path}`);
|
|
37
45
|
}
|
|
38
46
|
}
|
|
47
|
+
try {
|
|
48
|
+
const footprint = await inspectDefaultContextFootprint(projectRoot);
|
|
49
|
+
report.info.push(`default Context read path: ${footprint.files.length} file(s), ${footprint.total_bytes} bytes`);
|
|
50
|
+
if (footprint.total_bytes > DEFAULT_CONTEXT_TOTAL_SOFT_BUDGET_BYTES) {
|
|
51
|
+
report.warnings.push(`default Context read path is ${footprint.total_bytes} bytes, above the ${DEFAULT_CONTEXT_TOTAL_SOFT_BUDGET_BYTES}-byte soft budget; shorten near-universal facts or move specialized role Context to read_policy=\"on-demand\"`);
|
|
52
|
+
}
|
|
53
|
+
for (const file of footprint.files) {
|
|
54
|
+
if (file.bytes <= DEFAULT_CONTEXT_FILE_SOFT_BUDGET_BYTES)
|
|
55
|
+
continue;
|
|
56
|
+
report.warnings.push(`default Context file ${file.path} is ${file.bytes} bytes, above the ${DEFAULT_CONTEXT_FILE_SOFT_BUDGET_BYTES}-byte per-file soft budget`);
|
|
57
|
+
}
|
|
58
|
+
for (const group of footprint.duplicate_groups) {
|
|
59
|
+
report.warnings.push(`default Context contains byte-identical files: ${group.join(", ")}; keep one owning fact source and replace duplicates with a short pointer`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
report.warnings.push(`default Context footprint unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
64
|
+
}
|
|
65
|
+
for (const location of await findUserSuperpowersSkills()) {
|
|
66
|
+
report.warnings.push(`user-level using-superpowers Skill detected at ${location}. Tiny Context workflows do not depend on it and doctor will not modify global configuration. To disable it explicitly for Codex, remove/disable that plugin or add a matching [[skills.config]] entry with enabled = false in ${path.join(os.homedir(), ".codex", "config.toml")}.`);
|
|
67
|
+
}
|
|
39
68
|
report.info.push("doctor complete");
|
|
40
69
|
return report;
|
|
41
70
|
}
|
|
71
|
+
async function findUserSuperpowersSkills() {
|
|
72
|
+
const home = os.homedir();
|
|
73
|
+
const direct = path.join(home, ".codex", "skills", "using-superpowers", "SKILL.md");
|
|
74
|
+
const result = [];
|
|
75
|
+
if (await pathExists(direct))
|
|
76
|
+
result.push(direct);
|
|
77
|
+
const cache = path.join(home, ".codex", "plugins", "cache");
|
|
78
|
+
try {
|
|
79
|
+
for (const owner of await readdir(cache)) {
|
|
80
|
+
const candidateRoot = path.join(cache, owner);
|
|
81
|
+
for (const plugin of await readdir(candidateRoot)) {
|
|
82
|
+
if (plugin !== "superpowers")
|
|
83
|
+
continue;
|
|
84
|
+
for (const version of await readdir(path.join(candidateRoot, plugin))) {
|
|
85
|
+
const candidate = path.join(candidateRoot, plugin, version, "skills", "using-superpowers", "SKILL.md");
|
|
86
|
+
if (await pathExists(candidate))
|
|
87
|
+
result.push(candidate);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { }
|
|
93
|
+
return [...new Set(result)].sort();
|
|
94
|
+
}
|
package/dist/lib/harness-root.js
CHANGED
|
@@ -6,30 +6,45 @@ export async function readHarnessRootConfig(projectRoot) {
|
|
|
6
6
|
const candidates = await readHarnessRootConfigCandidates(projectRoot);
|
|
7
7
|
if (candidates.length > 0) {
|
|
8
8
|
const candidate = candidates[0];
|
|
9
|
-
return {
|
|
9
|
+
return {
|
|
10
|
+
harnessFolderName: candidate.harnessFolderName,
|
|
11
|
+
source: candidate.source,
|
|
12
|
+
};
|
|
10
13
|
}
|
|
11
14
|
return { harnessFolderName: DEFAULT_HARNESS_ROOT, source: "default" };
|
|
12
15
|
}
|
|
13
16
|
export async function readHarnessRootConfigCandidates(projectRoot) {
|
|
14
17
|
const candidates = [];
|
|
15
18
|
const packageJson = await readJsonConfig(path.join(projectRoot, "package.json"));
|
|
16
|
-
const packageConfig = packageJson && typeof packageJson === "object"
|
|
19
|
+
const packageConfig = packageJson && typeof packageJson === "object"
|
|
20
|
+
? packageJson.tyContext
|
|
21
|
+
: undefined;
|
|
17
22
|
const packageValue = folderNameFromObject(packageConfig);
|
|
18
23
|
if (packageValue) {
|
|
19
|
-
candidates.push({
|
|
24
|
+
candidates.push({
|
|
25
|
+
harnessFolderName: normalizeHarnessFolderName(packageValue),
|
|
26
|
+
source: "package.json#tyContext",
|
|
27
|
+
legacy: false,
|
|
28
|
+
});
|
|
20
29
|
}
|
|
21
30
|
const explicitConfig = await readJsonConfig(path.join(projectRoot, HARNESS_JSON_CONFIG_PATH));
|
|
22
31
|
const explicitValue = folderNameFromObject(explicitConfig);
|
|
23
32
|
if (explicitValue) {
|
|
24
|
-
candidates.push({
|
|
33
|
+
candidates.push({
|
|
34
|
+
harnessFolderName: normalizeHarnessFolderName(explicitValue),
|
|
35
|
+
source: HARNESS_JSON_CONFIG_PATH,
|
|
36
|
+
legacy: false,
|
|
37
|
+
});
|
|
25
38
|
}
|
|
26
|
-
const legacyPackageConfig = packageJson && typeof packageJson === "object"
|
|
39
|
+
const legacyPackageConfig = packageJson && typeof packageJson === "object"
|
|
40
|
+
? packageJson.sdlcHarness
|
|
41
|
+
: undefined;
|
|
27
42
|
const legacyPackageValue = folderNameFromObject(legacyPackageConfig);
|
|
28
43
|
if (legacyPackageValue) {
|
|
29
44
|
candidates.push({
|
|
30
45
|
harnessFolderName: normalizeHarnessFolderName(legacyPackageValue),
|
|
31
46
|
source: "package.json#sdlcHarness",
|
|
32
|
-
legacy: true
|
|
47
|
+
legacy: true,
|
|
33
48
|
});
|
|
34
49
|
}
|
|
35
50
|
const legacyExplicitConfig = await readJsonConfig(path.join(projectRoot, LEGACY_HARNESS_JSON_CONFIG_PATH));
|
|
@@ -38,7 +53,7 @@ export async function readHarnessRootConfigCandidates(projectRoot) {
|
|
|
38
53
|
candidates.push({
|
|
39
54
|
harnessFolderName: normalizeHarnessFolderName(legacyExplicitValue),
|
|
40
55
|
source: LEGACY_HARNESS_JSON_CONFIG_PATH,
|
|
41
|
-
legacy: true
|
|
56
|
+
legacy: true,
|
|
42
57
|
});
|
|
43
58
|
}
|
|
44
59
|
return candidates;
|
|
@@ -58,7 +73,9 @@ function folderNameFromObject(value) {
|
|
|
58
73
|
}
|
|
59
74
|
const record = value;
|
|
60
75
|
const folderName = record.harnessFolderName ?? record.harnessFloderName;
|
|
61
|
-
return typeof folderName === "string" && folderName.trim()
|
|
76
|
+
return typeof folderName === "string" && folderName.trim()
|
|
77
|
+
? folderName
|
|
78
|
+
: undefined;
|
|
62
79
|
}
|
|
63
80
|
async function readJsonConfig(filePath) {
|
|
64
81
|
if (!(await pathExists(filePath))) {
|
package/dist/lib/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { CONTEXT_MANIFEST_PATH, defaultContextManifestTemplate } from "./context-manifest.js";
|
|
3
|
-
import { architectureContextTemplate, areaContextTemplate, globalContextTemplate, verificationContextTemplate } from "./context-templates.js";
|
|
2
|
+
import { CONTEXT_MANIFEST_PATH, defaultContextManifestTemplate, } from "./context-manifest.js";
|
|
3
|
+
import { architectureContextTemplate, areaContextTemplate, globalContextTemplate, verificationContextTemplate, } from "./context-templates.js";
|
|
4
4
|
import { writeConfigIfMissing } from "./config.js";
|
|
5
5
|
import { createDesignMdIfMissing, DESIGN_MD_PATH } from "./design-md.js";
|
|
6
6
|
import { harnessConfigPath } from "./harness-root.js";
|
|
@@ -50,7 +50,10 @@ async function createProjectContext(projectRoot, report) {
|
|
|
50
50
|
["project_context/global.md", globalContextTemplate()],
|
|
51
51
|
["project_context/architecture.md", architectureContextTemplate()],
|
|
52
52
|
["project_context/areas/main.md", areaContextTemplate("main")],
|
|
53
|
-
[
|
|
53
|
+
[
|
|
54
|
+
"project_context/areas/main/verification.md",
|
|
55
|
+
verificationContextTemplate("main"),
|
|
56
|
+
],
|
|
54
57
|
];
|
|
55
58
|
for (const [relative, content] of files) {
|
|
56
59
|
const target = path.join(projectRoot, relative);
|
|
@@ -13,8 +13,14 @@ export async function detectLegacyManagedDirectory(projectRoot, root, migration)
|
|
|
13
13
|
if (path.basename(file) === ".gitkeep") {
|
|
14
14
|
continue;
|
|
15
15
|
}
|
|
16
|
-
const relativeToLegacyRoot = path
|
|
17
|
-
|
|
16
|
+
const relativeToLegacyRoot = path
|
|
17
|
+
.relative(legacyRoot, file)
|
|
18
|
+
.split(path.sep)
|
|
19
|
+
.join("/");
|
|
20
|
+
const relativeToProject = path
|
|
21
|
+
.relative(projectRoot, file)
|
|
22
|
+
.split(path.sep)
|
|
23
|
+
.join("/");
|
|
18
24
|
const classification = await classifyLegacyManagedFile(relativeToLegacyRoot);
|
|
19
25
|
if (classification.kind === "override") {
|
|
20
26
|
items.push(item(migration, "manual_required", relativeToProject, "Legacy skill overrides are no longer supported; move rules into a standalone project-local Skill."));
|
|
@@ -47,21 +53,31 @@ async function classifyLegacyManagedFile(relative) {
|
|
|
47
53
|
if (!(await pathExists(assetPath))) {
|
|
48
54
|
return { kind: "unknown" };
|
|
49
55
|
}
|
|
50
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
kind: "generated",
|
|
58
|
+
targetRelative: mapped.targetRelative,
|
|
59
|
+
assetPath,
|
|
60
|
+
};
|
|
51
61
|
}
|
|
52
62
|
function legacyGeneratedMapping(relative) {
|
|
53
63
|
if (relative === `make/${LEGACY_MAKEFILE}`) {
|
|
54
|
-
return {
|
|
64
|
+
return {
|
|
65
|
+
targetRelative: `make/${CURRENT_MAKEFILE}`,
|
|
66
|
+
assetSegments: ["make", CURRENT_MAKEFILE],
|
|
67
|
+
};
|
|
55
68
|
}
|
|
56
69
|
for (const [prefix, assetPrefix] of [
|
|
57
70
|
["agents/", "agents"],
|
|
58
71
|
["context_templates/", "context_templates"],
|
|
59
72
|
["skills/", "skills"],
|
|
60
|
-
["minimal_tools/", "tools"]
|
|
73
|
+
["minimal_tools/", "tools"],
|
|
61
74
|
]) {
|
|
62
75
|
if (relative.startsWith(prefix)) {
|
|
63
76
|
const rest = relative.slice(prefix.length);
|
|
64
|
-
return {
|
|
77
|
+
return {
|
|
78
|
+
targetRelative: `${prefix}${rest}`,
|
|
79
|
+
assetSegments: [assetPrefix, ...rest.split("/")],
|
|
80
|
+
};
|
|
65
81
|
}
|
|
66
82
|
}
|
|
67
83
|
return undefined;
|
|
@@ -74,6 +90,6 @@ function item(migration, status, pathLabel, message) {
|
|
|
74
90
|
scope: migration.scope,
|
|
75
91
|
status,
|
|
76
92
|
path: pathLabel,
|
|
77
|
-
message
|
|
93
|
+
message,
|
|
78
94
|
};
|
|
79
95
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { LEGACY_HARNESS_JSON_CONFIG_PATH, readHarnessRootConfigCandidates } from "./harness-root.js";
|
|
2
|
+
import { LEGACY_HARNESS_JSON_CONFIG_PATH, readHarnessRootConfigCandidates, } from "./harness-root.js";
|
|
3
3
|
import { pathExists, readText, writeTextIfChanged } from "./fs.js";
|
|
4
4
|
import { detectLegacyManagedDirectory } from "./legacy-managed-scan.js";
|
|
5
5
|
import { HARNESS_JSON_CONFIG_PATH } from "./paths.js";
|
|
@@ -16,7 +16,7 @@ export const legacySdlcHarnessMigration = {
|
|
|
16
16
|
manualMessage: "Resolve legacy sdlc-harness conflicts or move old override rules into standalone project-local Skills.",
|
|
17
17
|
detect: detectLegacySdlcHarness,
|
|
18
18
|
apply: migrateLegacySdlcHarness,
|
|
19
|
-
verify: async () => undefined
|
|
19
|
+
verify: async () => undefined,
|
|
20
20
|
};
|
|
21
21
|
async function detectLegacySdlcHarness(projectRoot, root, migration) {
|
|
22
22
|
const items = [];
|
|
@@ -25,7 +25,8 @@ async function detectLegacySdlcHarness(projectRoot, root, migration) {
|
|
|
25
25
|
const legacyCandidates = candidates.filter((candidate) => candidate.legacy);
|
|
26
26
|
const currentRoot = currentCandidates[0]?.harnessFolderName;
|
|
27
27
|
const distinctLegacyRoots = Array.from(new Set(legacyCandidates.map((candidate) => candidate.harnessFolderName)));
|
|
28
|
-
if (currentRoot &&
|
|
28
|
+
if (currentRoot &&
|
|
29
|
+
distinctLegacyRoots.some((legacyRoot) => legacyRoot !== currentRoot)) {
|
|
29
30
|
items.push(item(migration, "blocked", rootConflictPath(currentCandidates, legacyCandidates), "Current ty-context and legacy sdlc-harness root configuration disagree; choose the harness root manually before upgrade."));
|
|
30
31
|
}
|
|
31
32
|
else if (!currentRoot && distinctLegacyRoots.length > 1) {
|
|
@@ -46,7 +47,8 @@ async function migrateLegacySdlcHarness(projectRoot, root, report) {
|
|
|
46
47
|
await migrateConfigYamlPaths(projectRoot, root, report);
|
|
47
48
|
}
|
|
48
49
|
async function needsLegacySafeMigration(projectRoot, root, hasLegacyRootConfig) {
|
|
49
|
-
if (hasLegacyRootConfig &&
|
|
50
|
+
if (hasLegacyRootConfig &&
|
|
51
|
+
(await legacyPackageConfigNeedsCopy(projectRoot))) {
|
|
50
52
|
return true;
|
|
51
53
|
}
|
|
52
54
|
if (await legacyJsonConfigNeedsCopy(projectRoot)) {
|
|
@@ -66,7 +68,8 @@ async function legacyPackageConfigNeedsCopy(projectRoot) {
|
|
|
66
68
|
return false;
|
|
67
69
|
}
|
|
68
70
|
const packageJson = parseJsonRecord(await readText(packagePath), "package.json");
|
|
69
|
-
return isJsonRecord(packageJson.sdlcHarness) &&
|
|
71
|
+
return (isJsonRecord(packageJson.sdlcHarness) &&
|
|
72
|
+
!isJsonRecord(packageJson.tyContext));
|
|
70
73
|
}
|
|
71
74
|
async function legacyJsonConfigNeedsCopy(projectRoot) {
|
|
72
75
|
const legacyPath = path.join(projectRoot, LEGACY_HARNESS_JSON_CONFIG_PATH);
|
|
@@ -81,7 +84,11 @@ async function configYamlHasLegacyManagedPaths(projectRoot, root) {
|
|
|
81
84
|
return hasLegacyManagedPath(await readText(configPath));
|
|
82
85
|
}
|
|
83
86
|
async function hasLegacyManagedMarkers(projectRoot) {
|
|
84
|
-
for (const relative of [
|
|
87
|
+
for (const relative of [
|
|
88
|
+
"AGENTS.md",
|
|
89
|
+
"Makefile",
|
|
90
|
+
".github/workflows/harness.yml",
|
|
91
|
+
]) {
|
|
85
92
|
const target = path.join(projectRoot, ...relative.split("/"));
|
|
86
93
|
if ((await pathExists(target)) && hasLegacyMarker(await readText(target))) {
|
|
87
94
|
return true;
|
|
@@ -96,7 +103,8 @@ async function migratePackageJsonConfig(projectRoot, report) {
|
|
|
96
103
|
return;
|
|
97
104
|
}
|
|
98
105
|
const packageJson = parseJsonRecord(await readText(packagePath), "package.json");
|
|
99
|
-
if (!isJsonRecord(packageJson.sdlcHarness) ||
|
|
106
|
+
if (!isJsonRecord(packageJson.sdlcHarness) ||
|
|
107
|
+
isJsonRecord(packageJson.tyContext)) {
|
|
100
108
|
report.skipped.push("package.json#sdlcHarness");
|
|
101
109
|
return;
|
|
102
110
|
}
|
|
@@ -147,10 +155,12 @@ async function migrateConfigYamlPaths(projectRoot, root, report) {
|
|
|
147
155
|
}
|
|
148
156
|
}
|
|
149
157
|
function rewriteLegacyManagedPaths(content) {
|
|
150
|
-
return content
|
|
158
|
+
return content
|
|
159
|
+
.replaceAll(LEGACY_MANAGED_ROOT, CURRENT_MANAGED_ROOT)
|
|
160
|
+
.replaceAll(LEGACY_MAKEFILE, CURRENT_MAKEFILE);
|
|
151
161
|
}
|
|
152
162
|
function hasLegacyManagedPath(content) {
|
|
153
|
-
return content.includes(LEGACY_MANAGED_ROOT) || content.includes(LEGACY_MAKEFILE);
|
|
163
|
+
return (content.includes(LEGACY_MANAGED_ROOT) || content.includes(LEGACY_MAKEFILE));
|
|
154
164
|
}
|
|
155
165
|
function hasLegacyMarker(content) {
|
|
156
166
|
return [
|
|
@@ -158,7 +168,7 @@ function hasLegacyMarker(content) {
|
|
|
158
168
|
"<!-- sdlc-harness:begin -->",
|
|
159
169
|
"# pjsdlc:sdlc-harness:make:begin",
|
|
160
170
|
"# sdlc-harness:make:begin",
|
|
161
|
-
"# pjsdlc:sdlc-harness:github-workflow:begin"
|
|
171
|
+
"# pjsdlc:sdlc-harness:github-workflow:begin",
|
|
162
172
|
].some((marker) => content.includes(marker));
|
|
163
173
|
}
|
|
164
174
|
function rootConflictPath(currentCandidates, legacyCandidates) {
|
|
@@ -174,7 +184,7 @@ function item(migrationId, status, pathLabel, message) {
|
|
|
174
184
|
scope: legacySdlcHarnessMigration.scope,
|
|
175
185
|
status,
|
|
176
186
|
path: pathLabel,
|
|
177
|
-
message
|
|
187
|
+
message,
|
|
178
188
|
};
|
|
179
189
|
}
|
|
180
190
|
function parseJsonRecord(content, pathLabel) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CompiledDeliveryContractV2, DeliveryAssertionV2, DeliveryCheckV2, DeliveryContractV2 } from "./long-task-delivery-types.js";
|
|
2
|
+
export type AcceptanceReference = {
|
|
3
|
+
scope: "global";
|
|
4
|
+
check_key: string;
|
|
5
|
+
assertion_key: string;
|
|
6
|
+
} | {
|
|
7
|
+
scope: "outcome";
|
|
8
|
+
outcome_key: string;
|
|
9
|
+
check_key: string;
|
|
10
|
+
assertion_key: string;
|
|
11
|
+
};
|
|
12
|
+
export interface ResolvedAcceptanceAssertion {
|
|
13
|
+
ref: string;
|
|
14
|
+
scope: AcceptanceReference["scope"];
|
|
15
|
+
outcome_key: string | null;
|
|
16
|
+
check_key: string;
|
|
17
|
+
assertion_key: string;
|
|
18
|
+
check: DeliveryCheckV2;
|
|
19
|
+
assertion: DeliveryAssertionV2;
|
|
20
|
+
}
|
|
21
|
+
export declare function parseAcceptanceReference(ref: string): AcceptanceReference;
|
|
22
|
+
export declare function resolveAcceptanceAssertion(contract: DeliveryContractV2 | CompiledDeliveryContractV2, ref: string): ResolvedAcceptanceAssertion | null;
|