project-tiny-context-harness 0.8.11 → 0.8.13
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/LICENSE +21 -21
- package/README.md +514 -472
- package/assets/README.md +803 -749
- package/assets/README.zh-CN.md +468 -431
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +22 -24
- package/assets/agents/long-task-implementation.toml +15 -0
- package/assets/context_templates/architecture.md +18 -18
- package/assets/context_templates/area.md +30 -30
- package/assets/context_templates/context.toml +24 -24
- package/assets/context_templates/deployment.md +35 -35
- package/assets/context_templates/global.md +56 -56
- package/assets/context_templates/product-surface-contract.md +70 -70
- package/assets/context_templates/screen-contract.md +189 -189
- package/assets/context_templates/verification.md +25 -25
- package/assets/github/.gitkeep +1 -1
- package/assets/github/harness.yml +39 -39
- package/assets/make/.gitkeep +1 -1
- package/assets/make/ty-context.mk +48 -48
- package/assets/skills/context_development_engineer/SKILL.md +72 -185
- package/assets/skills/context_full_project_export/SKILL.md +28 -28
- package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
- package/assets/skills/context_product_plan/SKILL.md +35 -101
- package/assets/skills/context_surface_contract/SKILL.md +194 -191
- package/assets/skills/context_uiux_design/SKILL.md +49 -172
- package/assets/skills/design-resource-authoring/SKILL.md +54 -88
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +51 -163
- package/assets/skills/design-resource-authoring/references/formal-selected-web-app-handoff.md +96 -0
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +140 -120
- package/assets/skills/design-resource-authoring/references/recovery-and-writeback.md +199 -0
- package/assets/skills/design-resource-authoring/references/resource-selection.md +158 -181
- package/assets/skills/design-system-authoring/SKILL.md +57 -57
- package/assets/skills/design-system-authoring/agents/openai.yaml +6 -6
- package/assets/skills/design-system-authoring/references/authority-adoption.md +48 -48
- package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
- package/assets/skills/long-task-workflow/SKILL.md +71 -106
- package/assets/skills/long-task-workflow/agents/openai.yaml +1 -1
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +71 -69
- package/assets/skills/long-task-workflow/references/contract-authoring.md +110 -101
- package/assets/skills/long-task-workflow/references/evidence-design.md +99 -78
- package/assets/skills/long-task-workflow/references/source-authoring.md +90 -90
- package/assets/tools/validate_context.py +442 -442
- package/dist/commands/design-resource-recovery.d.ts +1 -0
- package/dist/commands/design-resource-recovery.js +152 -0
- package/dist/commands/design-resource.js +29 -3
- package/dist/commands/enable.js +2 -0
- package/dist/commands/index.js +2 -2
- package/dist/commands/long-task-revision.js +8 -7
- package/dist/commands/sync.js +2 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -0
- package/dist/lib/compact-authoring-support.d.ts +22 -0
- package/dist/lib/compact-authoring-support.js +143 -0
- package/dist/lib/compact-shared-structure-authoring.d.ts +5 -0
- package/dist/lib/compact-shared-structure-authoring.js +9 -0
- package/dist/lib/compact-shared-structure-types.d.ts +61 -0
- package/dist/lib/compact-shared-structure-types.js +1 -0
- package/dist/lib/compact-shared-structure-validation.d.ts +2 -0
- package/dist/lib/compact-shared-structure-validation.js +159 -0
- package/dist/lib/compact-shared-structures.d.ts +3 -0
- package/dist/lib/compact-shared-structures.js +204 -0
- package/dist/lib/design-resource-fact-enums.d.ts +4 -0
- package/dist/lib/design-resource-fact-enums.js +12 -0
- package/dist/lib/design-resource-fact-manifest-shape-evidence.js +2 -2
- package/dist/lib/design-resource-fact-policy.d.ts +2 -2
- package/dist/lib/design-resource-fact-types.d.ts +2 -2
- package/dist/lib/design-resource-handoff-bundle-draft.js +4 -2
- package/dist/lib/design-resource-handoff-input-types.d.ts +3 -0
- package/dist/lib/design-resource-handoff-parser.d.ts +2 -2
- package/dist/lib/design-resource-handoff-parser.js +2 -2
- package/dist/lib/design-resource-handoff-shape.d.ts +2 -0
- package/dist/lib/design-resource-handoff-shape.js +10 -0
- package/dist/lib/design-resource-handoff-snapshot.js +4 -0
- package/dist/lib/design-resource-handoff-validation.d.ts +4 -1
- package/dist/lib/design-resource-handoff-validation.js +11 -0
- package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +4 -2
- package/dist/lib/design-resource-reconciliation-codec.d.ts +2 -0
- package/dist/lib/design-resource-reconciliation-codec.js +174 -0
- package/dist/lib/design-resource-reconciliation-types.d.ts +62 -0
- package/dist/lib/design-resource-reconciliation-types.js +1 -0
- package/dist/lib/design-resource-reconciliation.d.ts +3 -0
- package/dist/lib/design-resource-reconciliation.js +224 -0
- package/dist/lib/design-resource-recovery-authority-policy.d.ts +8 -0
- package/dist/lib/design-resource-recovery-authority-policy.js +123 -0
- package/dist/lib/design-resource-recovery-catalog-resources.d.ts +6 -0
- package/dist/lib/design-resource-recovery-catalog-resources.js +121 -0
- package/dist/lib/design-resource-recovery-catalog-shape.d.ts +3 -0
- package/dist/lib/design-resource-recovery-catalog-shape.js +104 -0
- package/dist/lib/design-resource-recovery-catalog.d.ts +9 -0
- package/dist/lib/design-resource-recovery-catalog.js +103 -0
- package/dist/lib/design-resource-recovery-cleanup.d.ts +2 -0
- package/dist/lib/design-resource-recovery-cleanup.js +11 -0
- package/dist/lib/design-resource-recovery-codec-primitives.d.ts +19 -0
- package/dist/lib/design-resource-recovery-codec-primitives.js +92 -0
- package/dist/lib/design-resource-recovery-codec.d.ts +4 -0
- package/dist/lib/design-resource-recovery-codec.js +93 -0
- package/dist/lib/design-resource-recovery-current.d.ts +9 -0
- package/dist/lib/design-resource-recovery-current.js +41 -0
- package/dist/lib/design-resource-recovery-delta-policy.d.ts +5 -0
- package/dist/lib/design-resource-recovery-delta-policy.js +108 -0
- package/dist/lib/design-resource-recovery-files.d.ts +37 -0
- package/dist/lib/design-resource-recovery-files.js +204 -0
- package/dist/lib/design-resource-recovery-final-disposition-shape.d.ts +2 -0
- package/dist/lib/design-resource-recovery-final-disposition-shape.js +47 -0
- package/dist/lib/design-resource-recovery-patch-types.d.ts +54 -0
- package/dist/lib/design-resource-recovery-patch-types.js +1 -0
- package/dist/lib/design-resource-recovery-replay.d.ts +7 -0
- package/dist/lib/design-resource-recovery-replay.js +112 -0
- package/dist/lib/design-resource-recovery-repository-bindings.d.ts +9 -0
- package/dist/lib/design-resource-recovery-repository-bindings.js +49 -0
- package/dist/lib/design-resource-recovery-schema.d.ts +5 -0
- package/dist/lib/design-resource-recovery-schema.js +5 -0
- package/dist/lib/design-resource-recovery-shape.d.ts +10 -0
- package/dist/lib/design-resource-recovery-shape.js +184 -0
- package/dist/lib/design-resource-recovery-source-authority.d.ts +5 -0
- package/dist/lib/design-resource-recovery-source-authority.js +219 -0
- package/dist/lib/design-resource-recovery-text.d.ts +17 -0
- package/dist/lib/design-resource-recovery-text.js +186 -0
- package/dist/lib/design-resource-recovery-types.d.ts +197 -0
- package/dist/lib/design-resource-recovery-types.js +1 -0
- package/dist/lib/design-resource-recovery-writeback-policy.d.ts +5 -0
- package/dist/lib/design-resource-recovery-writeback-policy.js +326 -0
- package/dist/lib/design-resource-recovery-writeback-shape.d.ts +6 -0
- package/dist/lib/design-resource-recovery-writeback-shape.js +155 -0
- package/dist/lib/design-resource-recovery.d.ts +44 -0
- package/dist/lib/design-resource-recovery.js +216 -0
- package/dist/lib/design-resource-symbolic-applicability-authority.d.ts +7 -0
- package/dist/lib/design-resource-symbolic-applicability-authority.js +19 -0
- package/dist/lib/design-resource-symbolic-applicability-policy.d.ts +12 -0
- package/dist/lib/design-resource-symbolic-applicability-policy.js +79 -0
- package/dist/lib/design-resource-symbolic-applicability-profiles.d.ts +8 -0
- package/dist/lib/design-resource-symbolic-applicability-profiles.js +55 -0
- package/dist/lib/design-resource-symbolic-applicability-shape.d.ts +2 -0
- package/dist/lib/design-resource-symbolic-applicability-shape.js +76 -0
- package/dist/lib/design-resource-symbolic-applicability-validation.d.ts +7 -0
- package/dist/lib/design-resource-symbolic-applicability-validation.js +128 -0
- package/dist/lib/design-resource-symbolic-compilation.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-compilation.js +13 -0
- package/dist/lib/design-resource-symbolic-denotation.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-denotation.js +167 -0
- package/dist/lib/design-resource-symbolic-disposition-validation.d.ts +4 -0
- package/dist/lib/design-resource-symbolic-disposition-validation.js +28 -0
- package/dist/lib/design-resource-symbolic-fact-policy.d.ts +12 -0
- package/dist/lib/design-resource-symbolic-fact-policy.js +12 -0
- package/dist/lib/design-resource-symbolic-fact-shape.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-fact-shape.js +138 -0
- package/dist/lib/design-resource-symbolic-fact-types.d.ts +213 -0
- package/dist/lib/design-resource-symbolic-fact-types.js +1 -0
- package/dist/lib/design-resource-symbolic-fact-validation.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-fact-validation.js +86 -0
- package/dist/lib/design-resource-symbolic-indexes.d.ts +23 -0
- package/dist/lib/design-resource-symbolic-indexes.js +54 -0
- package/dist/lib/design-resource-symbolic-manifest-shape.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-manifest-shape.js +155 -0
- package/dist/lib/design-resource-symbolic-manifest-validation.d.ts +6 -0
- package/dist/lib/design-resource-symbolic-manifest-validation.js +132 -0
- package/dist/lib/design-resource-symbolic-noninterference-artifact.d.ts +33 -0
- package/dist/lib/design-resource-symbolic-noninterference-artifact.js +110 -0
- package/dist/lib/design-resource-symbolic-noninterference-equivalence.d.ts +3 -0
- package/dist/lib/design-resource-symbolic-noninterference-equivalence.js +77 -0
- package/dist/lib/design-resource-symbolic-noninterference-recompute.d.ts +4 -0
- package/dist/lib/design-resource-symbolic-noninterference-recompute.js +146 -0
- package/dist/lib/design-resource-symbolic-noninterference-scope.d.ts +7 -0
- package/dist/lib/design-resource-symbolic-noninterference-scope.js +49 -0
- package/dist/lib/design-resource-symbolic-noninterference-shape.d.ts +2 -0
- package/dist/lib/design-resource-symbolic-noninterference-shape.js +152 -0
- package/dist/lib/design-resource-symbolic-noninterference-types.d.ts +103 -0
- package/dist/lib/design-resource-symbolic-noninterference-types.js +1 -0
- package/dist/lib/design-resource-symbolic-noninterference-validation.d.ts +5 -0
- package/dist/lib/design-resource-symbolic-noninterference-validation.js +62 -0
- package/dist/lib/design-resource-symbolic-oracle-fingerprint.d.ts +1 -0
- package/dist/lib/design-resource-symbolic-oracle-fingerprint.js +47 -0
- package/dist/lib/design-resource-symbolic-predicate-shape.d.ts +6 -0
- package/dist/lib/design-resource-symbolic-predicate-shape.js +123 -0
- package/dist/lib/design-resource-symbolic-production-closure.d.ts +4 -0
- package/dist/lib/design-resource-symbolic-production-closure.js +144 -0
- package/dist/lib/design-resource-symbolic-proof-authority-validation.d.ts +10 -0
- package/dist/lib/design-resource-symbolic-proof-authority-validation.js +68 -0
- package/dist/lib/design-resource-symbolic-proof-validation.d.ts +10 -0
- package/dist/lib/design-resource-symbolic-proof-validation.js +89 -0
- package/dist/lib/design-resource-symbolic-region-validation.d.ts +19 -0
- package/dist/lib/design-resource-symbolic-region-validation.js +146 -0
- package/dist/lib/design-resource-symbolic-resource-validation.d.ts +5 -0
- package/dist/lib/design-resource-symbolic-resource-validation.js +90 -0
- package/dist/lib/design-resource-symbolic-rule-shape.d.ts +27 -0
- package/dist/lib/design-resource-symbolic-rule-shape.js +158 -0
- package/dist/lib/design-resource-symbolic-safety-validation.d.ts +6 -0
- package/dist/lib/design-resource-symbolic-safety-validation.js +29 -0
- package/dist/lib/design-resource-symbolic-source-ir-evaluation.d.ts +19 -0
- package/dist/lib/design-resource-symbolic-source-ir-evaluation.js +74 -0
- package/dist/lib/design-resource-symbolic-source-ir-evidence.d.ts +44 -0
- package/dist/lib/design-resource-symbolic-source-ir-evidence.js +88 -0
- package/dist/lib/design-resource-symbolic-source-ir-oracle.d.ts +13 -0
- package/dist/lib/design-resource-symbolic-source-ir-oracle.js +96 -0
- package/dist/lib/design-resource-symbolic-source-ir-proof.d.ts +14 -0
- package/dist/lib/design-resource-symbolic-source-ir-proof.js +98 -0
- package/dist/lib/design-resource-symbolic-source-ir-shape.d.ts +2 -0
- package/dist/lib/design-resource-symbolic-source-ir-shape.js +38 -0
- package/dist/lib/design-resource-symbolic-source-ir-types.d.ts +17 -0
- package/dist/lib/design-resource-symbolic-source-ir-types.js +2 -0
- package/dist/lib/design-resource-symbolic-static-dependency-validation.d.ts +2 -0
- package/dist/lib/design-resource-symbolic-static-dependency-validation.js +83 -0
- package/dist/lib/design-resource-symbolic-structural-closure-validation.d.ts +6 -0
- package/dist/lib/design-resource-symbolic-structural-closure-validation.js +79 -0
- package/dist/lib/design-resource-symbolic-validation-support.d.ts +29 -0
- package/dist/lib/design-resource-symbolic-validation-support.js +111 -0
- package/dist/lib/design-resource-v1-capacity-header.d.ts +8 -0
- package/dist/lib/design-resource-v1-capacity-header.js +231 -0
- package/dist/lib/design-resource-v1-capacity.d.ts +5 -0
- package/dist/lib/design-resource-v1-capacity.js +45 -0
- package/dist/lib/init.js +1 -0
- package/dist/lib/long-task-acceptance-shape.js +8 -2
- package/dist/lib/long-task-activation-validation.js +13 -3
- package/dist/lib/long-task-admitted-observation-records.d.ts +25 -0
- package/dist/lib/long-task-admitted-observation-records.js +40 -0
- package/dist/lib/long-task-admitted-observation.d.ts +93 -0
- package/dist/lib/long-task-admitted-observation.js +201 -0
- package/dist/lib/long-task-artifacts.d.ts +1 -0
- package/dist/lib/long-task-artifacts.js +1 -0
- package/dist/lib/long-task-authority-material-diff.js +1 -0
- package/dist/lib/long-task-authority-policy.d.ts +5 -0
- package/dist/lib/long-task-authority-policy.js +5 -0
- package/dist/lib/long-task-authority-revision-details.js +3 -1
- package/dist/lib/long-task-authority.js +2 -1
- package/dist/lib/long-task-check-execution-policy.js +5 -0
- package/dist/lib/long-task-check-runner.d.ts +2 -2
- package/dist/lib/long-task-check-runner.js +440 -23
- package/dist/lib/long-task-claims.d.ts +18 -0
- package/dist/lib/long-task-claims.js +35 -0
- package/dist/lib/long-task-codex-agent-profile.d.ts +42 -0
- package/dist/lib/long-task-codex-agent-profile.js +276 -0
- package/dist/lib/long-task-compact-authoring-projections.d.ts +12 -0
- package/dist/lib/long-task-compact-authoring-projections.js +67 -0
- package/dist/lib/long-task-compact-authoring.d.ts +3 -0
- package/dist/lib/long-task-compact-authoring.js +173 -0
- package/dist/lib/long-task-compact-carrier.d.ts +7 -0
- package/dist/lib/long-task-compact-carrier.js +132 -0
- package/dist/lib/long-task-compact-parser.d.ts +14 -0
- package/dist/lib/long-task-compact-parser.js +123 -0
- package/dist/lib/long-task-compact-primitives.d.ts +22 -0
- package/dist/lib/long-task-compact-primitives.js +132 -0
- package/dist/lib/long-task-compact-projections.d.ts +4 -0
- package/dist/lib/long-task-compact-projections.js +153 -0
- package/dist/lib/long-task-compact-structure-targets.d.ts +2 -0
- package/dist/lib/long-task-compact-structure-targets.js +91 -0
- package/dist/lib/long-task-conformance-policy.js +3 -1
- package/dist/lib/long-task-counterfactual-claim-policy.d.ts +3 -4
- package/dist/lib/long-task-counterfactual-claim-policy.js +11 -3
- package/dist/lib/long-task-counterfactual-sandbox.d.ts +1 -1
- package/dist/lib/long-task-counterfactual-sandbox.js +8 -5
- package/dist/lib/long-task-counterfactual-types.d.ts +2 -0
- package/dist/lib/long-task-delivery-compiler.js +2 -0
- package/dist/lib/long-task-delivery-parser.d.ts +1 -0
- package/dist/lib/long-task-delivery-parser.js +38 -6
- package/dist/lib/long-task-design-resource-handoff.d.ts +2 -1
- package/dist/lib/long-task-design-resource-handoff.js +71 -11
- package/dist/lib/long-task-design-resource-method-binding.d.ts +8 -1
- package/dist/lib/long-task-design-resource-method-binding.js +150 -0
- package/dist/lib/long-task-evidence-capability-codec.js +256 -34
- package/dist/lib/long-task-evidence-capability-policy.d.ts +3 -2
- package/dist/lib/long-task-evidence-capability-policy.js +142 -8
- package/dist/lib/long-task-evidence-capability-runtime.d.ts +5 -2
- package/dist/lib/long-task-evidence-capability-runtime.js +420 -68
- package/dist/lib/long-task-evidence-capability-types.d.ts +70 -2
- package/dist/lib/long-task-evidence-sensitivity-policy.d.ts +9 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.js +31 -1
- package/dist/lib/long-task-evidence-v2.d.ts +4 -4
- package/dist/lib/long-task-evidence-v2.js +322 -44
- package/dist/lib/long-task-exact-comparison.d.ts +16 -0
- package/dist/lib/long-task-exact-comparison.js +28 -0
- package/dist/lib/long-task-execution-observation.d.ts +24 -0
- package/dist/lib/long-task-execution-observation.js +332 -0
- package/dist/lib/long-task-explain-acceptance-link.d.ts +4 -0
- package/dist/lib/long-task-explain-acceptance-link.js +4 -0
- package/dist/lib/long-task-explain-claim-links.d.ts +2 -0
- package/dist/lib/long-task-explain-claim-links.js +2 -0
- package/dist/lib/long-task-explain-source-links.d.ts +6 -0
- package/dist/lib/long-task-final-v2.js +7 -4
- package/dist/lib/long-task-hook-install.d.ts +19 -2
- package/dist/lib/long-task-hook-install.js +288 -91
- package/dist/lib/long-task-json-pointer-observation.d.ts +59 -0
- package/dist/lib/long-task-json-pointer-observation.js +184 -0
- package/dist/lib/long-task-observation-artifact.d.ts +8 -0
- package/dist/lib/long-task-observation-artifact.js +58 -0
- package/dist/lib/long-task-observation-authority.d.ts +17 -0
- package/dist/lib/long-task-observation-authority.js +348 -0
- package/dist/lib/long-task-paths.js +1 -1
- package/dist/lib/long-task-playwright-capability-records.d.ts +2 -0
- package/dist/lib/long-task-playwright-capability-records.js +74 -2
- package/dist/lib/long-task-process-observation.d.ts +6 -0
- package/dist/lib/long-task-process-observation.js +117 -0
- package/dist/lib/long-task-process-runtime-closure.d.ts +13 -0
- package/dist/lib/long-task-process-runtime-closure.js +175 -0
- package/dist/lib/long-task-progress.js +2 -0
- package/dist/lib/long-task-protected-files.d.ts +1 -1
- package/dist/lib/long-task-protected-files.js +1 -30
- package/dist/lib/long-task-risk.js +8 -3
- package/dist/lib/long-task-root-shape.js +10 -1
- package/dist/lib/long-task-runner-environment.d.ts +1 -1
- package/dist/lib/long-task-runner-environment.js +4 -4
- package/dist/lib/long-task-runner-freeze.d.ts +4 -2
- package/dist/lib/long-task-runner-freeze.js +130 -28
- package/dist/lib/long-task-runtime-types.d.ts +111 -0
- package/dist/lib/long-task-scoped-binding.d.ts +13 -0
- package/dist/lib/long-task-scoped-binding.js +11 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +2 -1
- package/dist/lib/long-task-semantic-fact-binding-types.d.ts +8 -0
- package/dist/lib/long-task-semantic-fact-closure.js +4 -1
- package/dist/lib/long-task-semantic-fact-contract-closure.d.ts +1 -1
- package/dist/lib/long-task-semantic-fact-contract-closure.js +18 -6
- package/dist/lib/long-task-semantic-fact-contract-facts.d.ts +1 -1
- package/dist/lib/long-task-semantic-fact-contract-facts.js +4 -1
- package/dist/lib/long-task-semantic-fact-contract-proofs.d.ts +1 -1
- package/dist/lib/long-task-semantic-fact-contract-proofs.js +12 -3
- package/dist/lib/long-task-semantic-fact-evidence.d.ts +8 -4
- package/dist/lib/long-task-semantic-fact-evidence.js +103 -43
- package/dist/lib/long-task-semantic-fact-shape.js +17 -6
- package/dist/lib/long-task-shape-primitives.d.ts +1 -1
- package/dist/lib/long-task-shape-primitives.js +1 -0
- package/dist/lib/long-task-source-claim-validation.js +4 -1
- package/dist/lib/long-task-source-item-parser.d.ts +2 -2
- package/dist/lib/long-task-source-item-parser.js +20 -11
- package/dist/lib/long-task-source-target-continuity.d.ts +2 -2
- package/dist/lib/long-task-source-target-continuity.js +35 -2
- package/dist/lib/long-task-source-target-index.d.ts +3 -0
- package/dist/lib/long-task-source-target-index.js +19 -0
- package/dist/lib/long-task-stage-policy.js +10 -4
- package/dist/lib/long-task-static-observation-freeze.d.ts +83 -0
- package/dist/lib/long-task-static-observation-freeze.js +428 -0
- package/dist/lib/long-task-status-projection.js +5 -1
- package/dist/lib/long-task-target-policy.d.ts +1 -1
- package/dist/lib/long-task-target-policy.js +3 -0
- package/dist/lib/long-task-ui-design-policy.js +64 -4
- package/dist/lib/long-task-ui-surface-shape.js +195 -0
- package/dist/lib/long-task-ui-surface-types.d.ts +53 -0
- package/dist/lib/long-task-verifier-dependency-closure.js +7 -3
- package/dist/lib/long-task-verifier-v2.js +70 -9
- package/dist/lib/long-task-worker-selection.d.ts +2 -0
- package/dist/lib/long-task-worker-selection.js +7 -0
- package/dist/lib/long-task-workspace-scope.js +3 -1
- package/dist/lib/long-task-workspace.d.ts +1 -1
- package/dist/lib/long-task-workspace.js +12 -13
- package/dist/lib/migrations.js +58 -0
- package/dist/lib/profiles.js +0 -1
- package/dist/lib/repository-path-safety.d.ts +14 -0
- package/dist/lib/repository-path-safety.js +126 -0
- package/dist/lib/semantic-fact-compact-authoring.d.ts +2 -0
- package/dist/lib/semantic-fact-compact-authoring.js +160 -0
- package/dist/lib/semantic-fact-compact-capacity.d.ts +9 -0
- package/dist/lib/semantic-fact-compact-capacity.js +40 -0
- package/dist/lib/semantic-fact-compact-carrier.d.ts +16 -0
- package/dist/lib/semantic-fact-compact-carrier.js +146 -0
- package/dist/lib/semantic-fact-compact-parser.d.ts +17 -0
- package/dist/lib/semantic-fact-compact-parser.js +168 -0
- package/dist/lib/semantic-fact-compact-revision.d.ts +11 -0
- package/dist/lib/semantic-fact-compact-revision.js +64 -0
- package/dist/lib/semantic-fact-compact-support.d.ts +23 -0
- package/dist/lib/semantic-fact-compact-support.js +159 -0
- package/dist/lib/semantic-fact-policy-census.d.ts +1 -0
- package/dist/lib/semantic-fact-policy-census.js +43 -0
- package/dist/lib/semantic-fact-proof-shape.d.ts +1 -1
- package/dist/lib/semantic-fact-property-shape.d.ts +1 -1
- package/dist/lib/semantic-fact-source-parser.d.ts +5 -0
- package/dist/lib/semantic-fact-source-parser.js +47 -6
- package/dist/lib/structural-closure-cost.d.ts +79 -0
- package/dist/lib/structural-closure-cost.js +91 -0
- package/dist/lib/symbolic-denotation-dag-builder.d.ts +25 -0
- package/dist/lib/symbolic-denotation-dag-builder.js +176 -0
- package/dist/lib/symbolic-denotation-domain-validation.d.ts +3 -0
- package/dist/lib/symbolic-denotation-domain-validation.js +56 -0
- package/dist/lib/symbolic-denotation-engine.d.ts +32 -0
- package/dist/lib/symbolic-denotation-engine.js +140 -0
- package/dist/lib/symbolic-denotation-public.d.ts +11 -0
- package/dist/lib/symbolic-denotation-public.js +12 -0
- package/dist/lib/symbolic-denotation-runtime.d.ts +20 -0
- package/dist/lib/symbolic-denotation-runtime.js +90 -0
- package/dist/lib/symbolic-denotation-support.d.ts +11 -0
- package/dist/lib/symbolic-denotation-support.js +49 -0
- package/dist/lib/symbolic-denotation-types.d.ts +133 -0
- package/dist/lib/symbolic-denotation-types.js +18 -0
- package/dist/lib/symbolic-denotation-validation.d.ts +6 -0
- package/dist/lib/symbolic-denotation-validation.js +126 -0
- package/dist/lib/sync-engine.d.ts +1 -0
- package/dist/lib/sync-engine.js +4 -1
- package/dist/lib/upgrade.js +1 -0
- package/dist/long-task-hook.js +40 -1
- package/dist/public-types.d.ts +8 -0
- package/dist/public-types.js +1 -0
- package/dist/schemas/design-resource-symbolic-noninterference-artifact-v2.schema.json +289 -0
- package/dist/schemas/design-resource-symbolic-source-ir-v1.schema.json +130 -0
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +435 -5
- package/migrations/README.md +92 -15
- package/package.json +2 -2
- package/source-mappings.yaml +28 -25
- package/assets/skills/source-plan-authoring/SKILL.md +0 -14
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { pathExists } from "./fs.js";
|
|
5
5
|
const MANAGED_STATUS = "Tiny Context long-task live authority gate";
|
|
6
|
+
const PRE_TOOL_USE_MATCHER = "^(spawn_agent|Agent)$";
|
|
7
|
+
const LONG_TASK_IMPLEMENTATION_AGENT_MATCHER = "^long_task_implementation$";
|
|
8
|
+
const MANAGED_HOOK_EVENTS = [
|
|
9
|
+
"PreToolUse",
|
|
10
|
+
"SessionStart",
|
|
11
|
+
"PostCompact",
|
|
12
|
+
"Stop",
|
|
13
|
+
"SubagentStart",
|
|
14
|
+
];
|
|
15
|
+
const MANAGED_MATCHERS = new Set([
|
|
16
|
+
PRE_TOOL_USE_MATCHER,
|
|
17
|
+
LONG_TASK_IMPLEMENTATION_AGENT_MATCHER,
|
|
18
|
+
]);
|
|
6
19
|
const LEGACY_MANAGED_STATUSES = new Set([
|
|
7
20
|
"Tiny Context long-task live authority gate",
|
|
8
21
|
"Tiny Context long-task authority gate",
|
|
@@ -17,94 +30,85 @@ const LEGACY_REPO_LOCAL_COMMANDS = new Set([
|
|
|
17
30
|
"node .codex\\hooks\\long-task-hook.mjs",
|
|
18
31
|
'node ".codex\\hooks\\long-task-hook.mjs"',
|
|
19
32
|
]);
|
|
20
|
-
export
|
|
33
|
+
export const LONG_TASK_HOOK_TRUST_REVIEW_NOTICE = "Codex Hook review required: open /hooks and trust the current Tiny Context project Hook before relying on PreToolUse, SubagentStart, SessionStart or Stop behavior. Tiny Context cannot observe or persist Codex Hook trust.";
|
|
34
|
+
const DEFAULT_FILE_OPERATIONS = {
|
|
35
|
+
lstat: (target) => fs.lstat(target),
|
|
36
|
+
readFile: (target, encoding) => fs.readFile(target, encoding),
|
|
37
|
+
mkdir: (target, options) => fs.mkdir(target, options),
|
|
38
|
+
writeFile: (target, content, options) => fs.writeFile(target, content, options),
|
|
39
|
+
rename: (source, destination) => fs.rename(source, destination),
|
|
40
|
+
rm: (target, options) => fs.rm(target, options),
|
|
41
|
+
randomId: () => randomUUID(),
|
|
42
|
+
};
|
|
43
|
+
export async function installLongTaskHooks(projectRoot, report, fileOperations = {}) {
|
|
44
|
+
const operations = operationsWith(fileOperations);
|
|
21
45
|
const packageRoot = fileURLToPath(new URL("../../", import.meta.url));
|
|
22
46
|
const entry = path.join(packageRoot, "dist", "long-task-hook.js");
|
|
23
|
-
|
|
47
|
+
const entryStatus = await lstatOrNull(entry, operations);
|
|
48
|
+
if (!entryStatus || entryStatus.isSymbolicLink() || !entryStatus.isFile()) {
|
|
24
49
|
report.blocked.push("package-owned dist/long-task-hook.js is missing");
|
|
25
50
|
return;
|
|
26
51
|
}
|
|
27
|
-
const legacyScript = path.join(projectRoot, ".codex", "hooks", "long-task-hook.mjs");
|
|
28
|
-
if (await pathExists(legacyScript)) {
|
|
29
|
-
await rm(legacyScript, { force: true });
|
|
30
|
-
report.changed.push(".codex/hooks/long-task-hook.mjs");
|
|
31
|
-
}
|
|
32
|
-
const command = packageOwnedCommand(entry);
|
|
33
52
|
const config = path.join(projectRoot, ".codex", "hooks.json");
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
const legacyScript = path.join(projectRoot, ".codex", "hooks", "long-task-hook.mjs");
|
|
54
|
+
try {
|
|
55
|
+
const legacy = await inspectLegacyScript(projectRoot, operations);
|
|
56
|
+
const loaded = await readHookConfig(projectRoot, true, operations);
|
|
57
|
+
const command = packageOwnedCommand(entry);
|
|
58
|
+
const packageHooksWereCurrent = packageHooksAreCurrent(loaded.root, command);
|
|
59
|
+
const next = mergeManagedHooks(loaded.root, command);
|
|
60
|
+
const content = `${JSON.stringify(next, null, 2)}\n`;
|
|
61
|
+
if (loaded.snapshot.kind === "regular" &&
|
|
62
|
+
loaded.snapshot.content === content) {
|
|
63
|
+
report.skipped.push(".codex/hooks.json");
|
|
38
64
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
else {
|
|
66
|
+
await publishHookConfig(config, loaded.snapshot, content, operations);
|
|
67
|
+
report.changed.push(".codex/hooks.json");
|
|
68
|
+
if (!packageHooksWereCurrent)
|
|
69
|
+
addNotice(report);
|
|
42
70
|
}
|
|
71
|
+
await removeLegacyScriptIfPresent(projectRoot, legacyScript, legacy, report, operations);
|
|
43
72
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const event of ["SessionStart", "PostCompact", "Stop"]) {
|
|
47
|
-
const groups = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
48
|
-
const cleaned = removeManagedHookEntries(groups, command);
|
|
49
|
-
cleaned.groups.push({
|
|
50
|
-
hooks: [
|
|
51
|
-
{
|
|
52
|
-
type: "command",
|
|
53
|
-
command,
|
|
54
|
-
commandWindows: command,
|
|
55
|
-
timeout: event === "Stop" ? 3600 : 10,
|
|
56
|
-
statusMessage: MANAGED_STATUS,
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
});
|
|
60
|
-
hooks[event] = cleaned.groups;
|
|
73
|
+
catch (error) {
|
|
74
|
+
report.blocked.push(`.codex/hooks.json: ${message(error)}`);
|
|
61
75
|
}
|
|
62
|
-
if (await writeIfChanged(config, `${JSON.stringify(root, null, 2)}\n`))
|
|
63
|
-
report.changed.push(".codex/hooks.json");
|
|
64
|
-
else
|
|
65
|
-
report.skipped.push(".codex/hooks.json");
|
|
66
76
|
}
|
|
67
|
-
export async function uninstallLongTaskHooks(projectRoot, report) {
|
|
77
|
+
export async function uninstallLongTaskHooks(projectRoot, report, fileOperations = {}) {
|
|
78
|
+
const operations = operationsWith(fileOperations);
|
|
68
79
|
const packageRoot = fileURLToPath(new URL("../../", import.meta.url));
|
|
69
80
|
const command = packageOwnedCommand(path.join(packageRoot, "dist", "long-task-hook.js"));
|
|
70
|
-
const legacyScript = path.join(projectRoot, ".codex", "hooks", "long-task-hook.mjs");
|
|
71
|
-
if (await pathExists(legacyScript)) {
|
|
72
|
-
await rm(legacyScript, { force: true });
|
|
73
|
-
report.changed.push(".codex/hooks/long-task-hook.mjs");
|
|
74
|
-
}
|
|
75
81
|
const config = path.join(projectRoot, ".codex", "hooks.json");
|
|
76
|
-
|
|
77
|
-
return;
|
|
78
|
-
let root;
|
|
82
|
+
const legacyScript = path.join(projectRoot, ".codex", "hooks", "long-task-hook.mjs");
|
|
79
83
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
const legacy = await inspectLegacyScript(projectRoot, operations);
|
|
85
|
+
const loaded = await readHookConfig(projectRoot, false, operations);
|
|
86
|
+
let removed = 0;
|
|
87
|
+
const hooks = hookMap(loaded.root);
|
|
88
|
+
for (const event of MANAGED_HOOK_EVENTS) {
|
|
89
|
+
if (!Array.isArray(hooks[event]))
|
|
90
|
+
continue;
|
|
91
|
+
const cleaned = removeManagedHookEntries(hooks[event], command);
|
|
92
|
+
removed += cleaned.removed;
|
|
93
|
+
if (cleaned.groups.length)
|
|
94
|
+
hooks[event] = cleaned.groups;
|
|
95
|
+
else
|
|
96
|
+
delete hooks[event];
|
|
97
|
+
}
|
|
98
|
+
if (removed > 0 && loaded.snapshot.kind === "regular") {
|
|
99
|
+
loaded.root.hooks = hooks;
|
|
100
|
+
if (Object.keys(hooks).length === 0 &&
|
|
101
|
+
Object.keys(loaded.root).length === 1)
|
|
102
|
+
await removeHookConfig(config, loaded.snapshot, operations);
|
|
103
|
+
else
|
|
104
|
+
await publishHookConfig(config, loaded.snapshot, `${JSON.stringify(loaded.root, null, 2)}\n`, operations);
|
|
105
|
+
report.changed.push(".codex/hooks.json");
|
|
106
|
+
}
|
|
107
|
+
await removeLegacyScriptIfPresent(projectRoot, legacyScript, legacy, report, operations);
|
|
85
108
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
for (const event of ["SessionStart", "PostCompact", "Stop"]) {
|
|
89
|
-
if (!Array.isArray(hooks[event]))
|
|
90
|
-
continue;
|
|
91
|
-
const cleaned = removeManagedHookEntries(hooks[event], command);
|
|
92
|
-
if (cleaned.removed === 0)
|
|
93
|
-
continue;
|
|
94
|
-
changed = true;
|
|
95
|
-
if (cleaned.groups.length)
|
|
96
|
-
hooks[event] = cleaned.groups;
|
|
97
|
-
else
|
|
98
|
-
delete hooks[event];
|
|
109
|
+
catch (error) {
|
|
110
|
+
report.blocked.push(`.codex/hooks.json: ${message(error)}`);
|
|
99
111
|
}
|
|
100
|
-
if (!changed)
|
|
101
|
-
return;
|
|
102
|
-
root.hooks = hooks;
|
|
103
|
-
if (Object.keys(hooks).length === 0 && Object.keys(root).length === 1)
|
|
104
|
-
await rm(config, { force: true });
|
|
105
|
-
else
|
|
106
|
-
await writeIfChanged(config, `${JSON.stringify(root, null, 2)}\n`);
|
|
107
|
-
report.changed.push(".codex/hooks.json");
|
|
108
112
|
}
|
|
109
113
|
export function packageOwnedCommand(entry) {
|
|
110
114
|
return `node "${path.resolve(entry).replace(/"/gu, '\\"')}"`;
|
|
@@ -129,8 +133,13 @@ export function removeManagedHookEntries(groups, currentPackageCommand = "") {
|
|
|
129
133
|
retained.push({ ...groupValue, hooks });
|
|
130
134
|
continue;
|
|
131
135
|
}
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
const keys = Object.keys(groupValue);
|
|
137
|
+
if (keys.every((key) => key === "hooks"))
|
|
138
|
+
continue;
|
|
139
|
+
if (MANAGED_MATCHERS.has(String(groupValue.matcher ?? "")) &&
|
|
140
|
+
keys.every((key) => key === "matcher" || key === "hooks"))
|
|
141
|
+
continue;
|
|
142
|
+
retained.push({ ...groupValue, hooks });
|
|
134
143
|
}
|
|
135
144
|
return { groups: retained, removed };
|
|
136
145
|
}
|
|
@@ -141,8 +150,7 @@ export function isManagedHookEntry(entry, currentPackageCommand = "") {
|
|
|
141
150
|
const commands = [row.command, row.commandWindows]
|
|
142
151
|
.filter((value) => typeof value === "string")
|
|
143
152
|
.map((value) => value.trim());
|
|
144
|
-
|
|
145
|
-
if (repoLocal)
|
|
153
|
+
if (commands.some((command) => LEGACY_REPO_LOCAL_COMMANDS.has(command)))
|
|
146
154
|
return true;
|
|
147
155
|
const status = String(row.statusMessage ?? "");
|
|
148
156
|
if (!LEGACY_MANAGED_STATUSES.has(status))
|
|
@@ -150,6 +158,201 @@ export function isManagedHookEntry(entry, currentPackageCommand = "") {
|
|
|
150
158
|
return commands.some((command) => (Boolean(currentPackageCommand) && command === currentPackageCommand) ||
|
|
151
159
|
isHistoricalPackageOwnedCommand(command));
|
|
152
160
|
}
|
|
161
|
+
function mergeManagedHooks(root, command) {
|
|
162
|
+
const hooks = hookMap(root);
|
|
163
|
+
root.hooks = hooks;
|
|
164
|
+
for (const event of MANAGED_HOOK_EVENTS) {
|
|
165
|
+
const current = hooks[event];
|
|
166
|
+
if (current !== undefined && !Array.isArray(current))
|
|
167
|
+
throw new Error(`hook_event_not_array:${event}`);
|
|
168
|
+
const cleaned = removeManagedHookEntries(current ?? [], command);
|
|
169
|
+
cleaned.groups.push(managedHookGroup(event, command));
|
|
170
|
+
hooks[event] = cleaned.groups;
|
|
171
|
+
}
|
|
172
|
+
return root;
|
|
173
|
+
}
|
|
174
|
+
function managedHookGroup(event, command) {
|
|
175
|
+
return {
|
|
176
|
+
...(event === "PreToolUse" ? { matcher: PRE_TOOL_USE_MATCHER } : {}),
|
|
177
|
+
...(event === "SubagentStart"
|
|
178
|
+
? { matcher: LONG_TASK_IMPLEMENTATION_AGENT_MATCHER }
|
|
179
|
+
: {}),
|
|
180
|
+
hooks: [
|
|
181
|
+
{
|
|
182
|
+
type: "command",
|
|
183
|
+
command,
|
|
184
|
+
commandWindows: command,
|
|
185
|
+
timeout: event === "Stop" ? 3600 : 10,
|
|
186
|
+
statusMessage: MANAGED_STATUS,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function packageHooksAreCurrent(root, command) {
|
|
192
|
+
let hooks;
|
|
193
|
+
try {
|
|
194
|
+
hooks = hookMap(root);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
return MANAGED_HOOK_EVENTS.every((event) => {
|
|
200
|
+
const groups = hooks[event];
|
|
201
|
+
if (!Array.isArray(groups))
|
|
202
|
+
return false;
|
|
203
|
+
const matches = [];
|
|
204
|
+
for (const groupValue of groups) {
|
|
205
|
+
if (!isObject(groupValue) || !Array.isArray(groupValue.hooks))
|
|
206
|
+
continue;
|
|
207
|
+
for (const entryValue of groupValue.hooks) {
|
|
208
|
+
if (!isManagedHookEntry(entryValue, command))
|
|
209
|
+
continue;
|
|
210
|
+
matches.push({ group: groupValue, entry: object(entryValue) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (matches.length !== 1)
|
|
214
|
+
return false;
|
|
215
|
+
const [{ group, entry }] = matches;
|
|
216
|
+
const expectedMatcher = event === "PreToolUse"
|
|
217
|
+
? PRE_TOOL_USE_MATCHER
|
|
218
|
+
: event === "SubagentStart"
|
|
219
|
+
? LONG_TASK_IMPLEMENTATION_AGENT_MATCHER
|
|
220
|
+
: undefined;
|
|
221
|
+
return (entry.type === "command" &&
|
|
222
|
+
entry.command === command &&
|
|
223
|
+
entry.commandWindows === command &&
|
|
224
|
+
entry.timeout === (event === "Stop" ? 3600 : 10) &&
|
|
225
|
+
entry.statusMessage === MANAGED_STATUS &&
|
|
226
|
+
(expectedMatcher === undefined
|
|
227
|
+
? !Object.hasOwn(group, "matcher")
|
|
228
|
+
: group.matcher === expectedMatcher));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
async function readHookConfig(projectRoot, createDirectory, operations) {
|
|
232
|
+
const directory = await inspectCodexDirectory(projectRoot, createDirectory, operations);
|
|
233
|
+
if (directory === "absent")
|
|
234
|
+
return { root: {}, snapshot: { kind: "absent" } };
|
|
235
|
+
const config = path.join(projectRoot, ".codex", "hooks.json");
|
|
236
|
+
const status = await lstatOrNull(config, operations);
|
|
237
|
+
if (!status)
|
|
238
|
+
return { root: {}, snapshot: { kind: "absent" } };
|
|
239
|
+
if (status.isSymbolicLink())
|
|
240
|
+
throw new Error("destination_symlink_or_junction");
|
|
241
|
+
if (!status.isFile())
|
|
242
|
+
throw new Error("destination_not_regular_file");
|
|
243
|
+
const content = await operations.readFile(config, "utf8");
|
|
244
|
+
let decoded;
|
|
245
|
+
try {
|
|
246
|
+
decoded = JSON.parse(content);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
throw new Error("invalid JSON");
|
|
250
|
+
}
|
|
251
|
+
if (!isObject(decoded))
|
|
252
|
+
throw new Error("root_not_object");
|
|
253
|
+
hookMap(decoded);
|
|
254
|
+
return { root: decoded, snapshot: { kind: "regular", content } };
|
|
255
|
+
}
|
|
256
|
+
function hookMap(root) {
|
|
257
|
+
if (root.hooks === undefined)
|
|
258
|
+
return {};
|
|
259
|
+
if (!isObject(root.hooks))
|
|
260
|
+
throw new Error("hooks_not_object");
|
|
261
|
+
return root.hooks;
|
|
262
|
+
}
|
|
263
|
+
async function inspectCodexDirectory(projectRoot, create, operations) {
|
|
264
|
+
const directory = path.join(projectRoot, ".codex");
|
|
265
|
+
let status = await lstatOrNull(directory, operations);
|
|
266
|
+
if (!status && create) {
|
|
267
|
+
await operations.mkdir(directory, { recursive: true });
|
|
268
|
+
status = await lstatOrNull(directory, operations);
|
|
269
|
+
}
|
|
270
|
+
if (!status)
|
|
271
|
+
return "absent";
|
|
272
|
+
if (status.isSymbolicLink())
|
|
273
|
+
throw new Error("parent_symlink_or_junction:.codex");
|
|
274
|
+
if (!status.isDirectory())
|
|
275
|
+
throw new Error("parent_not_directory:.codex");
|
|
276
|
+
return "regular";
|
|
277
|
+
}
|
|
278
|
+
async function inspectLegacyScript(projectRoot, operations) {
|
|
279
|
+
if ((await inspectCodexDirectory(projectRoot, false, operations)) === "absent")
|
|
280
|
+
return { kind: "absent" };
|
|
281
|
+
const parent = path.join(projectRoot, ".codex", "hooks");
|
|
282
|
+
const parentStatus = await lstatOrNull(parent, operations);
|
|
283
|
+
if (!parentStatus)
|
|
284
|
+
return { kind: "absent" };
|
|
285
|
+
if (parentStatus.isSymbolicLink())
|
|
286
|
+
throw new Error("legacy_parent_symlink_or_junction");
|
|
287
|
+
if (!parentStatus.isDirectory())
|
|
288
|
+
throw new Error("legacy_parent_not_directory");
|
|
289
|
+
const target = path.join(parent, "long-task-hook.mjs");
|
|
290
|
+
const targetStatus = await lstatOrNull(target, operations);
|
|
291
|
+
if (!targetStatus)
|
|
292
|
+
return { kind: "absent" };
|
|
293
|
+
if (targetStatus.isSymbolicLink())
|
|
294
|
+
throw new Error("legacy_hook_symlink_or_junction");
|
|
295
|
+
if (!targetStatus.isFile())
|
|
296
|
+
throw new Error("legacy_hook_not_regular_file");
|
|
297
|
+
return { kind: "regular" };
|
|
298
|
+
}
|
|
299
|
+
async function removeLegacyScriptIfPresent(projectRoot, target, initial, report, operations) {
|
|
300
|
+
if (initial.kind === "absent")
|
|
301
|
+
return;
|
|
302
|
+
const current = await inspectLegacyScript(projectRoot, operations);
|
|
303
|
+
if (current.kind !== "regular")
|
|
304
|
+
throw new Error("legacy_hook_changed_before_delete");
|
|
305
|
+
await operations.rm(target, { force: true });
|
|
306
|
+
report.changed.push(".codex/hooks/long-task-hook.mjs");
|
|
307
|
+
}
|
|
308
|
+
async function publishHookConfig(target, initial, content, operations) {
|
|
309
|
+
const temp = `${target}.tmp-${process.pid}-${operations.randomId()}`;
|
|
310
|
+
let renamed = false;
|
|
311
|
+
try {
|
|
312
|
+
await operations.writeFile(temp, content, { flag: "wx" });
|
|
313
|
+
await assertTargetUnchanged(target, initial, operations);
|
|
314
|
+
await operations.rename(temp, target);
|
|
315
|
+
renamed = true;
|
|
316
|
+
}
|
|
317
|
+
finally {
|
|
318
|
+
if (!renamed)
|
|
319
|
+
await operations.rm(temp, { force: true }).catch(() => { });
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async function removeHookConfig(target, initial, operations) {
|
|
323
|
+
await assertTargetUnchanged(target, initial, operations);
|
|
324
|
+
await operations.rm(target, { force: true });
|
|
325
|
+
}
|
|
326
|
+
async function assertTargetUnchanged(target, initial, operations) {
|
|
327
|
+
const projectRoot = path.dirname(path.dirname(target));
|
|
328
|
+
await inspectCodexDirectory(projectRoot, false, operations);
|
|
329
|
+
const status = await lstatOrNull(target, operations);
|
|
330
|
+
if (initial.kind === "absent") {
|
|
331
|
+
if (status)
|
|
332
|
+
throw new Error("concurrent change: destination appeared");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (!status || status.isSymbolicLink() || !status.isFile())
|
|
336
|
+
throw new Error("concurrent change: destination type changed");
|
|
337
|
+
if ((await operations.readFile(target, "utf8")) !== initial.content)
|
|
338
|
+
throw new Error("concurrent change: destination content changed");
|
|
339
|
+
}
|
|
340
|
+
function addNotice(report) {
|
|
341
|
+
(report.notices ??= []).push(LONG_TASK_HOOK_TRUST_REVIEW_NOTICE);
|
|
342
|
+
}
|
|
343
|
+
function operationsWith(overrides) {
|
|
344
|
+
return { ...DEFAULT_FILE_OPERATIONS, ...overrides };
|
|
345
|
+
}
|
|
346
|
+
async function lstatOrNull(target, operations) {
|
|
347
|
+
try {
|
|
348
|
+
return await operations.lstat(target);
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
if (code(error) === "ENOENT")
|
|
352
|
+
return null;
|
|
353
|
+
throw error;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
153
356
|
function isHistoricalPackageOwnedCommand(command) {
|
|
154
357
|
const match = /^node "([^"\r\n]+)"$/u.exec(command);
|
|
155
358
|
if (!match)
|
|
@@ -163,22 +366,16 @@ function isHistoricalPackageOwnedCommand(command) {
|
|
|
163
366
|
return (/\/node_modules\/project-tiny-context-harness\/dist\/long-task-hook\.js$/u.test(normalized) || /\/packages\/ty-context\/dist\/long-task-hook\.js$/u.test(normalized));
|
|
164
367
|
}
|
|
165
368
|
function object(value) {
|
|
166
|
-
return value
|
|
167
|
-
? value
|
|
168
|
-
: {};
|
|
369
|
+
return isObject(value) ? value : {};
|
|
169
370
|
}
|
|
170
371
|
function isObject(value) {
|
|
171
372
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
172
373
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const temp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
181
|
-
await writeFile(temp, content, { flag: "wx" });
|
|
182
|
-
await rename(temp, file);
|
|
183
|
-
return true;
|
|
374
|
+
function code(error) {
|
|
375
|
+
return typeof error === "object" && error !== null && "code" in error
|
|
376
|
+
? String(error.code)
|
|
377
|
+
: "";
|
|
378
|
+
}
|
|
379
|
+
function message(error) {
|
|
380
|
+
return error instanceof Error ? error.message : String(error);
|
|
184
381
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export declare const JSON_POINTER_EXACT_CAPABILITY = "json-pointer-exact-v1";
|
|
2
|
+
export declare const JSON_POINTER_EXACT_ORACLE_IDENTITY = "ty-context-json-pointer-exact";
|
|
3
|
+
export declare const JSON_POINTER_EXACT_ORACLE_VERSION = "1.0.0";
|
|
4
|
+
export declare const JSON_POINTER_EXACT_METHODS: readonly ["exact_value", "content", "component_state"];
|
|
5
|
+
export declare const JSON_POINTER_EXACT_LIMITS: Readonly<{
|
|
6
|
+
max_file_bytes: 1048576;
|
|
7
|
+
max_depth: 64;
|
|
8
|
+
max_pointer_bytes: 4096;
|
|
9
|
+
max_pointer_segments: 128;
|
|
10
|
+
max_canonical_value_bytes: 262144;
|
|
11
|
+
max_artifacts_per_check: 256;
|
|
12
|
+
max_total_artifact_bytes: 16777216;
|
|
13
|
+
}>;
|
|
14
|
+
export declare const JSON_POINTER_EXACT_SPEC_SHA256: string;
|
|
15
|
+
export interface JsonPointerExactBudget {
|
|
16
|
+
readonly seen_artifact_paths: Set<string>;
|
|
17
|
+
total_artifact_bytes: number;
|
|
18
|
+
}
|
|
19
|
+
export interface JsonPointerExactLocator {
|
|
20
|
+
kind: string;
|
|
21
|
+
value: string;
|
|
22
|
+
}
|
|
23
|
+
export interface JsonPointerExactObservation {
|
|
24
|
+
capability: typeof JSON_POINTER_EXACT_CAPABILITY;
|
|
25
|
+
artifact_path: string;
|
|
26
|
+
artifact_sha256: string;
|
|
27
|
+
locator: {
|
|
28
|
+
kind: "json_pointer";
|
|
29
|
+
value: string;
|
|
30
|
+
};
|
|
31
|
+
value_sha256: string;
|
|
32
|
+
canonical_value_bytes: number;
|
|
33
|
+
sensitivity: "plain";
|
|
34
|
+
}
|
|
35
|
+
export declare function createJsonPointerExactBudget(): JsonPointerExactBudget;
|
|
36
|
+
export declare function isJsonPointerExactOracle(oracle: {
|
|
37
|
+
trust?: string;
|
|
38
|
+
identity?: string;
|
|
39
|
+
version?: string;
|
|
40
|
+
sha256?: string | null;
|
|
41
|
+
}): boolean;
|
|
42
|
+
export declare function extractJsonPointerExactObservationFromBytes(input: {
|
|
43
|
+
artifact_path: string;
|
|
44
|
+
bytes: Uint8Array;
|
|
45
|
+
locator: JsonPointerExactLocator;
|
|
46
|
+
sensitivity: string;
|
|
47
|
+
budget?: JsonPointerExactBudget;
|
|
48
|
+
}): JsonPointerExactObservation;
|
|
49
|
+
export declare function validateJsonPointerExactLocator(locator: JsonPointerExactLocator): {
|
|
50
|
+
kind: "json_pointer";
|
|
51
|
+
value: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function normalizeObservationArtifactPath(value: string): string;
|
|
54
|
+
export declare function invalidObservation(code: string): Error;
|
|
55
|
+
export declare function observationErrorMessage(error: unknown): string;
|
|
56
|
+
export declare function resolveJsonPointer(root: unknown, pointer: string): unknown;
|
|
57
|
+
export declare function parseJsonWithoutDuplicateKeys(content: string): unknown;
|
|
58
|
+
export declare function decodeUtf8Json(bytes: Uint8Array): string;
|
|
59
|
+
export declare function assertJsonTree(value: unknown, depth: number): void;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { canonicalValueJson, parseStrictYaml, sha256Hex, } from "./strict-codec.js";
|
|
3
|
+
export const JSON_POINTER_EXACT_CAPABILITY = "json-pointer-exact-v1";
|
|
4
|
+
export const JSON_POINTER_EXACT_ORACLE_IDENTITY = "ty-context-json-pointer-exact";
|
|
5
|
+
export const JSON_POINTER_EXACT_ORACLE_VERSION = "1.0.0";
|
|
6
|
+
export const JSON_POINTER_EXACT_METHODS = Object.freeze([
|
|
7
|
+
"exact_value",
|
|
8
|
+
"content",
|
|
9
|
+
"component_state",
|
|
10
|
+
]);
|
|
11
|
+
export const JSON_POINTER_EXACT_LIMITS = Object.freeze({
|
|
12
|
+
max_file_bytes: 1_048_576,
|
|
13
|
+
max_depth: 64,
|
|
14
|
+
max_pointer_bytes: 4_096,
|
|
15
|
+
max_pointer_segments: 128,
|
|
16
|
+
max_canonical_value_bytes: 262_144,
|
|
17
|
+
max_artifacts_per_check: 256,
|
|
18
|
+
max_total_artifact_bytes: 16_777_216,
|
|
19
|
+
});
|
|
20
|
+
export const JSON_POINTER_EXACT_SPEC_SHA256 = sha256Hex(canonicalValueJson({
|
|
21
|
+
capability: JSON_POINTER_EXACT_CAPABILITY,
|
|
22
|
+
oracle_identity: JSON_POINTER_EXACT_ORACLE_IDENTITY,
|
|
23
|
+
oracle_version: JSON_POINTER_EXACT_ORACLE_VERSION,
|
|
24
|
+
media_type: "application/json",
|
|
25
|
+
encoding: "utf-8",
|
|
26
|
+
locator: "rfc6901-json-pointer",
|
|
27
|
+
canonicalization: "canonical-json-v1",
|
|
28
|
+
methods: JSON_POINTER_EXACT_METHODS,
|
|
29
|
+
comparator: "exact_value",
|
|
30
|
+
mode: "exact",
|
|
31
|
+
sensitivity: "plain",
|
|
32
|
+
limits: JSON_POINTER_EXACT_LIMITS,
|
|
33
|
+
}));
|
|
34
|
+
export function createJsonPointerExactBudget() {
|
|
35
|
+
return { seen_artifact_paths: new Set(), total_artifact_bytes: 0 };
|
|
36
|
+
}
|
|
37
|
+
export function isJsonPointerExactOracle(oracle) {
|
|
38
|
+
return (oracle.trust === "named_external_tcb" &&
|
|
39
|
+
oracle.identity === JSON_POINTER_EXACT_ORACLE_IDENTITY &&
|
|
40
|
+
oracle.version === JSON_POINTER_EXACT_ORACLE_VERSION &&
|
|
41
|
+
oracle.sha256 === null);
|
|
42
|
+
}
|
|
43
|
+
export function extractJsonPointerExactObservationFromBytes(input) {
|
|
44
|
+
const artifactPath = normalizeObservationArtifactPath(input.artifact_path);
|
|
45
|
+
if (input.sensitivity !== "plain")
|
|
46
|
+
throw invalidObservation("observation_protected_requires_frozen_adapter");
|
|
47
|
+
if (input.bytes.byteLength > JSON_POINTER_EXACT_LIMITS.max_file_bytes)
|
|
48
|
+
throw invalidObservation("observation_artifact_size_limit");
|
|
49
|
+
accountForArtifact(input.budget, artifactPath, input.bytes.byteLength);
|
|
50
|
+
const locator = validateJsonPointerExactLocator(input.locator);
|
|
51
|
+
const parsed = parseJsonWithoutDuplicateKeys(decodeUtf8Json(input.bytes));
|
|
52
|
+
assertJsonTree(parsed, 0);
|
|
53
|
+
const canonical = canonicalValueJson(resolveJsonPointer(parsed, locator.value));
|
|
54
|
+
const canonicalBytes = Buffer.byteLength(canonical, "utf8");
|
|
55
|
+
if (canonicalBytes > JSON_POINTER_EXACT_LIMITS.max_canonical_value_bytes)
|
|
56
|
+
throw invalidObservation("observation_canonical_value_size_limit");
|
|
57
|
+
return {
|
|
58
|
+
capability: JSON_POINTER_EXACT_CAPABILITY,
|
|
59
|
+
artifact_path: artifactPath,
|
|
60
|
+
artifact_sha256: sha256Hex(input.bytes),
|
|
61
|
+
locator,
|
|
62
|
+
value_sha256: sha256Hex(canonical),
|
|
63
|
+
canonical_value_bytes: canonicalBytes,
|
|
64
|
+
sensitivity: "plain",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function validateJsonPointerExactLocator(locator) {
|
|
68
|
+
if (locator.kind !== "json_pointer" ||
|
|
69
|
+
typeof locator.value !== "string" ||
|
|
70
|
+
locator.value.startsWith("#") ||
|
|
71
|
+
(locator.value !== "" && !locator.value.startsWith("/")) ||
|
|
72
|
+
Buffer.byteLength(locator.value, "utf8") >
|
|
73
|
+
JSON_POINTER_EXACT_LIMITS.max_pointer_bytes)
|
|
74
|
+
throw invalidObservation("observation_locator_not_admitted");
|
|
75
|
+
const encoded = locator.value === "" ? [] : locator.value.slice(1).split("/");
|
|
76
|
+
if (encoded.length > JSON_POINTER_EXACT_LIMITS.max_pointer_segments)
|
|
77
|
+
throw invalidObservation("observation_locator_segment_limit");
|
|
78
|
+
for (const token of encoded)
|
|
79
|
+
if (/~(?:[^01]|$)/u.test(token))
|
|
80
|
+
throw invalidObservation("observation_locator_not_admitted");
|
|
81
|
+
return { kind: "json_pointer", value: locator.value };
|
|
82
|
+
}
|
|
83
|
+
export function normalizeObservationArtifactPath(value) {
|
|
84
|
+
if (!value ||
|
|
85
|
+
value.includes("\\") ||
|
|
86
|
+
value.includes("\0") ||
|
|
87
|
+
path.posix.isAbsolute(value) ||
|
|
88
|
+
/^[a-z]:/iu.test(value))
|
|
89
|
+
throw invalidObservation("observation_artifact_path_escape");
|
|
90
|
+
const segments = value.split("/");
|
|
91
|
+
if (segments.some((segment) => !segment || segment === "." || segment === ".."))
|
|
92
|
+
throw invalidObservation("observation_artifact_path_escape");
|
|
93
|
+
return segments.join("/");
|
|
94
|
+
}
|
|
95
|
+
export function invalidObservation(code) {
|
|
96
|
+
return new Error(code);
|
|
97
|
+
}
|
|
98
|
+
export function observationErrorMessage(error) {
|
|
99
|
+
return error instanceof Error ? error.message : String(error);
|
|
100
|
+
}
|
|
101
|
+
export function resolveJsonPointer(root, pointer) {
|
|
102
|
+
let current = root;
|
|
103
|
+
if (pointer === "")
|
|
104
|
+
return current;
|
|
105
|
+
for (const encoded of pointer.slice(1).split("/")) {
|
|
106
|
+
const token = encoded.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
107
|
+
if (Array.isArray(current)) {
|
|
108
|
+
if (!/^(?:0|[1-9]\d*)$/u.test(token))
|
|
109
|
+
throw invalidObservation("observation_locator_array_index_invalid");
|
|
110
|
+
const index = Number(token);
|
|
111
|
+
if (!Number.isSafeInteger(index) || index >= current.length)
|
|
112
|
+
throw invalidObservation("observation_locator_not_found");
|
|
113
|
+
current = current[index];
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (!current ||
|
|
117
|
+
typeof current !== "object" ||
|
|
118
|
+
!Object.hasOwn(current, token))
|
|
119
|
+
throw invalidObservation("observation_locator_not_found");
|
|
120
|
+
current = current[token];
|
|
121
|
+
}
|
|
122
|
+
return current;
|
|
123
|
+
}
|
|
124
|
+
export function parseJsonWithoutDuplicateKeys(content) {
|
|
125
|
+
let parsed;
|
|
126
|
+
try {
|
|
127
|
+
parsed = JSON.parse(content);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
throw invalidObservation("observation_json_invalid");
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const strict = parseStrictYaml(content);
|
|
134
|
+
if (canonicalValueJson(strict) !== canonicalValueJson(parsed))
|
|
135
|
+
throw invalidObservation("observation_json_canonicalization_mismatch");
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
if (observationErrorMessage(error).includes("unique"))
|
|
139
|
+
throw invalidObservation("observation_json_duplicate_key");
|
|
140
|
+
if (observationErrorMessage(error).startsWith("observation_"))
|
|
141
|
+
throw error;
|
|
142
|
+
throw invalidObservation("observation_json_invalid");
|
|
143
|
+
}
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
export function decodeUtf8Json(bytes) {
|
|
147
|
+
if (bytes.byteLength >= 3 &&
|
|
148
|
+
bytes[0] === 0xef &&
|
|
149
|
+
bytes[1] === 0xbb &&
|
|
150
|
+
bytes[2] === 0xbf)
|
|
151
|
+
throw invalidObservation("observation_json_utf8_invalid");
|
|
152
|
+
try {
|
|
153
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
throw invalidObservation("observation_json_utf8_invalid");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
export function assertJsonTree(value, depth) {
|
|
160
|
+
if (depth > JSON_POINTER_EXACT_LIMITS.max_depth)
|
|
161
|
+
throw invalidObservation("observation_json_depth_limit");
|
|
162
|
+
if (typeof value === "number" && !Number.isFinite(value))
|
|
163
|
+
throw invalidObservation("observation_json_number_invalid");
|
|
164
|
+
if (Array.isArray(value)) {
|
|
165
|
+
for (const entry of value)
|
|
166
|
+
assertJsonTree(entry, depth + 1);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (value && typeof value === "object")
|
|
170
|
+
for (const entry of Object.values(value))
|
|
171
|
+
assertJsonTree(entry, depth + 1);
|
|
172
|
+
}
|
|
173
|
+
function accountForArtifact(budget, artifactPath, bytes) {
|
|
174
|
+
if (!budget || budget.seen_artifact_paths.has(artifactPath))
|
|
175
|
+
return;
|
|
176
|
+
if (budget.seen_artifact_paths.size >=
|
|
177
|
+
JSON_POINTER_EXACT_LIMITS.max_artifacts_per_check)
|
|
178
|
+
throw invalidObservation("observation_artifact_count_limit");
|
|
179
|
+
if (budget.total_artifact_bytes + bytes >
|
|
180
|
+
JSON_POINTER_EXACT_LIMITS.max_total_artifact_bytes)
|
|
181
|
+
throw invalidObservation("observation_artifact_total_size_limit");
|
|
182
|
+
budget.seen_artifact_paths.add(artifactPath);
|
|
183
|
+
budget.total_artifact_bytes += bytes;
|
|
184
|
+
}
|