project-tiny-context-harness 0.2.85 → 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 -163
- 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 +4 -2
- 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 -245
- package/assets/skills/composite-long-task-workflow/assets/execution-binding.template.md +0 -62
- 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 -682
- 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 -91
- package/dist/lib/superpowers-task-completion-output.js +0 -374
- 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 -393
- 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 -35
- package/dist/lib/superpowers-task-gates.d.ts +0 -12
- package/dist/lib/superpowers-task-gates.js +0 -267
- 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 -460
- 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 -293
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { pathExists } from "./fs.js";
|
|
3
|
-
import { validateAcceptanceArtifactDiagnostics } from "./plan-acceptance-artifacts.js";
|
|
4
|
-
import { assertExternalReviewerFields } from "./plan-acceptance-evidence.js";
|
|
5
|
-
import { AC_STATUSES, MATRIX_STATUSES, NON_COMPLETE_AC, NON_COMPLETE_MATRIX, assertStructuredNa, assertSurfaceConformance, contextDeltaRequired, findJsonFile, findRows, hasExplicitNoTestScope, isOutOfScope, isSurfaceConformanceRow, overallStatus, readJson, statusOf } from "./plan-acceptance-json.js";
|
|
6
|
-
import { assertReferencedPathsExist, hasRealPageEvidence, isBlankish, isUiFacing, primitiveText, repoRelative, resolveInputDir, valuesAsArray, weakProofHit } from "./plan-validator-common.js";
|
|
7
|
-
import { validateSuperpowersState } from "./superpowers-task-validator.js";
|
|
8
|
-
export async function validatePlanAcceptance(projectRoot, args = []) {
|
|
9
|
-
const info = [];
|
|
10
|
-
const warnings = [];
|
|
11
|
-
const hygiene = [];
|
|
12
|
-
const errors = [];
|
|
13
|
-
const targetDir = await resolveInputDir(projectRoot, args[0], "tmp/ty-context/plan-acceptance");
|
|
14
|
-
if (!(await pathExists(targetDir))) {
|
|
15
|
-
return { info, warnings, hygiene, errors: [`plan acceptance directory is missing: ${repoRelative(projectRoot, targetDir)}`] };
|
|
16
|
-
}
|
|
17
|
-
if (await pathExists(path.join(targetDir, "task-state.json"))) {
|
|
18
|
-
const stateReport = await validateSuperpowersState(projectRoot, [targetDir]);
|
|
19
|
-
return {
|
|
20
|
-
info: [
|
|
21
|
-
`checked state-backed plan acceptance ${repoRelative(projectRoot, targetDir)}`,
|
|
22
|
-
...stateReport.info,
|
|
23
|
-
...(stateReport.errors.length === 0 ? ["Plan acceptance state-backed artifact consistency passed"] : [])
|
|
24
|
-
],
|
|
25
|
-
warnings: stateReport.warnings,
|
|
26
|
-
hygiene: stateReport.hygiene,
|
|
27
|
-
errors: stateReport.errors
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
const matrixFile = await findJsonFile(targetDir, "plan-conformance-matrix");
|
|
31
|
-
const verdictFile = await findJsonFile(targetDir, "final-acceptance-verdict");
|
|
32
|
-
if (!matrixFile) {
|
|
33
|
-
errors.push(`plan acceptance directory is missing *-plan-conformance-matrix.json`);
|
|
34
|
-
}
|
|
35
|
-
if (!verdictFile) {
|
|
36
|
-
errors.push(`plan acceptance directory is missing *-final-acceptance-verdict.json`);
|
|
37
|
-
}
|
|
38
|
-
if (!matrixFile || !verdictFile) {
|
|
39
|
-
return { info, warnings, hygiene, errors };
|
|
40
|
-
}
|
|
41
|
-
const matrix = await readJson(matrixFile, errors);
|
|
42
|
-
const verdict = await readJson(verdictFile, errors);
|
|
43
|
-
if (matrix === undefined || verdict === undefined) {
|
|
44
|
-
return { info, warnings, hygiene, errors };
|
|
45
|
-
}
|
|
46
|
-
const matrixRows = findRows(matrix, ["plan_items", "items", "matrix", "entries", "plan_conformance"]);
|
|
47
|
-
const verdictRows = findRows(verdict, ["acceptance_items", "ac_verdicts", "verdicts", "items", "entries", "acs"]);
|
|
48
|
-
await validateMatrixRows(projectRoot, matrixRows, overallStatus(matrix), errors);
|
|
49
|
-
await validateVerdictRows(projectRoot, verdictRows, overallStatus(verdict), errors);
|
|
50
|
-
validateCrossReferences(matrixRows, verdictRows, errors);
|
|
51
|
-
validateContextFactReferences(matrix, verdict, matrixRows, verdictRows, errors);
|
|
52
|
-
await validateAcceptanceArtifactDiagnostics(projectRoot, targetDir, matrixRows, verdictRows, overallStatus(verdict), errors, warnings, hygiene);
|
|
53
|
-
info.push(`checked plan acceptance ${repoRelative(projectRoot, targetDir)} matrix_rows=${matrixRows.length} verdict_rows=${verdictRows.length}`);
|
|
54
|
-
if (errors.length === 0) {
|
|
55
|
-
info.push("Plan acceptance artifact consistency passed");
|
|
56
|
-
}
|
|
57
|
-
return { info, warnings, hygiene, errors };
|
|
58
|
-
}
|
|
59
|
-
async function validateMatrixRows(projectRoot, rows, overall, errors) {
|
|
60
|
-
if (rows.length === 0) {
|
|
61
|
-
errors.push("plan-conformance matrix has no trace rows");
|
|
62
|
-
}
|
|
63
|
-
for (const [index, row] of rows.entries()) {
|
|
64
|
-
const label = `plan-conformance matrix row ${index + 1}`;
|
|
65
|
-
const status = statusOf(row);
|
|
66
|
-
if (!MATRIX_STATUSES.has(status)) {
|
|
67
|
-
errors.push(`${label} has unsupported status: ${status || "<empty>"}`);
|
|
68
|
-
}
|
|
69
|
-
if (status === "out_of_scope_NA") {
|
|
70
|
-
assertStructuredNa(row, label, errors);
|
|
71
|
-
}
|
|
72
|
-
if (overall === "complete" && NON_COMPLETE_MATRIX.has(status)) {
|
|
73
|
-
errors.push(`${label} is ${status} but overall_status is complete`);
|
|
74
|
-
}
|
|
75
|
-
if (status === "complete" && !isBlankish(row.missing_paths)) {
|
|
76
|
-
errors.push(`${label} is complete but missing_paths is not empty`);
|
|
77
|
-
}
|
|
78
|
-
if (status === "complete") {
|
|
79
|
-
if (isBlankish(row.plan_requirement)) {
|
|
80
|
-
errors.push(`${label} is complete but plan_requirement is empty`);
|
|
81
|
-
}
|
|
82
|
-
if (isBlankish(row.expected_surfaces)) {
|
|
83
|
-
errors.push(`${label} is complete but expected_surfaces is empty`);
|
|
84
|
-
}
|
|
85
|
-
if (isBlankish(row.implemented_paths)) {
|
|
86
|
-
errors.push(`${label} is complete but implemented_paths is empty`);
|
|
87
|
-
}
|
|
88
|
-
if (isBlankish(row.tests) && !hasExplicitNoTestScope(row)) {
|
|
89
|
-
errors.push(`${label} is complete but tests is empty and no explicit no-test scope is recorded`);
|
|
90
|
-
}
|
|
91
|
-
if (isBlankish(row.runtime_evidence) && isBlankish(row.artifact_evidence) && isBlankish(row.real_page_evidence)) {
|
|
92
|
-
errors.push(`${label} is complete but has no runtime, artifact or real-page evidence`);
|
|
93
|
-
}
|
|
94
|
-
if (isBlankish(row.scope_assessment)) {
|
|
95
|
-
errors.push(`${label} is complete but scope_assessment is empty`);
|
|
96
|
-
}
|
|
97
|
-
if (isBlankish(row.drift)) {
|
|
98
|
-
errors.push(`${label} is complete but drift is empty`);
|
|
99
|
-
}
|
|
100
|
-
assertExternalReviewerFields(label, row, primitiveText([row.runtime_evidence, row.artifact_evidence, row.real_page_evidence, row.fresh_evidence]), errors);
|
|
101
|
-
const weak = weakProofHit(primitiveText(row));
|
|
102
|
-
if (weak) {
|
|
103
|
-
errors.push(`${label} is complete but contains weak-proof language matching /${weak}/`);
|
|
104
|
-
}
|
|
105
|
-
if (isUiFacing(primitiveText([row.expected_surfaces, row.plan_requirement, row.conformance_type]))) {
|
|
106
|
-
const realPageEvidence = primitiveText([
|
|
107
|
-
row.real_page_evidence,
|
|
108
|
-
row.user_path_evidence,
|
|
109
|
-
row.fresh_evidence,
|
|
110
|
-
row.runtime_evidence,
|
|
111
|
-
row.artifact_evidence
|
|
112
|
-
]);
|
|
113
|
-
if (!hasRealPageEvidence(realPageEvidence)) {
|
|
114
|
-
errors.push(`${label} is UI/surface-facing but lacks real_page_evidence`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
if (isSurfaceConformanceRow(row)) {
|
|
118
|
-
assertSurfaceConformance(row, label, errors);
|
|
119
|
-
}
|
|
120
|
-
await assertReferencedPathsExist(projectRoot, label, primitiveText([
|
|
121
|
-
row.implemented_paths,
|
|
122
|
-
row.tests,
|
|
123
|
-
row.runtime_evidence,
|
|
124
|
-
row.artifact_evidence,
|
|
125
|
-
row.real_page_evidence,
|
|
126
|
-
row.negative_surface_checks,
|
|
127
|
-
row.context_fact_refs
|
|
128
|
-
]), errors);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async function validateVerdictRows(projectRoot, rows, overall, errors) {
|
|
133
|
-
if (rows.length === 0) {
|
|
134
|
-
errors.push("final acceptance verdict has no AC rows");
|
|
135
|
-
}
|
|
136
|
-
for (const [index, row] of rows.entries()) {
|
|
137
|
-
const label = `final acceptance verdict row ${index + 1}`;
|
|
138
|
-
const status = statusOf(row);
|
|
139
|
-
if (!AC_STATUSES.has(status)) {
|
|
140
|
-
errors.push(`${label} has unsupported status: ${status || "<empty>"}`);
|
|
141
|
-
}
|
|
142
|
-
if (status === "out_of_scope_NA") {
|
|
143
|
-
assertStructuredNa(row, label, errors);
|
|
144
|
-
}
|
|
145
|
-
if (overall === "complete" && NON_COMPLETE_AC.has(status)) {
|
|
146
|
-
errors.push(`${label} is ${status} but overall_status is complete`);
|
|
147
|
-
}
|
|
148
|
-
if (status === "complete" && isBlankish(row.fresh_evidence)) {
|
|
149
|
-
errors.push(`${label} is complete but fresh_evidence is empty`);
|
|
150
|
-
}
|
|
151
|
-
if (status === "complete" && isBlankish(row.required_evidence)) {
|
|
152
|
-
errors.push(`${label} is complete but required_evidence is empty`);
|
|
153
|
-
}
|
|
154
|
-
if (status === "complete" && isBlankish(row.decision)) {
|
|
155
|
-
errors.push(`${label} is complete but decision is empty`);
|
|
156
|
-
}
|
|
157
|
-
if (status === "complete" && !isBlankish(row.missing_evidence)) {
|
|
158
|
-
errors.push(`${label} is complete but missing_evidence is not empty`);
|
|
159
|
-
}
|
|
160
|
-
if (status === "complete" && !isBlankish(row.contradictions)) {
|
|
161
|
-
errors.push(`${label} is complete but contradictions is not empty`);
|
|
162
|
-
}
|
|
163
|
-
if (status === "complete") {
|
|
164
|
-
const text = primitiveText(row);
|
|
165
|
-
assertExternalReviewerFields(label, row, primitiveText(row.fresh_evidence), errors);
|
|
166
|
-
const weak = weakProofHit(text);
|
|
167
|
-
if (weak) {
|
|
168
|
-
errors.push(`${label} is complete but contains weak-proof language matching /${weak}/`);
|
|
169
|
-
}
|
|
170
|
-
if (isUiFacing(text) && !isOutOfScope(row) && !hasRealPageEvidence(primitiveText(row.fresh_evidence))) {
|
|
171
|
-
errors.push(`${label} is UI-facing but lacks fresh real-page evidence or explicit N/A`);
|
|
172
|
-
}
|
|
173
|
-
await assertReferencedPathsExist(projectRoot, label, primitiveText([row.fresh_evidence, row.context_fact_refs]), errors);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function validateCrossReferences(matrixRows, verdictRows, errors) {
|
|
178
|
-
const planIds = new Set(matrixRows.map((row) => String(row.plan_item_id ?? row.id ?? "")).filter(Boolean));
|
|
179
|
-
const acIds = new Set(verdictRows.map((row) => String(row.ac_id ?? row.id ?? row.acceptance_item ?? "")).filter(Boolean));
|
|
180
|
-
let checked = 0;
|
|
181
|
-
for (const [index, row] of matrixRows.entries()) {
|
|
182
|
-
for (const acId of valuesAsArray(row.acceptance_ids ?? row.ac_ids)) {
|
|
183
|
-
checked += 1;
|
|
184
|
-
if (!acIds.has(acId)) {
|
|
185
|
-
errors.push(`plan-conformance matrix row ${index + 1} references unknown AC id: ${acId}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
for (const [index, row] of verdictRows.entries()) {
|
|
190
|
-
for (const planId of valuesAsArray(row.related_plan_item_ids ?? row.plan_item_ids)) {
|
|
191
|
-
checked += 1;
|
|
192
|
-
if (!planIds.has(planId)) {
|
|
193
|
-
errors.push(`final acceptance verdict row ${index + 1} references unknown plan item id: ${planId}`);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (matrixRows.length > 0 && verdictRows.length > 0 && checked === 0) {
|
|
198
|
-
errors.push("plan acceptance artifacts must include acceptance_ids or related_plan_item_ids cross references");
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function validateContextFactReferences(matrix, verdict, matrixRows, verdictRows, errors) {
|
|
202
|
-
if (!contextDeltaRequired(matrix) && !contextDeltaRequired(verdict)) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
const rows = [...matrixRows, ...verdictRows];
|
|
206
|
-
if (!rows.some((row) => !isBlankish(row.context_fact_refs))) {
|
|
207
|
-
errors.push("Context Delta is required but matrix/verdict rows do not cite context_fact_refs");
|
|
208
|
-
}
|
|
209
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { cell, hasRealPageEvidence, isBlankish, isRuntimeFacing, isUiFacing, parseRequiredTable, readRequiredFile, repoRelative, resolveInputFile, weakProofHit, assertReferencedPathsExist } from "./plan-validator-common.js";
|
|
2
|
-
const SOURCE_HEADERS = [
|
|
3
|
-
"Source item",
|
|
4
|
-
"Durable constraint",
|
|
5
|
-
"Type",
|
|
6
|
-
"Existing Context Hit",
|
|
7
|
-
"Context action",
|
|
8
|
-
"Owning Context",
|
|
9
|
-
"Coverage status"
|
|
10
|
-
];
|
|
11
|
-
const BINDING_HEADERS = [
|
|
12
|
-
"Context fact",
|
|
13
|
-
"Implementation obligation",
|
|
14
|
-
"Expected surfaces",
|
|
15
|
-
"Implemented paths",
|
|
16
|
-
"Forbidden shortcuts",
|
|
17
|
-
"Verification path",
|
|
18
|
-
"Binding status"
|
|
19
|
-
];
|
|
20
|
-
const SOURCE_STATUSES = new Set([
|
|
21
|
-
"covered",
|
|
22
|
-
"new_context_required",
|
|
23
|
-
"context_updated",
|
|
24
|
-
"task_local_only",
|
|
25
|
-
"out_of_scope_explicit",
|
|
26
|
-
"needs_user_decision",
|
|
27
|
-
"under_scoped"
|
|
28
|
-
]);
|
|
29
|
-
const BINDING_STATUSES = new Set([
|
|
30
|
-
"bound",
|
|
31
|
-
"partial",
|
|
32
|
-
"missing",
|
|
33
|
-
"blocked",
|
|
34
|
-
"out_of_scope_explicit",
|
|
35
|
-
"needs_user_decision",
|
|
36
|
-
"contradicted_by_current_state"
|
|
37
|
-
]);
|
|
38
|
-
const UNRESOLVED_SOURCE = new Set(["new_context_required", "needs_user_decision", "under_scoped"]);
|
|
39
|
-
const NON_BOUND = new Set(["partial", "missing", "blocked", "needs_user_decision", "contradicted_by_current_state"]);
|
|
40
|
-
export async function validatePlanContract(projectRoot, args = []) {
|
|
41
|
-
const info = [];
|
|
42
|
-
const errors = [];
|
|
43
|
-
const planPath = await resolveInputFile(projectRoot, args[0], "plan.md");
|
|
44
|
-
const content = await readRequiredFile(projectRoot, planPath, "plan contract", errors);
|
|
45
|
-
if (content === undefined) {
|
|
46
|
-
return { info, errors };
|
|
47
|
-
}
|
|
48
|
-
const sourceTable = parseRequiredTable(content, "Source-to-Context Coverage", SOURCE_HEADERS, "Source-to-Context Coverage", errors);
|
|
49
|
-
if (sourceTable?.headers.includes("implementation constraint")) {
|
|
50
|
-
errors.push("Source-to-Context Coverage must not include Implementation constraint; use Context-to-Implementation Binding instead");
|
|
51
|
-
}
|
|
52
|
-
const bindingTable = parseRequiredTable(content, "Context-to-Implementation Binding", BINDING_HEADERS, "Context-to-Implementation Binding", errors);
|
|
53
|
-
if (sourceTable) {
|
|
54
|
-
for (const row of sourceTable.rows) {
|
|
55
|
-
const status = cell(row, "Coverage status");
|
|
56
|
-
const label = `Source-to-Context Coverage row ${row.index}`;
|
|
57
|
-
if (!SOURCE_STATUSES.has(status)) {
|
|
58
|
-
errors.push(`${label} has unsupported Coverage status: ${status || "<empty>"}`);
|
|
59
|
-
}
|
|
60
|
-
if (UNRESOLVED_SOURCE.has(status)) {
|
|
61
|
-
errors.push(`${label} is unresolved (${status}) and cannot pass final plan-contract validation`);
|
|
62
|
-
}
|
|
63
|
-
if (status === "covered" && isBlankish(cell(row, "Existing Context Hit"))) {
|
|
64
|
-
errors.push(`${label} is covered but has no Existing Context Hit`);
|
|
65
|
-
}
|
|
66
|
-
if (status === "context_updated" && isBlankish(cell(row, "Owning Context"))) {
|
|
67
|
-
errors.push(`${label} is context_updated but has no Owning Context`);
|
|
68
|
-
}
|
|
69
|
-
await assertReferencedPathsExist(projectRoot, label, `${cell(row, "Existing Context Hit")} ${cell(row, "Owning Context")}`, errors);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (bindingTable) {
|
|
73
|
-
for (const row of bindingTable.rows) {
|
|
74
|
-
const status = cell(row, "Binding status");
|
|
75
|
-
const label = `Context-to-Implementation Binding row ${row.index}`;
|
|
76
|
-
const expectedSurfaces = cell(row, "Expected surfaces");
|
|
77
|
-
const implementedPaths = cell(row, "Implemented paths");
|
|
78
|
-
const verificationPath = cell(row, "Verification path");
|
|
79
|
-
const evidenceText = `${implementedPaths} ${verificationPath}`;
|
|
80
|
-
if (!BINDING_STATUSES.has(status)) {
|
|
81
|
-
errors.push(`${label} has unsupported Binding status: ${status || "<empty>"}`);
|
|
82
|
-
}
|
|
83
|
-
if (NON_BOUND.has(status)) {
|
|
84
|
-
errors.push(`${label} is ${status} and cannot pass final plan-contract validation`);
|
|
85
|
-
}
|
|
86
|
-
if (status === "bound") {
|
|
87
|
-
if (isBlankish(expectedSurfaces)) {
|
|
88
|
-
errors.push(`${label} is bound but has no Expected surfaces`);
|
|
89
|
-
}
|
|
90
|
-
if (isBlankish(implementedPaths)) {
|
|
91
|
-
errors.push(`${label} is bound but has no Implemented paths`);
|
|
92
|
-
}
|
|
93
|
-
if (isBlankish(verificationPath)) {
|
|
94
|
-
errors.push(`${label} is bound but has no Verification path`);
|
|
95
|
-
}
|
|
96
|
-
const weak = weakProofHit(`${cell(row, "Context fact")} ${cell(row, "Implementation obligation")} ${expectedSurfaces} ${evidenceText}`);
|
|
97
|
-
if (weak) {
|
|
98
|
-
errors.push(`${label} is bound but contains weak-proof language matching /${weak}/`);
|
|
99
|
-
}
|
|
100
|
-
if (isUiFacing(`${expectedSurfaces} ${cell(row, "Implementation obligation")}`) && !hasRealPageEvidence(evidenceText)) {
|
|
101
|
-
errors.push(`${label} is UI/surface-facing but lacks real page, route, browser or screenshot evidence`);
|
|
102
|
-
}
|
|
103
|
-
if (isRuntimeFacing(expectedSurfaces) && !isRuntimeFacing(evidenceText)) {
|
|
104
|
-
errors.push(`${label} expects runtime/API/worker coverage but implemented evidence does not name that surface`);
|
|
105
|
-
}
|
|
106
|
-
assertForbiddenShortcutsNotUsed(row, evidenceText, label, errors);
|
|
107
|
-
}
|
|
108
|
-
await assertReferencedPathsExist(projectRoot, label, `${cell(row, "Context fact")} ${implementedPaths} ${verificationPath}`, errors);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
info.push(`checked plan contract ${repoRelative(projectRoot, planPath)} source_rows=${sourceTable?.rows.length ?? 0} binding_rows=${bindingTable?.rows.length ?? 0}`);
|
|
112
|
-
if (errors.length === 0) {
|
|
113
|
-
info.push("Plan contract validation passed");
|
|
114
|
-
}
|
|
115
|
-
return { info, errors };
|
|
116
|
-
}
|
|
117
|
-
function assertForbiddenShortcutsNotUsed(row, evidenceText, label, errors) {
|
|
118
|
-
const shortcuts = cell(row, "Forbidden shortcuts")
|
|
119
|
-
.split(/[,;\n]/)
|
|
120
|
-
.map((item) => item.trim())
|
|
121
|
-
.filter((item) => item && !isBlankish(item));
|
|
122
|
-
for (const shortcut of shortcuts) {
|
|
123
|
-
if (evidenceText.toLowerCase().includes(shortcut.toLowerCase())) {
|
|
124
|
-
errors.push(`${label} is bound but its evidence uses forbidden shortcut: ${shortcut}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export interface PlanTableRow {
|
|
2
|
-
index: number;
|
|
3
|
-
line: number;
|
|
4
|
-
cells: Record<string, string>;
|
|
5
|
-
text: string;
|
|
6
|
-
}
|
|
7
|
-
export interface ParsedPlanTable {
|
|
8
|
-
rows: PlanTableRow[];
|
|
9
|
-
headers: string[];
|
|
10
|
-
}
|
|
11
|
-
export declare function resolveInputFile(projectRoot: string, value: string | undefined, defaultPath: string): Promise<string>;
|
|
12
|
-
export declare function resolveInputDir(projectRoot: string, value: string | undefined, defaultPath: string): Promise<string>;
|
|
13
|
-
export declare function repoRelative(projectRoot: string, file: string): string;
|
|
14
|
-
export declare function readRequiredFile(projectRoot: string, file: string, label: string, errors: string[]): Promise<string | undefined>;
|
|
15
|
-
export declare function parseRequiredTable(content: string, heading: string, expectedHeaders: string[], label: string, errors: string[]): ParsedPlanTable | undefined;
|
|
16
|
-
export declare function cell(row: PlanTableRow, header: string): string;
|
|
17
|
-
export declare function isBlankish(value: unknown): boolean;
|
|
18
|
-
export declare function weakProofHit(text: string): string | undefined;
|
|
19
|
-
export declare function assertReferencedPathsExist(projectRoot: string, label: string, text: string, errors: string[]): Promise<void>;
|
|
20
|
-
export declare function primitiveText(value: unknown): string;
|
|
21
|
-
export declare function valuesAsArray(value: unknown): string[];
|
|
22
|
-
export declare function hasRealPageEvidence(text: string): boolean;
|
|
23
|
-
export declare function isUiFacing(text: string): boolean;
|
|
24
|
-
export declare function isRuntimeFacing(text: string): boolean;
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { pathExists, readText } from "./fs.js";
|
|
4
|
-
const PATH_PATTERN = /(?:`([^`]+)`)|((?:\.\/)?(?:project_context|packages|tests|tmp|src|app|pages|components|\.codex|tools|examples)\/[A-Za-z0-9._@+/-]+(?:\.(?:md|ts|tsx|js|mjs|json|yaml|yml|toml|png|jpe?g|webp|html|css|scss|py|go|rs|java|cs|sh|ps1))?)/g;
|
|
5
|
-
const WEAK_PROOF_PATTERNS = [
|
|
6
|
-
/\bchecked path(?:s)?\b/i,
|
|
7
|
-
/\bsampled(?:[_ -]?only)?\b/i,
|
|
8
|
-
/\bnot live-proven\b/i,
|
|
9
|
-
/\blacks?\b/i,
|
|
10
|
-
/\bmissing\b/i,
|
|
11
|
-
/\bgap\b/i,
|
|
12
|
-
/\bpartial\b/i,
|
|
13
|
-
/\bblocked\b/i,
|
|
14
|
-
/\bunconfigured\b/i,
|
|
15
|
-
/\bnot visible by default\b/i
|
|
16
|
-
];
|
|
17
|
-
export async function resolveInputFile(projectRoot, value, defaultPath) {
|
|
18
|
-
const raw = value ?? defaultPath;
|
|
19
|
-
const absolute = path.isAbsolute(raw) ? path.resolve(raw) : path.resolve(projectRoot, raw);
|
|
20
|
-
let candidate = absolute;
|
|
21
|
-
try {
|
|
22
|
-
const stat = await fs.stat(absolute);
|
|
23
|
-
if (stat.isDirectory()) {
|
|
24
|
-
candidate = path.join(absolute, defaultPath);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
if (!path.extname(absolute)) {
|
|
29
|
-
candidate = path.join(absolute, defaultPath);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return candidate;
|
|
33
|
-
}
|
|
34
|
-
export async function resolveInputDir(projectRoot, value, defaultPath) {
|
|
35
|
-
return path.isAbsolute(value ?? defaultPath)
|
|
36
|
-
? path.resolve(value ?? defaultPath)
|
|
37
|
-
: path.resolve(projectRoot, value ?? defaultPath);
|
|
38
|
-
}
|
|
39
|
-
export function repoRelative(projectRoot, file) {
|
|
40
|
-
return path.relative(projectRoot, file).split(path.sep).join("/");
|
|
41
|
-
}
|
|
42
|
-
export async function readRequiredFile(projectRoot, file, label, errors) {
|
|
43
|
-
if (!isInside(projectRoot, file)) {
|
|
44
|
-
errors.push(`${label} must stay inside the project root: ${file}`);
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
|
-
if (!(await pathExists(file))) {
|
|
48
|
-
errors.push(`${label} is missing: ${repoRelative(projectRoot, file)}`);
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
return readText(file);
|
|
52
|
-
}
|
|
53
|
-
export function parseRequiredTable(content, heading, expectedHeaders, label, errors) {
|
|
54
|
-
const section = sectionBody(content, heading);
|
|
55
|
-
if (section === undefined) {
|
|
56
|
-
errors.push(`plan contract is missing section: ${heading}`);
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
const lines = section.split(/\r?\n/);
|
|
60
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
61
|
-
if (!lines[index].includes("|")) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
const headers = splitTableLine(lines[index]);
|
|
65
|
-
const normalized = headers.map(normalizeHeader);
|
|
66
|
-
if (!expectedHeaders.every((header) => normalized.includes(normalizeHeader(header)))) {
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const rows = [];
|
|
70
|
-
for (let rowIndex = index + 1; rowIndex < lines.length; rowIndex += 1) {
|
|
71
|
-
const line = lines[rowIndex];
|
|
72
|
-
if (!line.includes("|")) {
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
if (isSeparatorLine(line)) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
const values = splitTableLine(line);
|
|
79
|
-
const cells = {};
|
|
80
|
-
for (const [cellIndex, header] of normalized.entries()) {
|
|
81
|
-
cells[header] = values[cellIndex]?.trim() ?? "";
|
|
82
|
-
}
|
|
83
|
-
rows.push({
|
|
84
|
-
index: rows.length + 1,
|
|
85
|
-
line: rowIndex + 1,
|
|
86
|
-
cells,
|
|
87
|
-
text: Object.values(cells).join(" ")
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
const missing = expectedHeaders.filter((header) => !normalized.includes(normalizeHeader(header)));
|
|
91
|
-
if (missing.length > 0) {
|
|
92
|
-
errors.push(`${label} table is missing column(s): ${missing.join(", ")}`);
|
|
93
|
-
}
|
|
94
|
-
return { rows, headers: normalized };
|
|
95
|
-
}
|
|
96
|
-
errors.push(`${label} section must include a markdown table with columns: ${expectedHeaders.join(" | ")}`);
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
export function cell(row, header) {
|
|
100
|
-
return row.cells[normalizeHeader(header)] ?? "";
|
|
101
|
-
}
|
|
102
|
-
export function isBlankish(value) {
|
|
103
|
-
if (Array.isArray(value)) {
|
|
104
|
-
return value.length === 0 || value.every(isBlankish);
|
|
105
|
-
}
|
|
106
|
-
if (value === undefined || value === null) {
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
const text = String(value).trim().toLowerCase();
|
|
110
|
-
return text === "" || text === "-" || text === "n/a" || text === "na" || text === "none" || text === "[]" || text === "not applicable";
|
|
111
|
-
}
|
|
112
|
-
export function weakProofHit(text) {
|
|
113
|
-
return WEAK_PROOF_PATTERNS.find((pattern) => pattern.test(text))?.source;
|
|
114
|
-
}
|
|
115
|
-
export async function assertReferencedPathsExist(projectRoot, label, text, errors) {
|
|
116
|
-
for (const reference of extractPathReferences(text)) {
|
|
117
|
-
const absolute = path.resolve(projectRoot, reference);
|
|
118
|
-
if (!isInside(projectRoot, absolute)) {
|
|
119
|
-
errors.push(`${label} references a path outside the project root: ${reference}`);
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (!(await pathExists(absolute))) {
|
|
123
|
-
errors.push(`${label} references missing path: ${reference}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
export function primitiveText(value) {
|
|
128
|
-
if (value === undefined || value === null) {
|
|
129
|
-
return "";
|
|
130
|
-
}
|
|
131
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
132
|
-
return String(value);
|
|
133
|
-
}
|
|
134
|
-
if (Array.isArray(value)) {
|
|
135
|
-
return value.map(primitiveText).join(" ");
|
|
136
|
-
}
|
|
137
|
-
if (typeof value === "object") {
|
|
138
|
-
return Object.values(value).map(primitiveText).join(" ");
|
|
139
|
-
}
|
|
140
|
-
return "";
|
|
141
|
-
}
|
|
142
|
-
export function valuesAsArray(value) {
|
|
143
|
-
if (Array.isArray(value)) {
|
|
144
|
-
return value.flatMap(valuesAsArray);
|
|
145
|
-
}
|
|
146
|
-
if (isBlankish(value)) {
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
return String(value)
|
|
150
|
-
.split(/[,;\n]/)
|
|
151
|
-
.map((item) => item.trim())
|
|
152
|
-
.filter(Boolean);
|
|
153
|
-
}
|
|
154
|
-
export function hasRealPageEvidence(text) {
|
|
155
|
-
return /\b(real[- ]page|browser|route|screen|screenshot|url|localhost|https?:\/\/|page)\b/i.test(text);
|
|
156
|
-
}
|
|
157
|
-
export function isUiFacing(text) {
|
|
158
|
-
return /\b(ui|browser|page|screen|console|frontend|route|surface)\b/i.test(text);
|
|
159
|
-
}
|
|
160
|
-
export function isRuntimeFacing(text) {
|
|
161
|
-
return /\b(runtime|worker|api|schema|endpoint|service|queue|daemon|runner)\b/i.test(text);
|
|
162
|
-
}
|
|
163
|
-
function sectionBody(content, heading) {
|
|
164
|
-
const escaped = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
165
|
-
const match = new RegExp(`^##\\s+${escaped}\\s*$`, "im").exec(content);
|
|
166
|
-
if (!match) {
|
|
167
|
-
return undefined;
|
|
168
|
-
}
|
|
169
|
-
const rest = content.slice(match.index + match[0].length);
|
|
170
|
-
const next = /^##\s+/m.exec(rest);
|
|
171
|
-
return next ? rest.slice(0, next.index) : rest;
|
|
172
|
-
}
|
|
173
|
-
function splitTableLine(line) {
|
|
174
|
-
return line.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((cellValue) => cellValue.trim());
|
|
175
|
-
}
|
|
176
|
-
function isSeparatorLine(line) {
|
|
177
|
-
return splitTableLine(line).every((value) => /^:?-{3,}:?$/.test(value.trim()));
|
|
178
|
-
}
|
|
179
|
-
function normalizeHeader(value) {
|
|
180
|
-
return value.replace(/`/g, "").trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
|
|
181
|
-
}
|
|
182
|
-
function extractPathReferences(text) {
|
|
183
|
-
const references = new Set();
|
|
184
|
-
for (const match of text.matchAll(PATH_PATTERN)) {
|
|
185
|
-
const raw = (match[1] ?? match[2] ?? "").trim();
|
|
186
|
-
if (!raw || raw.includes("*") || /^https?:\/\//i.test(raw)) {
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
references.add(raw.replace(/\\/g, "/").replace(/^\.\//, "").replace(/[),.;:]+$/, ""));
|
|
190
|
-
}
|
|
191
|
-
return [...references];
|
|
192
|
-
}
|
|
193
|
-
function isInside(root, target) {
|
|
194
|
-
const relative = path.relative(root, target);
|
|
195
|
-
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
196
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { SuperpowersTaskState } from "./superpowers-task-state-schema.js";
|
|
2
|
-
export interface Ac010BootstrapResult {
|
|
3
|
-
invalidated_ac_ids: string[];
|
|
4
|
-
errors: string[];
|
|
5
|
-
}
|
|
6
|
-
export declare function evaluateAc010Bootstrap(state: SuperpowersTaskState, acStatuses: Record<string, string>): Ac010BootstrapResult;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const SUMMARY_ONLY = /\b(AC[-_ ]?010|final[-_ ]?gate|summary|final[-_ ]?acceptance[-_ ]?verdict|final[-_ ]?summary|matrix|validator)\b/i;
|
|
2
|
-
export function evaluateAc010Bootstrap(state, acStatuses) {
|
|
3
|
-
const invalidated = [];
|
|
4
|
-
const errors = [];
|
|
5
|
-
for (const [acId, ac] of Object.entries(state.graph?.acceptance_criteria ?? {})) {
|
|
6
|
-
if (!isSummaryAc(acId, ac)) {
|
|
7
|
-
continue;
|
|
8
|
-
}
|
|
9
|
-
if (acStatuses[acId] !== "complete" && ac.status !== "complete") {
|
|
10
|
-
continue;
|
|
11
|
-
}
|
|
12
|
-
const incomplete = Object.keys(state.graph.acceptance_criteria).filter((otherId) => otherId !== acId && acIsRequired(otherId) && acStatuses[otherId] !== "complete" && acStatuses[otherId] !== "out_of_scope_NA");
|
|
13
|
-
if (incomplete.length === 0) {
|
|
14
|
-
continue;
|
|
15
|
-
}
|
|
16
|
-
invalidated.push(acId);
|
|
17
|
-
errors.push(`${acId} final_gate_cannot_bootstrap_from_summary_only: summary AC cannot prove incomplete ACs ${incomplete.join(", ")}`);
|
|
18
|
-
}
|
|
19
|
-
return { invalidated_ac_ids: invalidated, errors };
|
|
20
|
-
}
|
|
21
|
-
function isSummaryAc(acId, ac) {
|
|
22
|
-
return /^AC-?0?10$/i.test(acId) || SUMMARY_ONLY.test([ac.scope ?? "", ac.assertion_command ?? "", ...(ac.final_evidence_expected ?? [])].join("\n"));
|
|
23
|
-
}
|
|
24
|
-
function acIsRequired(acId) {
|
|
25
|
-
return !/^AC-?0?10$/i.test(acId);
|
|
26
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { type AssertionResult, type NegativeEvidenceScan } from "./superpowers-task-state-schema.js";
|
|
2
|
-
export declare function normalizeAssertionResult(value: unknown): AssertionResult | undefined;
|
|
3
|
-
export declare function normalizeNegativeEvidenceScan(value: unknown): NegativeEvidenceScan | undefined;
|