project-tiny-context-harness 0.2.85 → 0.6.1
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 +164 -427
- package/assets/README.md +284 -455
- package/assets/README.zh-CN.md +200 -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 +63 -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 +467 -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
|
@@ -19,7 +19,7 @@ export async function buildManifest(params) {
|
|
|
19
19
|
artifacts: params.artifacts.map((artifact) => artifactReport(artifact)),
|
|
20
20
|
warnings: params.warnings,
|
|
21
21
|
omitted: params.omitted,
|
|
22
|
-
recommended_upload_sets: params.recommendedUploadSets
|
|
22
|
+
recommended_upload_sets: params.recommendedUploadSets,
|
|
23
23
|
};
|
|
24
24
|
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@ export function artifactReport(artifact) {
|
|
|
32
32
|
characters: artifact.content.length,
|
|
33
33
|
source_count: artifact.sourceCount,
|
|
34
34
|
source_line_count: artifact.sourceLineCount,
|
|
35
|
-
warning_count: artifact.warningCount
|
|
35
|
+
warning_count: artifact.warningCount,
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
export async function writeArtifactSet(projectRoot, outputDir, artifacts) {
|
|
@@ -55,13 +55,22 @@ export async function pruneTimestampedExports(projectRoot, keepCount) {
|
|
|
55
55
|
catch {
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
|
-
const timestampDirs = entries
|
|
58
|
+
const timestampDirs = entries
|
|
59
|
+
.filter((entry) => /^\d{8}T\d{6}Z$/.test(entry))
|
|
60
|
+
.sort()
|
|
61
|
+
.reverse();
|
|
59
62
|
for (const entry of timestampDirs.slice(keepCount)) {
|
|
60
|
-
await fs.rm(path.join(exportsRoot, entry), {
|
|
63
|
+
await fs.rm(path.join(exportsRoot, entry), {
|
|
64
|
+
recursive: true,
|
|
65
|
+
force: true,
|
|
66
|
+
});
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
export function timestampForFile(now) {
|
|
64
|
-
return now
|
|
70
|
+
return now
|
|
71
|
+
.toISOString()
|
|
72
|
+
.replace(/[-:]/g, "")
|
|
73
|
+
.replace(/\.\d{3}Z$/, "Z");
|
|
65
74
|
}
|
|
66
75
|
async function writeArtifacts(projectRoot, outputDir, artifacts) {
|
|
67
76
|
for (const artifact of artifacts) {
|
|
@@ -78,7 +87,10 @@ async function gitInfo(projectRoot) {
|
|
|
78
87
|
try {
|
|
79
88
|
const shaResult = await execFileAsync("git", ["-C", projectRoot, "rev-parse", "HEAD"], { encoding: "utf8" });
|
|
80
89
|
const dirtyResult = await execFileAsync("git", ["-C", projectRoot, "status", "--porcelain"], { encoding: "utf8" });
|
|
81
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
sha: shaResult.stdout.trim() || null,
|
|
92
|
+
dirty: dirtyResult.stdout.trim().length > 0,
|
|
93
|
+
};
|
|
82
94
|
}
|
|
83
95
|
catch {
|
|
84
96
|
return { sha: null, dirty: false };
|
|
@@ -4,7 +4,7 @@ import { promises as fs } from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import { listFiles, pathExists, readText } from "./fs.js";
|
|
7
|
-
import { shouldExcludeRelativePath, shouldIncludeCodeFile, toPosix } from "./source-files.js";
|
|
7
|
+
import { shouldExcludeRelativePath, shouldIncludeCodeFile, toPosix, } from "./source-files.js";
|
|
8
8
|
import { classifyCodeFile } from "./source-pack-classify.js";
|
|
9
9
|
import { matchesAny } from "./source-pack-config.js";
|
|
10
10
|
const execFileAsync = promisify(execFile);
|
|
@@ -16,10 +16,13 @@ export async function collectCodeRecords(projectRoot, warnings, options = {}) {
|
|
|
16
16
|
const records = [];
|
|
17
17
|
for (const file of candidates) {
|
|
18
18
|
const relative = repoRelative(projectRoot, file);
|
|
19
|
-
if (!shouldIncludeCodeFile(relative) ||
|
|
19
|
+
if (!shouldIncludeCodeFile(relative) ||
|
|
20
|
+
matchesAny(relative, options.exclude ?? [])) {
|
|
20
21
|
continue;
|
|
21
22
|
}
|
|
22
|
-
if (options.include &&
|
|
23
|
+
if (options.include &&
|
|
24
|
+
options.include.length > 0 &&
|
|
25
|
+
!matchesAny(relative, options.include)) {
|
|
23
26
|
continue;
|
|
24
27
|
}
|
|
25
28
|
if (!(await isRegularFile(file))) {
|
|
@@ -44,26 +47,36 @@ export async function collectCodeRecords(projectRoot, warnings, options = {}) {
|
|
|
44
47
|
routes: classification.routes,
|
|
45
48
|
score: classification.score,
|
|
46
49
|
bucket: classification.bucket,
|
|
47
|
-
bundle: "omitted"
|
|
50
|
+
bundle: "omitted",
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
53
|
return records.sort((left, right) => left.relative.localeCompare(right.relative));
|
|
51
54
|
}
|
|
52
55
|
export async function collectContextArtifacts(projectRoot, warnings, includePatterns) {
|
|
53
56
|
const files = new Set();
|
|
54
|
-
for (const relative of [
|
|
57
|
+
for (const relative of [
|
|
58
|
+
"AGENTS.md",
|
|
59
|
+
"README.md",
|
|
60
|
+
"DESIGN.md",
|
|
61
|
+
"project_context/global.md",
|
|
62
|
+
"project_context/architecture.md",
|
|
63
|
+
"project_context/context.toml",
|
|
64
|
+
]) {
|
|
55
65
|
await addIfExists(projectRoot, files, warnings, relative, relative.startsWith("project_context/"));
|
|
56
66
|
}
|
|
57
67
|
for (const file of await listFiles(path.join(projectRoot, "project_context"))) {
|
|
58
68
|
const relative = repoRelative(projectRoot, file);
|
|
59
|
-
if ((relative.endsWith(".md") || relative.endsWith(".toml")) &&
|
|
69
|
+
if ((relative.endsWith(".md") || relative.endsWith(".toml")) &&
|
|
70
|
+
!shouldExcludeRelativePath(relative)) {
|
|
60
71
|
files.add(file);
|
|
61
72
|
}
|
|
62
73
|
}
|
|
63
74
|
const artifacts = [];
|
|
64
75
|
for (const file of [...files].sort((a, b) => repoRelative(projectRoot, a).localeCompare(repoRelative(projectRoot, b)))) {
|
|
65
76
|
const relative = repoRelative(projectRoot, file);
|
|
66
|
-
if (includePatterns &&
|
|
77
|
+
if (includePatterns &&
|
|
78
|
+
includePatterns.length > 0 &&
|
|
79
|
+
!matchesAny(relative, includePatterns)) {
|
|
67
80
|
continue;
|
|
68
81
|
}
|
|
69
82
|
const rawContent = await readText(file);
|
|
@@ -75,7 +88,7 @@ export async function collectContextArtifacts(projectRoot, warnings, includePatt
|
|
|
75
88
|
relative,
|
|
76
89
|
content: redacted.content,
|
|
77
90
|
lines: countLines(redacted.content),
|
|
78
|
-
characters: redacted.content.length
|
|
91
|
+
characters: redacted.content.length,
|
|
79
92
|
});
|
|
80
93
|
}
|
|
81
94
|
return artifacts;
|
|
@@ -103,11 +116,22 @@ async function addIfExists(projectRoot, files, warnings, relative, required) {
|
|
|
103
116
|
}
|
|
104
117
|
async function listGitCandidateFiles(projectRoot) {
|
|
105
118
|
try {
|
|
106
|
-
const result = await execFileAsync("git", [
|
|
119
|
+
const result = await execFileAsync("git", [
|
|
120
|
+
"-C",
|
|
121
|
+
projectRoot,
|
|
122
|
+
"ls-files",
|
|
123
|
+
"--cached",
|
|
124
|
+
"--others",
|
|
125
|
+
"--exclude-standard",
|
|
126
|
+
"-z",
|
|
127
|
+
], {
|
|
107
128
|
encoding: "utf8",
|
|
108
|
-
maxBuffer: GIT_LS_MAX_BUFFER
|
|
129
|
+
maxBuffer: GIT_LS_MAX_BUFFER,
|
|
109
130
|
});
|
|
110
|
-
return result.stdout
|
|
131
|
+
return result.stdout
|
|
132
|
+
.split("\0")
|
|
133
|
+
.filter(Boolean)
|
|
134
|
+
.map((relative) => path.join(projectRoot, ...toPosix(relative).split("/")));
|
|
111
135
|
}
|
|
112
136
|
catch {
|
|
113
137
|
return undefined;
|
|
@@ -22,7 +22,7 @@ export function renderFullProjectContextArtifact(contexts, warnings, meta) {
|
|
|
22
22
|
"## Context Sources",
|
|
23
23
|
"",
|
|
24
24
|
...contexts.map(renderContextArtifact),
|
|
25
|
-
""
|
|
25
|
+
"",
|
|
26
26
|
].join("\n");
|
|
27
27
|
}
|
|
28
28
|
export function renderCodeIndexArtifact(records, areas, warnings, meta) {
|
|
@@ -52,7 +52,11 @@ export function renderCodeIndexArtifact(records, areas, warnings, meta) {
|
|
|
52
52
|
"## Context Area Mapping",
|
|
53
53
|
"",
|
|
54
54
|
"Inferred buckets below are export routing only; they are not durable architecture or product ownership facts.",
|
|
55
|
-
areas.length > 0
|
|
55
|
+
areas.length > 0
|
|
56
|
+
? areas
|
|
57
|
+
.map((area) => `- ${area.id}: root=${area.root}; context=${area.context}`)
|
|
58
|
+
.join("\n")
|
|
59
|
+
: "- No Context area mappings found.",
|
|
56
60
|
"",
|
|
57
61
|
"## Key Entry Points",
|
|
58
62
|
"",
|
|
@@ -68,7 +72,9 @@ export function renderCodeIndexArtifact(records, areas, warnings, meta) {
|
|
|
68
72
|
"",
|
|
69
73
|
"## CLI / Worker / Script Index",
|
|
70
74
|
"",
|
|
71
|
-
renderRecordList(records
|
|
75
|
+
renderRecordList(records
|
|
76
|
+
.filter((record) => record.tags.includes("cli") || record.tags.includes("worker"))
|
|
77
|
+
.slice(0, 30)),
|
|
72
78
|
"",
|
|
73
79
|
"## Test / Verification Index",
|
|
74
80
|
"",
|
|
@@ -76,12 +82,14 @@ export function renderCodeIndexArtifact(records, areas, warnings, meta) {
|
|
|
76
82
|
"",
|
|
77
83
|
"## Oversized Files",
|
|
78
84
|
"",
|
|
79
|
-
renderRecordList(records
|
|
85
|
+
renderRecordList(records
|
|
86
|
+
.filter((record) => record.tags.includes("oversized"))
|
|
87
|
+
.slice(0, 30)),
|
|
80
88
|
"",
|
|
81
89
|
"## Source File Index",
|
|
82
90
|
"",
|
|
83
91
|
renderSourceFileIndex(records),
|
|
84
|
-
""
|
|
92
|
+
"",
|
|
85
93
|
].join("\n");
|
|
86
94
|
}
|
|
87
95
|
export function renderBundleArtifact(title, records, contexts, omitted, warnings, meta, policy) {
|
|
@@ -109,16 +117,21 @@ export function renderBundleArtifact(title, records, contexts, omitted, warnings
|
|
|
109
117
|
"",
|
|
110
118
|
"## Related Context Paths",
|
|
111
119
|
"",
|
|
112
|
-
contexts.length > 0
|
|
120
|
+
contexts.length > 0
|
|
121
|
+
? contexts
|
|
122
|
+
.map((context) => `- ${context.relative} (${context.lines} lines)`)
|
|
123
|
+
.join("\n")
|
|
124
|
+
: "- No related Context files selected.",
|
|
113
125
|
"",
|
|
114
126
|
"## Source Files",
|
|
115
127
|
"",
|
|
116
|
-
records.map(renderSourceRecord).join("\n\n") ||
|
|
128
|
+
records.map(renderSourceRecord).join("\n\n") ||
|
|
129
|
+
"- No source files selected for this bundle.",
|
|
117
130
|
"",
|
|
118
131
|
"## Omitted Files Summary",
|
|
119
132
|
"",
|
|
120
133
|
renderOmittedSummary(omitted),
|
|
121
|
-
""
|
|
134
|
+
"",
|
|
122
135
|
].join("\n");
|
|
123
136
|
}
|
|
124
137
|
export function renderTaskContextArtifact(taskName, contexts, records, verification, omitted, warnings, meta) {
|
|
@@ -150,21 +163,31 @@ export function renderTaskContextArtifact(taskName, contexts, records, verificat
|
|
|
150
163
|
"",
|
|
151
164
|
"## Selected Source Files",
|
|
152
165
|
"",
|
|
153
|
-
records.map(renderSourceRecord).join("\n\n") ||
|
|
166
|
+
records.map(renderSourceRecord).join("\n\n") ||
|
|
167
|
+
"- No selected source files matched the task filters.",
|
|
154
168
|
"",
|
|
155
169
|
"## Verification Entry Points",
|
|
156
170
|
"",
|
|
157
|
-
verification.length > 0
|
|
171
|
+
verification.length > 0
|
|
172
|
+
? verification.map((entry) => `- ${entry}`).join("\n")
|
|
173
|
+
: "- No profile verification entries selected.",
|
|
158
174
|
"",
|
|
159
175
|
"## Omitted / Support Notes",
|
|
160
176
|
"",
|
|
161
177
|
renderOmittedSummary(omitted),
|
|
162
|
-
""
|
|
178
|
+
"",
|
|
163
179
|
].join("\n");
|
|
164
180
|
}
|
|
165
181
|
function renderContextArtifact(context) {
|
|
166
182
|
const fence = fenceFor(context.content);
|
|
167
|
-
return [
|
|
183
|
+
return [
|
|
184
|
+
`### ${context.relative}`,
|
|
185
|
+
"",
|
|
186
|
+
`${fence}markdown`,
|
|
187
|
+
context.content.trimEnd(),
|
|
188
|
+
fence,
|
|
189
|
+
"",
|
|
190
|
+
].join("\n");
|
|
168
191
|
}
|
|
169
192
|
function renderSourceRecord(record) {
|
|
170
193
|
const fence = fenceFor(record.content);
|
|
@@ -183,7 +206,7 @@ function renderSourceRecord(record) {
|
|
|
183
206
|
"",
|
|
184
207
|
`${fence}${record.language}`,
|
|
185
208
|
record.content.trimEnd(),
|
|
186
|
-
fence
|
|
209
|
+
fence,
|
|
187
210
|
].join("\n");
|
|
188
211
|
}
|
|
189
212
|
function renderSourceFileIndex(records) {
|
|
@@ -193,7 +216,7 @@ function renderSourceFileIndex(records) {
|
|
|
193
216
|
return [
|
|
194
217
|
"| Path | Type | Lines | Characters | SHA256 | Summary | Bundle | Tags |",
|
|
195
218
|
"|---|---:|---:|---:|---|---|---|---|",
|
|
196
|
-
...records.map((record) => `| ${escapeTableCell(record.relative)} | ${escapeTableCell(record.language)} | ${record.lines} | ${record.characters} | ${record.sha256.slice(0, 12)} | ${escapeTableCell(record.summary)} | ${record.bundle} | ${escapeTableCell(record.tags.join(", "))} |`)
|
|
219
|
+
...records.map((record) => `| ${escapeTableCell(record.relative)} | ${escapeTableCell(record.language)} | ${record.lines} | ${record.characters} | ${record.sha256.slice(0, 12)} | ${escapeTableCell(record.summary)} | ${record.bundle} | ${escapeTableCell(record.tags.join(", "))} |`),
|
|
197
220
|
].join("\n");
|
|
198
221
|
}
|
|
199
222
|
function renderRepositoryShape(records) {
|
|
@@ -202,10 +225,10 @@ function renderRepositoryShape(records) {
|
|
|
202
225
|
const top = record.relative.split("/")[0] || ".";
|
|
203
226
|
counts.set(top, (counts.get(top) ?? 0) + 1);
|
|
204
227
|
}
|
|
205
|
-
return [...counts.entries()]
|
|
228
|
+
return ([...counts.entries()]
|
|
206
229
|
.sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]))
|
|
207
230
|
.map(([name, count]) => `- ${name}: ${count} source file(s)`)
|
|
208
|
-
.join("\n") || "- No source files matched.";
|
|
231
|
+
.join("\n") || "- No source files matched.");
|
|
209
232
|
}
|
|
210
233
|
function renderRecordList(records, includeRoutes = false) {
|
|
211
234
|
if (records.length === 0) {
|
|
@@ -216,13 +239,19 @@ function renderRecordList(records, includeRoutes = false) {
|
|
|
216
239
|
.join("\n");
|
|
217
240
|
}
|
|
218
241
|
function renderWarningList(warnings) {
|
|
219
|
-
return warnings.length > 0
|
|
242
|
+
return warnings.length > 0
|
|
243
|
+
? warnings.map((warning) => ` - ${warning}`)
|
|
244
|
+
: [" - none"];
|
|
220
245
|
}
|
|
221
246
|
function renderOmittedSummary(omitted) {
|
|
222
247
|
const reasons = Object.entries(omitted.reason_counts)
|
|
223
248
|
.sort((left, right) => left[0].localeCompare(right[0]))
|
|
224
249
|
.map(([reason, count]) => ` - ${reason}: ${count}`);
|
|
225
|
-
return [
|
|
250
|
+
return [
|
|
251
|
+
`- omitted_source_file_count: ${omitted.source_file_count}`,
|
|
252
|
+
"- reason_counts:",
|
|
253
|
+
...(reasons.length > 0 ? reasons : [" - none: 0"]),
|
|
254
|
+
].join("\n");
|
|
226
255
|
}
|
|
227
256
|
function fenceFor(content) {
|
|
228
257
|
let fence = "```";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export function stableJson(value) {
|
|
3
|
+
return JSON.stringify(sortJson(value), null, 2);
|
|
4
|
+
}
|
|
5
|
+
export function sha256(value) {
|
|
6
|
+
return createHash("sha256").update(value).digest("hex");
|
|
7
|
+
}
|
|
8
|
+
function sortJson(value) {
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
return value.map(sortJson);
|
|
11
|
+
}
|
|
12
|
+
if (!isRecord(value)) {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
return Object.fromEntries(Object.keys(value)
|
|
16
|
+
.sort()
|
|
17
|
+
.map((key) => [key, sortJson(value[key])]));
|
|
18
|
+
}
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
21
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function canonicalJson(value: unknown): string;
|
|
2
|
+
export declare function canonicalValueJson(value: unknown): string;
|
|
3
|
+
export declare function sha256Hex(value: string | Uint8Array): string;
|
|
4
|
+
export declare function parseStrictYaml(content: string): unknown;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import YAML, { isAlias, isMap, isPair, isScalar, isSeq, visit, } from "yaml";
|
|
3
|
+
export function canonicalJson(value) {
|
|
4
|
+
return `${JSON.stringify(sortCanonical(value), null, 2)}\n`;
|
|
5
|
+
}
|
|
6
|
+
export function canonicalValueJson(value) {
|
|
7
|
+
return JSON.stringify(sortCanonical(value));
|
|
8
|
+
}
|
|
9
|
+
export function sha256Hex(value) {
|
|
10
|
+
return createHash("sha256").update(value).digest("hex");
|
|
11
|
+
}
|
|
12
|
+
export function parseStrictYaml(content) {
|
|
13
|
+
if (content.charCodeAt(0) === 0xfeff)
|
|
14
|
+
throw new Error("YAML byte-order marks are not allowed");
|
|
15
|
+
if (/^%(?:YAML|TAG)\b/m.test(content))
|
|
16
|
+
throw new Error("YAML directives are not allowed");
|
|
17
|
+
const documents = YAML.parseAllDocuments(content, {
|
|
18
|
+
merge: false,
|
|
19
|
+
schema: "core",
|
|
20
|
+
strict: true,
|
|
21
|
+
stringKeys: true,
|
|
22
|
+
uniqueKeys: true,
|
|
23
|
+
});
|
|
24
|
+
const document = assertSingleDocument(documents);
|
|
25
|
+
if (document.directives.yaml.explicit ||
|
|
26
|
+
Object.keys(document.directives.tags).some((handle) => handle !== "!!"))
|
|
27
|
+
throw new Error("YAML directives are not allowed");
|
|
28
|
+
visit(document, (_key, node) => inspectNode(node));
|
|
29
|
+
return document.toJS({ maxAliasCount: 0 });
|
|
30
|
+
}
|
|
31
|
+
function assertSingleDocument(documents) {
|
|
32
|
+
if (documents.length !== 1)
|
|
33
|
+
throw new Error("YAML must contain exactly one document");
|
|
34
|
+
const document = documents[0];
|
|
35
|
+
const issue = document.errors[0] ?? document.warnings[0];
|
|
36
|
+
if (issue)
|
|
37
|
+
throw new Error(`Invalid YAML: ${issue.message}`);
|
|
38
|
+
return document;
|
|
39
|
+
}
|
|
40
|
+
function inspectNode(node) {
|
|
41
|
+
if (isAlias(node))
|
|
42
|
+
throw new Error("YAML aliases are not allowed");
|
|
43
|
+
const tagged = node;
|
|
44
|
+
if (tagged.anchor)
|
|
45
|
+
throw new Error("YAML anchors are not allowed");
|
|
46
|
+
if (tagged.tag)
|
|
47
|
+
throw new Error("YAML explicit tags are not allowed");
|
|
48
|
+
if (isPair(node) && isScalar(node.key) && node.key.value === "<<")
|
|
49
|
+
throw new Error("YAML merge keys are not allowed");
|
|
50
|
+
if (isMap(node) || isSeq(node) || isScalar(node) || isPair(node))
|
|
51
|
+
return;
|
|
52
|
+
throw new Error("Unsupported YAML node");
|
|
53
|
+
}
|
|
54
|
+
function sortCanonical(value) {
|
|
55
|
+
if (Array.isArray(value))
|
|
56
|
+
return value.map(sortCanonical);
|
|
57
|
+
if (value && typeof value === "object")
|
|
58
|
+
return Object.fromEntries(Object.keys(value)
|
|
59
|
+
.sort()
|
|
60
|
+
.map((key) => [
|
|
61
|
+
key,
|
|
62
|
+
sortCanonical(value[key]),
|
|
63
|
+
]));
|
|
64
|
+
return value;
|
|
65
|
+
}
|
package/dist/lib/sync-engine.js
CHANGED
|
@@ -2,15 +2,17 @@ import path from "node:path";
|
|
|
2
2
|
import { promises as fs } from "node:fs";
|
|
3
3
|
import { readConfig } from "./config.js";
|
|
4
4
|
import { harnessPath, harnessRoot } from "./harness-root.js";
|
|
5
|
-
import { copyTree, listFiles, pathExists, readText, writeTextIfChanged } from "./fs.js";
|
|
6
|
-
import { AGENTS_BLOCK_MARKERS, GITHUB_WORKFLOW_BLOCK_END, GITHUB_WORKFLOW_BLOCK_MARKERS, GITHUB_WORKFLOW_BLOCK_START, MAKEFILE_BLOCK_END, MAKEFILE_BLOCK_MARKERS, MAKEFILE_BLOCK_START, MANAGED_BLOCK_END, MANAGED_BLOCK_START } from "./managed-file.js";
|
|
5
|
+
import { copyTree, listFiles, pathExists, readText, writeTextIfChanged, } from "./fs.js";
|
|
6
|
+
import { AGENTS_BLOCK_MARKERS, GITHUB_WORKFLOW_BLOCK_END, GITHUB_WORKFLOW_BLOCK_MARKERS, GITHUB_WORKFLOW_BLOCK_START, MAKEFILE_BLOCK_END, MAKEFILE_BLOCK_MARKERS, MAKEFILE_BLOCK_START, MANAGED_BLOCK_END, MANAGED_BLOCK_START, } from "./managed-file.js";
|
|
7
7
|
import { packageAssetPath } from "./paths.js";
|
|
8
8
|
import { assertSupportedSchema } from "./schema-guard.js";
|
|
9
|
+
import { installLongTaskHooks, uninstallLongTaskHooks, } from "./long-task-hook-install.js";
|
|
10
|
+
import { enabledManagedSkillNames, isProfileEnabled } from "./profiles.js";
|
|
9
11
|
export function emptySyncReport() {
|
|
10
12
|
return {
|
|
11
13
|
changed: [],
|
|
12
14
|
skipped: [],
|
|
13
|
-
blocked: []
|
|
15
|
+
blocked: [],
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
18
|
export async function runSync(projectRoot) {
|
|
@@ -23,11 +25,17 @@ export async function runSync(projectRoot) {
|
|
|
23
25
|
return report;
|
|
24
26
|
}
|
|
25
27
|
for (const managedFile of config.managed_files) {
|
|
26
|
-
await syncManagedFile(projectRoot, root, managedFile, report);
|
|
28
|
+
await syncManagedFile(projectRoot, root, managedFile, report, config);
|
|
29
|
+
}
|
|
30
|
+
if (isProfileEnabled(config, "long-task")) {
|
|
31
|
+
await installLongTaskHooks(projectRoot, report);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
await uninstallLongTaskHooks(projectRoot, report);
|
|
27
35
|
}
|
|
28
36
|
return report;
|
|
29
37
|
}
|
|
30
|
-
async function syncManagedFile(projectRoot, root, managedFile, report) {
|
|
38
|
+
async function syncManagedFile(projectRoot, root, managedFile, report, config) {
|
|
31
39
|
const destination = path.join(projectRoot, managedFile.path);
|
|
32
40
|
if (managedFile.path === "AGENTS.md") {
|
|
33
41
|
await syncAgentsBlock(destination, root, report);
|
|
@@ -38,7 +46,7 @@ async function syncManagedFile(projectRoot, root, managedFile, report) {
|
|
|
38
46
|
return;
|
|
39
47
|
}
|
|
40
48
|
if (isSkillsManagedPath(managedFile.path, root)) {
|
|
41
|
-
await syncSkillsTree(packageAssetPath("skills"), path.join(projectRoot, root, "skills"), report);
|
|
49
|
+
await syncSkillsTree(packageAssetPath("skills"), path.join(projectRoot, root, "skills"), report, enabledManagedSkillNames(config));
|
|
42
50
|
return;
|
|
43
51
|
}
|
|
44
52
|
const managedPath = normalizeManagedPath(managedFile.path);
|
|
@@ -47,14 +55,17 @@ async function syncManagedFile(projectRoot, root, managedFile, report) {
|
|
|
47
55
|
return;
|
|
48
56
|
}
|
|
49
57
|
if (managedPath === harnessPath(root, "ty-context-managed", "context_templates")) {
|
|
50
|
-
await syncTree(packageAssetPath("context_templates"), destination, report, {
|
|
58
|
+
await syncTree(packageAssetPath("context_templates"), destination, report, {
|
|
59
|
+
prune: true,
|
|
60
|
+
});
|
|
51
61
|
return;
|
|
52
62
|
}
|
|
53
63
|
if (managedPath === harnessPath(root, "ty-context-managed", "policies")) {
|
|
54
64
|
await syncTree(packageAssetPath("policies"), destination, report);
|
|
55
65
|
return;
|
|
56
66
|
}
|
|
57
|
-
if (managedPath ===
|
|
67
|
+
if (managedPath ===
|
|
68
|
+
harnessPath(root, "ty-context-managed", "make", "ty-context.mk")) {
|
|
58
69
|
await syncFile(packageAssetPath("make", "ty-context.mk"), destination, report, "skip-if-missing");
|
|
59
70
|
return;
|
|
60
71
|
}
|
|
@@ -85,14 +96,16 @@ async function syncAgentsBlock(destination, root, report) {
|
|
|
85
96
|
}
|
|
86
97
|
const core = renderAgentsCore(await readText(corePath), root);
|
|
87
98
|
const block = `${MANAGED_BLOCK_START}\n${core.trim()}\n${MANAGED_BLOCK_END}`;
|
|
88
|
-
const existing = (await pathExists(destination))
|
|
99
|
+
const existing = (await pathExists(destination))
|
|
100
|
+
? await readText(destination)
|
|
101
|
+
: "";
|
|
89
102
|
const next = mergeManagedBlock({
|
|
90
103
|
existing,
|
|
91
104
|
block,
|
|
92
105
|
markers: AGENTS_BLOCK_MARKERS,
|
|
93
106
|
pathLabel: "AGENTS.md",
|
|
94
107
|
insert: "append",
|
|
95
|
-
report
|
|
108
|
+
report,
|
|
96
109
|
});
|
|
97
110
|
if (!next) {
|
|
98
111
|
return;
|
|
@@ -108,14 +121,16 @@ function renderAgentsCore(content, root) {
|
|
|
108
121
|
return content.replaceAll(".agent", root).replaceAll(".codex", root);
|
|
109
122
|
}
|
|
110
123
|
async function syncMakefileInclude(destination, root, report) {
|
|
111
|
-
const existing = (await pathExists(destination))
|
|
124
|
+
const existing = (await pathExists(destination))
|
|
125
|
+
? await readText(destination)
|
|
126
|
+
: "";
|
|
112
127
|
const resetDefaultGoal = shouldResetMakeDefaultGoal(existing);
|
|
113
128
|
const includePath = `${root.replace(/\\/g, "/")}/ty-context-managed/make/ty-context.mk`;
|
|
114
129
|
const blockLines = [
|
|
115
130
|
MAKEFILE_BLOCK_START,
|
|
116
131
|
"# Included before project targets so project recipes win on name conflicts.",
|
|
117
132
|
`-include ${includePath}`,
|
|
118
|
-
MAKEFILE_BLOCK_END
|
|
133
|
+
MAKEFILE_BLOCK_END,
|
|
119
134
|
];
|
|
120
135
|
if (resetDefaultGoal) {
|
|
121
136
|
blockLines.splice(3, 0, ".DEFAULT_GOAL :=");
|
|
@@ -127,7 +142,7 @@ async function syncMakefileInclude(destination, root, report) {
|
|
|
127
142
|
markers: MAKEFILE_BLOCK_MARKERS,
|
|
128
143
|
pathLabel: "Makefile",
|
|
129
144
|
insert: "prepend",
|
|
130
|
-
report
|
|
145
|
+
report,
|
|
131
146
|
});
|
|
132
147
|
if (!next) {
|
|
133
148
|
return;
|
|
@@ -194,9 +209,14 @@ function findManagedBlock(existing, markersList) {
|
|
|
194
209
|
matches.push({ markers, startIndex, endIndex });
|
|
195
210
|
}
|
|
196
211
|
if (matches.length > 1) {
|
|
197
|
-
return {
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
return {
|
|
213
|
+
status: "invalid",
|
|
214
|
+
reason: "conflicting managed block marker namespaces",
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return matches[0]
|
|
218
|
+
? { status: "found", ...matches[0] }
|
|
219
|
+
: { status: "missing" };
|
|
200
220
|
}
|
|
201
221
|
async function syncTree(source, destination, report, options = {}) {
|
|
202
222
|
if (!(await pathExists(source))) {
|
|
@@ -224,7 +244,10 @@ async function removeStaleManagedFiles(source, destination) {
|
|
|
224
244
|
.map((file) => path.relative(source, file).split(path.sep).join("/")));
|
|
225
245
|
const removed = [];
|
|
226
246
|
for (const destinationFile of await listFiles(destination)) {
|
|
227
|
-
const relative = path
|
|
247
|
+
const relative = path
|
|
248
|
+
.relative(destination, destinationFile)
|
|
249
|
+
.split(path.sep)
|
|
250
|
+
.join("/");
|
|
228
251
|
if (sourceFiles.has(relative)) {
|
|
229
252
|
continue;
|
|
230
253
|
}
|
|
@@ -233,13 +256,18 @@ async function removeStaleManagedFiles(source, destination) {
|
|
|
233
256
|
}
|
|
234
257
|
return removed;
|
|
235
258
|
}
|
|
236
|
-
async function syncSkillsTree(source, destination, report) {
|
|
259
|
+
async function syncSkillsTree(source, destination, report, enabledSkillNames) {
|
|
237
260
|
if (!(await pathExists(source))) {
|
|
238
261
|
report.skipped.push(path.basename(destination));
|
|
239
262
|
return;
|
|
240
263
|
}
|
|
241
264
|
const files = await listFiles(source);
|
|
242
|
-
const
|
|
265
|
+
const allManagedSkillNames = new Set(files
|
|
266
|
+
.map((file) => path.relative(source, file).split(path.sep)[0])
|
|
267
|
+
.filter(Boolean));
|
|
268
|
+
const realFiles = files
|
|
269
|
+
.filter((file) => !file.endsWith(".gitkeep"))
|
|
270
|
+
.filter((file) => enabledSkillNames.has(path.relative(source, file).split(path.sep)[0]));
|
|
243
271
|
if (realFiles.length === 0) {
|
|
244
272
|
report.skipped.push(path.basename(destination));
|
|
245
273
|
return;
|
|
@@ -254,6 +282,21 @@ async function syncSkillsTree(source, destination, report) {
|
|
|
254
282
|
report.skipped.push(destinationFile);
|
|
255
283
|
}
|
|
256
284
|
}
|
|
285
|
+
const managedSkillNames = new Set(realFiles
|
|
286
|
+
.map((file) => path.relative(source, file).split(path.sep)[0])
|
|
287
|
+
.filter(Boolean));
|
|
288
|
+
for (const skillName of managedSkillNames) {
|
|
289
|
+
report.changed.push(...(await removeStaleManagedFiles(path.join(source, skillName), path.join(destination, skillName))));
|
|
290
|
+
}
|
|
291
|
+
for (const skillName of allManagedSkillNames) {
|
|
292
|
+
if (enabledSkillNames.has(skillName))
|
|
293
|
+
continue;
|
|
294
|
+
const disabled = path.join(destination, skillName);
|
|
295
|
+
if (!(await pathExists(disabled)))
|
|
296
|
+
continue;
|
|
297
|
+
await fs.rm(disabled, { recursive: true, force: true });
|
|
298
|
+
report.changed.push(disabled);
|
|
299
|
+
}
|
|
257
300
|
}
|
|
258
301
|
async function blockDeprecatedSkillOverrides(projectRoot, root, report) {
|
|
259
302
|
for (const overrideRoot of skillOverrideRoots(projectRoot, root)) {
|
|
@@ -274,12 +317,18 @@ function skillOverrideRoots(projectRoot, root) {
|
|
|
274
317
|
return [
|
|
275
318
|
{
|
|
276
319
|
absolute: path.join(projectRoot, root, "ty-context-managed", "override_skills"),
|
|
277
|
-
relative: path
|
|
320
|
+
relative: path
|
|
321
|
+
.join(root, "ty-context-managed", "override_skills")
|
|
322
|
+
.split(path.sep)
|
|
323
|
+
.join("/"),
|
|
278
324
|
},
|
|
279
325
|
{
|
|
280
326
|
absolute: path.join(projectRoot, root, "pjsdlc_managed", "override_skills"),
|
|
281
|
-
relative: path
|
|
282
|
-
|
|
327
|
+
relative: path
|
|
328
|
+
.join(root, "pjsdlc_managed", "override_skills")
|
|
329
|
+
.split(path.sep)
|
|
330
|
+
.join("/"),
|
|
331
|
+
},
|
|
283
332
|
];
|
|
284
333
|
}
|
|
285
334
|
async function syncFile(source, destination, report, missingMode) {
|
|
@@ -320,7 +369,9 @@ async function syncGithubWorkflow(source, destination, relativePath, report) {
|
|
|
320
369
|
report.blocked.push(`${relativePath}: incomplete managed workflow markers`);
|
|
321
370
|
return;
|
|
322
371
|
}
|
|
323
|
-
if (markerState === "managed" ||
|
|
372
|
+
if (markerState === "managed" ||
|
|
373
|
+
normalizeWorkflow(existing) ===
|
|
374
|
+
normalizeWorkflow(stripWorkflowMarkers(sourceContent))) {
|
|
324
375
|
if (await writeTextIfChanged(destination, sourceContent)) {
|
|
325
376
|
report.changed.push(relativePath);
|
|
326
377
|
}
|
|
@@ -344,7 +395,8 @@ function workflowMarkerState(content) {
|
|
|
344
395
|
function stripWorkflowMarkers(content) {
|
|
345
396
|
return content
|
|
346
397
|
.split(/\r?\n/)
|
|
347
|
-
.filter((line) => line.trim() !== GITHUB_WORKFLOW_BLOCK_START &&
|
|
398
|
+
.filter((line) => line.trim() !== GITHUB_WORKFLOW_BLOCK_START &&
|
|
399
|
+
line.trim() !== GITHUB_WORKFLOW_BLOCK_END)
|
|
348
400
|
.join("\n");
|
|
349
401
|
}
|
|
350
402
|
function normalizeWorkflow(content) {
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -3,10 +3,14 @@ export interface HarnessConfig {
|
|
|
3
3
|
package: string;
|
|
4
4
|
schema_version: string;
|
|
5
5
|
};
|
|
6
|
+
profiles: {
|
|
7
|
+
enabled: HarnessProfile[];
|
|
8
|
+
};
|
|
6
9
|
modularity?: HarnessModularityConfig;
|
|
7
10
|
managed_files: ManagedFile[];
|
|
8
11
|
never_overwrite: string[];
|
|
9
12
|
}
|
|
13
|
+
export type HarnessProfile = "core-portable" | "workflow-default" | "long-task";
|
|
10
14
|
export interface HarnessModularityConfig {
|
|
11
15
|
limit?: number;
|
|
12
16
|
policy?: "scoped_waivers" | "strict_except_generated";
|
|
@@ -15,8 +19,11 @@ export interface HarnessModularityConfig {
|
|
|
15
19
|
export interface ModularityWaiverConfig {
|
|
16
20
|
path?: string;
|
|
17
21
|
category?: string;
|
|
22
|
+
owner?: string;
|
|
23
|
+
introduced_at?: string;
|
|
18
24
|
reason?: string;
|
|
19
|
-
|
|
25
|
+
tracking_issue?: string;
|
|
26
|
+
expiry_condition?: string;
|
|
20
27
|
}
|
|
21
28
|
export interface ManagedFile {
|
|
22
29
|
path: string;
|