project-tiny-context-harness 0.8.10 → 0.8.12
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 +490 -472
- package/assets/README.md +762 -749
- package/assets/README.zh-CN.md +446 -431
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +17 -23
- 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 +64 -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 +52 -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 +119 -119
- 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 +98 -94
- package/assets/skills/long-task-workflow/references/evidence-design.md +67 -63
- 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.js +9 -2
- package/dist/commands/enable.js +2 -0
- package/dist/commands/index.js +1 -1
- package/dist/commands/long-task-revision.js +8 -7
- package/dist/commands/sync.js +2 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +2 -1
- 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-manifest-validation.d.ts +2 -1
- 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.d.ts +11 -0
- package/dist/lib/design-resource-handoff-bundle-draft.js +40 -0
- package/dist/lib/design-resource-handoff-bundle.js +4 -28
- package/dist/lib/design-resource-handoff-input-types.d.ts +14 -0
- package/dist/lib/design-resource-handoff-input-types.js +1 -0
- package/dist/lib/design-resource-handoff-manifest-projection.d.ts +2 -1
- 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 +4 -1
- package/dist/lib/design-resource-handoff-shape.js +10 -0
- package/dist/lib/design-resource-handoff-snapshot.d.ts +1 -1
- package/dist/lib/design-resource-handoff-snapshot.js +4 -0
- package/dist/lib/design-resource-handoff-types.d.ts +0 -10
- package/dist/lib/design-resource-handoff-validation.d.ts +6 -2
- 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-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-activation-validation.js +2 -2
- package/dist/lib/long-task-authority-policy.d.ts +3 -0
- package/dist/lib/long-task-authority-policy.js +3 -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 +90 -0
- package/dist/lib/long-task-counterfactual-sandbox.d.ts +1 -1
- package/dist/lib/long-task-counterfactual-sandbox.js +7 -5
- 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.js +28 -0
- package/dist/lib/long-task-evidence-capability-runtime.js +271 -63
- package/dist/lib/long-task-evidence-capability-types.d.ts +70 -2
- package/dist/lib/long-task-evidence-v2.d.ts +1 -1
- package/dist/lib/long-task-evidence-v2.js +5 -5
- 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-playwright-capability-records.d.ts +2 -0
- package/dist/lib/long-task-playwright-capability-records.js +74 -2
- package/dist/lib/long-task-runner-freeze.d.ts +1 -1
- package/dist/lib/long-task-runner-freeze.js +4 -2
- package/dist/lib/long-task-semantic-contract-types.d.ts +1 -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 +15 -3
- 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 +5 -1
- package/dist/lib/long-task-semantic-fact-evidence.js +47 -4
- 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-item-parser.d.ts +2 -2
- package/dist/lib/long-task-source-item-parser.js +20 -11
- 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-v2.js +1 -1
- 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.js +11 -1
- package/dist/lib/migrations.js +58 -0
- package/dist/lib/profiles.js +0 -1
- 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 +390 -5
- package/migrations/README.md +15 -15
- package/package.json +2 -2
- package/source-mappings.yaml +28 -25
- package/assets/skills/source-plan-authoring/SKILL.md +0 -14
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { invalidDesignResourceHandoff } from "./design-resource-handoff-validation-primitives.js";
|
|
2
|
+
import { DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY } from "./design-resource-symbolic-fact-policy.js";
|
|
3
|
+
const V1_SCHEMA = "design-resource-observable-fact-manifest-v1";
|
|
4
|
+
export const DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE = "regenerate_as=design-resource-handoff-v2:fact_model=symbolic_rules_v2";
|
|
5
|
+
export function parseDesignResourceV1CapacityHeader(prefix) {
|
|
6
|
+
try {
|
|
7
|
+
const reader = new BoundedJsonReader(prefix);
|
|
8
|
+
const header = reader.readRootHeader();
|
|
9
|
+
if (header.first_key !== "schema_version")
|
|
10
|
+
invalid("v1_manifest_capacity_header_order_invalid", `first_key=${header.first_key ?? "missing"}:required=schema_version`);
|
|
11
|
+
if (header.schema_version !== V1_SCHEMA)
|
|
12
|
+
invalid("v1_manifest_capacity_header_schema_invalid", `schema_version=${String(header.schema_version)}`);
|
|
13
|
+
if (!header.generation)
|
|
14
|
+
invalid("v1_manifest_capacity_header_missing_or_late", `prefix_limit=${DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY.v1_capacity.capacity_header_prefix_max_bytes}:${DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE}`);
|
|
15
|
+
const collections = objectValue(header.generation, "v1_manifest_capacity_header_generation_invalid").collections;
|
|
16
|
+
if (!Array.isArray(collections))
|
|
17
|
+
invalid("v1_manifest_capacity_header_collections_invalid", "not_array");
|
|
18
|
+
const collectionCounts = new Map();
|
|
19
|
+
for (const value of collections) {
|
|
20
|
+
const collection = objectValue(value, "v1_manifest_capacity_header_collection_invalid");
|
|
21
|
+
if (typeof collection.name !== "string" || !collection.name)
|
|
22
|
+
invalid("v1_manifest_capacity_header_collection_name_invalid", "");
|
|
23
|
+
if (typeof collection.expected_count !== "number" ||
|
|
24
|
+
!Number.isSafeInteger(collection.expected_count) ||
|
|
25
|
+
collection.expected_count < 0)
|
|
26
|
+
invalid("v1_manifest_capacity_header_expected_count_invalid", collection.name);
|
|
27
|
+
if (collectionCounts.has(collection.name))
|
|
28
|
+
invalid("v1_manifest_capacity_header_collection_duplicate", collection.name);
|
|
29
|
+
collectionCounts.set(collection.name, collection.expected_count);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
schema_version: V1_SCHEMA,
|
|
33
|
+
collection_counts: collectionCounts,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error instanceof Error &&
|
|
38
|
+
error.message.startsWith("design_resource_handoff_invalid:"))
|
|
39
|
+
throw error;
|
|
40
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
41
|
+
invalid("v1_manifest_capacity_header_missing_or_late", `prefix_limit=${DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY.v1_capacity.capacity_header_prefix_max_bytes}:reason=${message}:${DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
class BoundedJsonReader {
|
|
45
|
+
input;
|
|
46
|
+
offset = 0;
|
|
47
|
+
depth = 0;
|
|
48
|
+
constructor(input) {
|
|
49
|
+
this.input = input;
|
|
50
|
+
}
|
|
51
|
+
readRootHeader() {
|
|
52
|
+
this.whitespace();
|
|
53
|
+
this.character("{");
|
|
54
|
+
const result = {
|
|
55
|
+
first_key: null,
|
|
56
|
+
schema_version: undefined,
|
|
57
|
+
generation: undefined,
|
|
58
|
+
};
|
|
59
|
+
this.whitespace();
|
|
60
|
+
if (this.peek() === "}")
|
|
61
|
+
throw new Error("root_empty");
|
|
62
|
+
for (;;) {
|
|
63
|
+
const key = this.string();
|
|
64
|
+
result.first_key ??= key;
|
|
65
|
+
this.whitespace();
|
|
66
|
+
this.character(":");
|
|
67
|
+
this.whitespace();
|
|
68
|
+
const value = this.value();
|
|
69
|
+
if (key === "schema_version")
|
|
70
|
+
result.schema_version = value;
|
|
71
|
+
if (key === "generation") {
|
|
72
|
+
result.generation = value;
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
this.whitespace();
|
|
76
|
+
const delimiter = this.peek();
|
|
77
|
+
if (delimiter === "}")
|
|
78
|
+
return result;
|
|
79
|
+
this.character(",");
|
|
80
|
+
this.whitespace();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
value() {
|
|
84
|
+
if (++this.depth > 64)
|
|
85
|
+
throw new Error("depth_limit");
|
|
86
|
+
try {
|
|
87
|
+
const next = this.peek();
|
|
88
|
+
if (next === '"')
|
|
89
|
+
return this.string();
|
|
90
|
+
if (next === "{")
|
|
91
|
+
return this.object();
|
|
92
|
+
if (next === "[")
|
|
93
|
+
return this.array();
|
|
94
|
+
if (next === "t")
|
|
95
|
+
return this.literal("true", true);
|
|
96
|
+
if (next === "f")
|
|
97
|
+
return this.literal("false", false);
|
|
98
|
+
if (next === "n")
|
|
99
|
+
return this.literal("null", null);
|
|
100
|
+
return this.number();
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
this.depth -= 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
object() {
|
|
107
|
+
const value = {};
|
|
108
|
+
this.character("{");
|
|
109
|
+
this.whitespace();
|
|
110
|
+
if (this.peek() === "}") {
|
|
111
|
+
this.offset += 1;
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
for (;;) {
|
|
115
|
+
const key = this.string();
|
|
116
|
+
if (Object.hasOwn(value, key))
|
|
117
|
+
throw new Error(`duplicate_key:${key}`);
|
|
118
|
+
this.whitespace();
|
|
119
|
+
this.character(":");
|
|
120
|
+
this.whitespace();
|
|
121
|
+
value[key] = this.value();
|
|
122
|
+
this.whitespace();
|
|
123
|
+
if (this.peek() === "}") {
|
|
124
|
+
this.offset += 1;
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
this.character(",");
|
|
128
|
+
this.whitespace();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
array() {
|
|
132
|
+
const value = [];
|
|
133
|
+
this.character("[");
|
|
134
|
+
this.whitespace();
|
|
135
|
+
if (this.peek() === "]") {
|
|
136
|
+
this.offset += 1;
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
for (;;) {
|
|
140
|
+
value.push(this.value());
|
|
141
|
+
this.whitespace();
|
|
142
|
+
if (this.peek() === "]") {
|
|
143
|
+
this.offset += 1;
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
this.character(",");
|
|
147
|
+
this.whitespace();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
string() {
|
|
151
|
+
this.character('"');
|
|
152
|
+
let value = "";
|
|
153
|
+
for (;;) {
|
|
154
|
+
if (this.offset >= this.input.length)
|
|
155
|
+
throw new Error("prefix_ended");
|
|
156
|
+
const character = this.input[this.offset++];
|
|
157
|
+
if (character === '"')
|
|
158
|
+
return value;
|
|
159
|
+
if (character === "\\") {
|
|
160
|
+
if (this.offset >= this.input.length)
|
|
161
|
+
throw new Error("prefix_ended");
|
|
162
|
+
const escaped = this.input[this.offset++];
|
|
163
|
+
const simple = {
|
|
164
|
+
'"': '"',
|
|
165
|
+
"\\": "\\",
|
|
166
|
+
"/": "/",
|
|
167
|
+
b: "\b",
|
|
168
|
+
f: "\f",
|
|
169
|
+
n: "\n",
|
|
170
|
+
r: "\r",
|
|
171
|
+
t: "\t",
|
|
172
|
+
};
|
|
173
|
+
if (escaped in simple)
|
|
174
|
+
value += simple[escaped];
|
|
175
|
+
else if (escaped === "u") {
|
|
176
|
+
const hex = this.input.slice(this.offset, this.offset + 4);
|
|
177
|
+
if (!/^[0-9a-fA-F]{4}$/u.test(hex))
|
|
178
|
+
throw new Error("unicode_escape_invalid");
|
|
179
|
+
value += String.fromCharCode(Number.parseInt(hex, 16));
|
|
180
|
+
this.offset += 4;
|
|
181
|
+
}
|
|
182
|
+
else
|
|
183
|
+
throw new Error("escape_invalid");
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
if (character.charCodeAt(0) < 0x20)
|
|
187
|
+
throw new Error("string_control_character");
|
|
188
|
+
value += character;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
number() {
|
|
193
|
+
const remaining = this.input.slice(this.offset);
|
|
194
|
+
const match = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/u.exec(remaining);
|
|
195
|
+
if (!match)
|
|
196
|
+
throw new Error("number_invalid");
|
|
197
|
+
this.offset += match[0].length;
|
|
198
|
+
const value = Number(match[0]);
|
|
199
|
+
if (!Number.isFinite(value))
|
|
200
|
+
throw new Error("number_non_finite");
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
literal(token, value) {
|
|
204
|
+
if (this.input.slice(this.offset, this.offset + token.length) !== token)
|
|
205
|
+
throw new Error(`literal_invalid:${token}`);
|
|
206
|
+
this.offset += token.length;
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
whitespace() {
|
|
210
|
+
while (/\s/u.test(this.input[this.offset] ?? ""))
|
|
211
|
+
this.offset += 1;
|
|
212
|
+
}
|
|
213
|
+
character(expected) {
|
|
214
|
+
if (this.input[this.offset] !== expected)
|
|
215
|
+
throw new Error(`expected:${expected}:at=${this.offset}`);
|
|
216
|
+
this.offset += 1;
|
|
217
|
+
}
|
|
218
|
+
peek() {
|
|
219
|
+
if (this.offset >= this.input.length)
|
|
220
|
+
throw new Error("prefix_ended");
|
|
221
|
+
return this.input[this.offset];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function objectValue(value, code) {
|
|
225
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
226
|
+
invalid(code, "not_object");
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
function invalid(code, detail) {
|
|
230
|
+
invalidDesignResourceHandoff(code, detail);
|
|
231
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type DesignResourceV1CapacityHeader } from "./design-resource-v1-capacity-header.js";
|
|
2
|
+
export { parseDesignResourceV1CapacityHeader } from "./design-resource-v1-capacity-header.js";
|
|
3
|
+
export type { DesignResourceV1CapacityHeader } from "./design-resource-v1-capacity-header.js";
|
|
4
|
+
export declare function assertDesignResourceV1HandoffCapacity(file: string): Promise<void>;
|
|
5
|
+
export declare function assertDesignResourceV1ManifestCapacity(file: string): Promise<DesignResourceV1CapacityHeader>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { open, stat } from "node:fs/promises";
|
|
2
|
+
import { invalidDesignResourceHandoff } from "./design-resource-handoff-validation-primitives.js";
|
|
3
|
+
import { DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY } from "./design-resource-symbolic-fact-policy.js";
|
|
4
|
+
import { DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE, parseDesignResourceV1CapacityHeader, } from "./design-resource-v1-capacity-header.js";
|
|
5
|
+
export { parseDesignResourceV1CapacityHeader } from "./design-resource-v1-capacity-header.js";
|
|
6
|
+
export async function assertDesignResourceV1HandoffCapacity(file) {
|
|
7
|
+
const bytes = (await stat(file)).size;
|
|
8
|
+
const limit = DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY.v1_capacity.embedded_handoff_max_bytes;
|
|
9
|
+
if (bytes > limit)
|
|
10
|
+
invalid("v1_handoff_capacity_exceeded", `bytes=${bytes}:limit=${limit}:${DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE}`);
|
|
11
|
+
}
|
|
12
|
+
export async function assertDesignResourceV1ManifestCapacity(file) {
|
|
13
|
+
const bytes = (await stat(file)).size;
|
|
14
|
+
const policy = DESIGN_RESOURCE_SYMBOLIC_FACT_POLICY.v1_capacity;
|
|
15
|
+
if (bytes > policy.canonical_manifest_max_bytes)
|
|
16
|
+
invalid("v1_manifest_capacity_exceeded", `bytes=${bytes}:limit=${policy.canonical_manifest_max_bytes}:${DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE}`);
|
|
17
|
+
const prefixBytes = Math.min(bytes, policy.capacity_header_prefix_max_bytes);
|
|
18
|
+
const buffer = Buffer.alloc(prefixBytes);
|
|
19
|
+
const handle = await open(file, "r");
|
|
20
|
+
try {
|
|
21
|
+
let offset = 0;
|
|
22
|
+
while (offset < prefixBytes) {
|
|
23
|
+
const result = await handle.read(buffer, offset, prefixBytes - offset, offset);
|
|
24
|
+
if (result.bytesRead === 0)
|
|
25
|
+
break;
|
|
26
|
+
offset += result.bytesRead;
|
|
27
|
+
}
|
|
28
|
+
if (offset !== prefixBytes)
|
|
29
|
+
invalid("v1_manifest_capacity_header_read_incomplete", `bytes_read=${offset}:expected=${prefixBytes}`);
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await handle.close();
|
|
33
|
+
}
|
|
34
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(buffer);
|
|
35
|
+
const header = parseDesignResourceV1CapacityHeader(text);
|
|
36
|
+
const expectedFactCells = header.collection_counts.get("fact_cells");
|
|
37
|
+
if (expectedFactCells === undefined)
|
|
38
|
+
invalid("v1_manifest_capacity_header_fact_cells_missing", DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE);
|
|
39
|
+
if (expectedFactCells > policy.expected_fact_cells_max)
|
|
40
|
+
invalid("v1_fact_cell_capacity_exceeded", `expected_count=${expectedFactCells}:limit=${policy.expected_fact_cells_max}:${DESIGN_RESOURCE_V1_REGENERATION_GUIDANCE}`);
|
|
41
|
+
return header;
|
|
42
|
+
}
|
|
43
|
+
function invalid(code, detail) {
|
|
44
|
+
invalidDesignResourceHandoff(code, detail);
|
|
45
|
+
}
|
package/dist/lib/init.js
CHANGED
|
@@ -25,6 +25,7 @@ export async function runInit(projectRoot, options) {
|
|
|
25
25
|
await createDesignMd(projectRoot, report);
|
|
26
26
|
const syncReport = await runSync(projectRoot);
|
|
27
27
|
report.push(`sync changed=${syncReport.changed.length} skipped=${syncReport.skipped.length} blocked=${syncReport.blocked.length}`);
|
|
28
|
+
report.push(...(syncReport.notices ?? []));
|
|
28
29
|
report.push(options.adopt ? "adopt mode complete" : "init complete");
|
|
29
30
|
return report;
|
|
30
31
|
}
|
|
@@ -66,7 +66,7 @@ export async function validateContractForActivation(options) {
|
|
|
66
66
|
const executionTarget = contract.task.execution_targets.find((target) => target.key === check.execution_target.target_ref);
|
|
67
67
|
if (!executionTarget)
|
|
68
68
|
continue;
|
|
69
|
-
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, null, repository, workspace, executionTarget, contract.task.execution_targets, [], []), null, check.key);
|
|
69
|
+
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, null, repository, workspace, executionTarget, contract.task.execution_targets, [], [], context?.files ?? []), null, check.key);
|
|
70
70
|
if (frozen)
|
|
71
71
|
globalChecks.push(frozen);
|
|
72
72
|
}
|
|
@@ -77,7 +77,7 @@ export async function validateContractForActivation(options) {
|
|
|
77
77
|
const executionTarget = contract.task.execution_targets.find((target) => target.key === check.execution_target.target_ref);
|
|
78
78
|
if (!executionTarget)
|
|
79
79
|
continue;
|
|
80
|
-
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, outcome.key, repository, workspace, executionTarget, contract.task.execution_targets, designTargetsForCheck(outcome, check.key), semanticFactClosure?.expectations_by_check.get(check.key) ?? []), outcome.key, check.key);
|
|
80
|
+
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, outcome.key, repository, workspace, executionTarget, contract.task.execution_targets, designTargetsForCheck(outcome, check.key), semanticFactClosure?.expectations_by_check.get(check.key) ?? [], context?.files ?? []), outcome.key, check.key);
|
|
81
81
|
if (frozen)
|
|
82
82
|
checks.push(frozen);
|
|
83
83
|
}
|
|
@@ -161,6 +161,7 @@ export declare const AUTHORITY_FIELD_POLICY_REGISTRIES: {
|
|
|
161
161
|
};
|
|
162
162
|
readonly design_target: {
|
|
163
163
|
key: "identity";
|
|
164
|
+
fact_model: "semantic_user_review";
|
|
164
165
|
interpretation: "semantic_user_review";
|
|
165
166
|
source_paths: "scope";
|
|
166
167
|
condition_keys: "semantic_user_review";
|
|
@@ -168,6 +169,8 @@ export declare const AUTHORITY_FIELD_POLICY_REGISTRIES: {
|
|
|
168
169
|
conformance_check_ref: "proof_additive";
|
|
169
170
|
conformance_assertion_ref: "proof_additive";
|
|
170
171
|
verification_method_bindings: "proof_additive";
|
|
172
|
+
symbolic_method_bindings: "proof_additive";
|
|
173
|
+
symbolic_certificate_binding: "proof_additive";
|
|
171
174
|
actual_artifact_path: "output_requirement";
|
|
172
175
|
comparison_artifact_path: "output_requirement";
|
|
173
176
|
};
|
|
@@ -144,6 +144,7 @@ const SURFACE_BINDING_AUTHORITY_POLICY = {
|
|
|
144
144
|
};
|
|
145
145
|
const DESIGN_TARGET_AUTHORITY_POLICY = {
|
|
146
146
|
key: "identity",
|
|
147
|
+
fact_model: "semantic_user_review",
|
|
147
148
|
interpretation: "semantic_user_review",
|
|
148
149
|
source_paths: "scope",
|
|
149
150
|
condition_keys: "semantic_user_review",
|
|
@@ -151,6 +152,8 @@ const DESIGN_TARGET_AUTHORITY_POLICY = {
|
|
|
151
152
|
conformance_check_ref: "proof_additive",
|
|
152
153
|
conformance_assertion_ref: "proof_additive",
|
|
153
154
|
verification_method_bindings: "proof_additive",
|
|
155
|
+
symbolic_method_bindings: "proof_additive",
|
|
156
|
+
symbolic_certificate_binding: "proof_additive",
|
|
154
157
|
actual_artifact_path: "output_requirement",
|
|
155
158
|
comparison_artifact_path: "output_requirement",
|
|
156
159
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Stats } from "node:fs";
|
|
2
|
+
import type { SyncReport } from "./sync-engine.js";
|
|
3
|
+
export declare const LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH = ".codex/agents/long-task-implementation.toml";
|
|
4
|
+
export declare const LONG_TASK_CODEX_AGENT_PROFILE_MANAGED_MARKER = "# ty-context:managed:long-task-implementation-worker";
|
|
5
|
+
export interface LongTaskCodexAgentProfile {
|
|
6
|
+
name: "long_task_implementation";
|
|
7
|
+
description: string;
|
|
8
|
+
developer_instructions: string;
|
|
9
|
+
model: string;
|
|
10
|
+
model_reasoning_effort: string;
|
|
11
|
+
agents: {
|
|
12
|
+
enabled: false;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export type LongTaskCodexAgentProfileValidation = {
|
|
16
|
+
valid: true;
|
|
17
|
+
profile: LongTaskCodexAgentProfile;
|
|
18
|
+
} | {
|
|
19
|
+
valid: false;
|
|
20
|
+
errors: string[];
|
|
21
|
+
};
|
|
22
|
+
export interface LongTaskCodexAgentProfileFileOperations {
|
|
23
|
+
lstat(target: string): Promise<Stats>;
|
|
24
|
+
realpath(target: string): Promise<string>;
|
|
25
|
+
readFile(target: string, encoding: "utf8"): Promise<string>;
|
|
26
|
+
mkdir(target: string, options: {
|
|
27
|
+
recursive: true;
|
|
28
|
+
}): Promise<unknown>;
|
|
29
|
+
writeFile(target: string, content: string, options: {
|
|
30
|
+
flag: "wx";
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
rename(source: string, destination: string): Promise<void>;
|
|
33
|
+
rm(target: string, options: {
|
|
34
|
+
force: true;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
randomId(): string;
|
|
37
|
+
}
|
|
38
|
+
export declare function parseAndValidateLongTaskCodexAgentProfile(content: string): LongTaskCodexAgentProfileValidation;
|
|
39
|
+
export declare function syncLongTaskCodexAgentProfile(projectRoot: string, resolvedHarnessRoot: string, enabled: boolean, report: SyncReport, fileOperations?: Partial<LongTaskCodexAgentProfileFileOperations>): Promise<void>;
|
|
40
|
+
export declare function longTaskCodexAgentProfileBootstrapPaths(projectRoot: string, resolvedHarnessRoot: string, enabled: boolean, fileOperations?: Partial<LongTaskCodexAgentProfileFileOperations>): Promise<string[]>;
|
|
41
|
+
export declare function isManagedLongTaskCodexAgentProfile(content: string): boolean;
|
|
42
|
+
export declare function atomicWriteLongTaskCodexAgentProfile(destination: string, content: string, operations?: LongTaskCodexAgentProfileFileOperations, beforeRename?: () => Promise<void>): Promise<void>;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parse as parseToml } from "smol-toml";
|
|
5
|
+
import { packageAssetPath } from "./paths.js";
|
|
6
|
+
export const LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH = ".codex/agents/long-task-implementation.toml";
|
|
7
|
+
export const LONG_TASK_CODEX_AGENT_PROFILE_MANAGED_MARKER = "# ty-context:managed:long-task-implementation-worker";
|
|
8
|
+
const ASSET_SEGMENTS = ["agents", "long-task-implementation.toml"];
|
|
9
|
+
const PROFILE_ROOT_FIELDS = new Set([
|
|
10
|
+
"name",
|
|
11
|
+
"description",
|
|
12
|
+
"developer_instructions",
|
|
13
|
+
"model",
|
|
14
|
+
"model_reasoning_effort",
|
|
15
|
+
"agents",
|
|
16
|
+
]);
|
|
17
|
+
const PROFILE_AGENT_FIELDS = new Set(["enabled"]);
|
|
18
|
+
const DEFAULT_FILE_OPERATIONS = {
|
|
19
|
+
lstat: (target) => fs.lstat(target),
|
|
20
|
+
realpath: (target) => fs.realpath(target),
|
|
21
|
+
readFile: (target, encoding) => fs.readFile(target, encoding),
|
|
22
|
+
mkdir: (target, options) => fs.mkdir(target, options),
|
|
23
|
+
writeFile: (target, content, options) => fs.writeFile(target, content, options),
|
|
24
|
+
rename: (source, destination) => fs.rename(source, destination),
|
|
25
|
+
rm: (target, options) => fs.rm(target, options),
|
|
26
|
+
randomId: () => randomUUID(),
|
|
27
|
+
};
|
|
28
|
+
export function parseAndValidateLongTaskCodexAgentProfile(content) {
|
|
29
|
+
const errors = [];
|
|
30
|
+
const normalized = content.replace(/\r\n/gu, "\n");
|
|
31
|
+
if (!hasManagedMarker(normalized))
|
|
32
|
+
errors.push("managed_marker_missing_or_invalid");
|
|
33
|
+
let decoded;
|
|
34
|
+
try {
|
|
35
|
+
decoded = parseToml(normalized);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return { valid: false, errors: [...errors, "toml_invalid"] };
|
|
39
|
+
}
|
|
40
|
+
const root = record(decoded);
|
|
41
|
+
if (!root)
|
|
42
|
+
return { valid: false, errors: [...errors, "profile_not_table"] };
|
|
43
|
+
for (const key of Object.keys(root).sort())
|
|
44
|
+
if (!PROFILE_ROOT_FIELDS.has(key))
|
|
45
|
+
errors.push(`unsupported_field:${key}`);
|
|
46
|
+
if (root.name !== "long_task_implementation")
|
|
47
|
+
errors.push("name_must_be_long_task_implementation");
|
|
48
|
+
if (!nonEmptyString(root.description))
|
|
49
|
+
errors.push("description_required");
|
|
50
|
+
if (!nonEmptyString(root.developer_instructions))
|
|
51
|
+
errors.push("developer_instructions_required");
|
|
52
|
+
if (!staticString(root.model))
|
|
53
|
+
errors.push("model_must_be_static_nonempty");
|
|
54
|
+
if (!staticString(root.model_reasoning_effort))
|
|
55
|
+
errors.push("model_reasoning_effort_must_be_static_nonempty");
|
|
56
|
+
const agents = record(root.agents);
|
|
57
|
+
if (!agents)
|
|
58
|
+
errors.push("agents_table_required");
|
|
59
|
+
else {
|
|
60
|
+
for (const key of Object.keys(agents).sort())
|
|
61
|
+
if (!PROFILE_AGENT_FIELDS.has(key))
|
|
62
|
+
errors.push(`unsupported_agents_field:${key}`);
|
|
63
|
+
if (agents.enabled !== false)
|
|
64
|
+
errors.push("agents_enabled_must_be_false");
|
|
65
|
+
}
|
|
66
|
+
if (errors.length)
|
|
67
|
+
return { valid: false, errors };
|
|
68
|
+
return {
|
|
69
|
+
valid: true,
|
|
70
|
+
profile: {
|
|
71
|
+
name: "long_task_implementation",
|
|
72
|
+
description: root.description,
|
|
73
|
+
developer_instructions: root.developer_instructions,
|
|
74
|
+
model: root.model,
|
|
75
|
+
model_reasoning_effort: root.model_reasoning_effort,
|
|
76
|
+
agents: { enabled: false },
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export async function syncLongTaskCodexAgentProfile(projectRoot, resolvedHarnessRoot, enabled, report, fileOperations = {}) {
|
|
81
|
+
if (resolvedHarnessRoot !== ".codex")
|
|
82
|
+
return;
|
|
83
|
+
const operations = operationsWith(fileOperations);
|
|
84
|
+
const asset = await readValidPackageProfile(operations);
|
|
85
|
+
if (!asset.valid) {
|
|
86
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: optional package asset ${asset.reason}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const destination = path.join(projectRoot, LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH);
|
|
90
|
+
if (!enabled) {
|
|
91
|
+
await removeManagedProfile(projectRoot, destination, report, operations);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const inspected = await inspectProfileDestination(projectRoot, destination, operations);
|
|
95
|
+
if (inspected.kind === "conflict") {
|
|
96
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: optional adapter conflict (${inspected.reason})`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
let previous = null;
|
|
100
|
+
if (inspected.kind === "regular") {
|
|
101
|
+
previous = await operations.readFile(destination, "utf8");
|
|
102
|
+
if (!hasManagedMarker(previous)) {
|
|
103
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: user-owned (managed marker absent)`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (previous === asset.content) {
|
|
107
|
+
report.skipped.push(LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
await atomicWriteLongTaskCodexAgentProfile(destination, asset.content, operations, async () => {
|
|
113
|
+
const current = await inspectProfileDestination(projectRoot, destination, operations);
|
|
114
|
+
if (previous === null && current.kind !== "absent")
|
|
115
|
+
throw new Error("destination_changed_before_rename");
|
|
116
|
+
if (previous !== null) {
|
|
117
|
+
if (current.kind !== "regular")
|
|
118
|
+
throw new Error("destination_changed_before_rename");
|
|
119
|
+
if ((await operations.readFile(destination, "utf8")) !== previous)
|
|
120
|
+
throw new Error("destination_content_changed_before_rename");
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
report.changed.push(LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: optional adapter write failed (${message(error)})`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export async function longTaskCodexAgentProfileBootstrapPaths(projectRoot, resolvedHarnessRoot, enabled, fileOperations = {}) {
|
|
130
|
+
if (!enabled || resolvedHarnessRoot !== ".codex")
|
|
131
|
+
return [];
|
|
132
|
+
const operations = operationsWith(fileOperations);
|
|
133
|
+
const asset = await readValidPackageProfile(operations);
|
|
134
|
+
if (!asset.valid)
|
|
135
|
+
return [];
|
|
136
|
+
const destination = path.join(projectRoot, LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH);
|
|
137
|
+
const inspected = await inspectProfileDestination(projectRoot, destination, operations);
|
|
138
|
+
if (inspected.kind !== "regular")
|
|
139
|
+
return [];
|
|
140
|
+
const existing = await operations.readFile(destination, "utf8");
|
|
141
|
+
return existing === asset.content &&
|
|
142
|
+
parseAndValidateLongTaskCodexAgentProfile(existing).valid
|
|
143
|
+
? [LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH]
|
|
144
|
+
: [];
|
|
145
|
+
}
|
|
146
|
+
export function isManagedLongTaskCodexAgentProfile(content) {
|
|
147
|
+
return parseAndValidateLongTaskCodexAgentProfile(content).valid;
|
|
148
|
+
}
|
|
149
|
+
export async function atomicWriteLongTaskCodexAgentProfile(destination, content, operations = DEFAULT_FILE_OPERATIONS, beforeRename = async () => undefined) {
|
|
150
|
+
await operations.mkdir(path.dirname(destination), { recursive: true });
|
|
151
|
+
const temp = `${destination}.tmp-${process.pid}-${operations.randomId()}`;
|
|
152
|
+
let renamed = false;
|
|
153
|
+
try {
|
|
154
|
+
await operations.writeFile(temp, content, { flag: "wx" });
|
|
155
|
+
await beforeRename();
|
|
156
|
+
await operations.rename(temp, destination);
|
|
157
|
+
renamed = true;
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
if (!renamed)
|
|
161
|
+
await operations.rm(temp, { force: true }).catch(() => { });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function removeManagedProfile(projectRoot, destination, report, operations) {
|
|
165
|
+
const inspected = await inspectProfileDestination(projectRoot, destination, operations);
|
|
166
|
+
if (inspected.kind === "absent")
|
|
167
|
+
return;
|
|
168
|
+
if (inspected.kind === "conflict") {
|
|
169
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: optional adapter conflict (${inspected.reason})`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const existing = await operations.readFile(destination, "utf8");
|
|
173
|
+
if (!hasManagedMarker(existing)) {
|
|
174
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: user-owned (managed marker absent)`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const current = await inspectProfileDestination(projectRoot, destination, operations);
|
|
178
|
+
if (current.kind !== "regular" ||
|
|
179
|
+
(await operations.readFile(destination, "utf8")) !== existing) {
|
|
180
|
+
report.skipped.push(`${LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH}: optional adapter changed before disable`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await operations.rm(destination, { force: true });
|
|
184
|
+
report.changed.push(LONG_TASK_CODEX_AGENT_PROFILE_RELATIVE_PATH);
|
|
185
|
+
}
|
|
186
|
+
async function readValidPackageProfile(operations) {
|
|
187
|
+
const source = packageAssetPath(...ASSET_SEGMENTS);
|
|
188
|
+
const sourceStat = await lstatOrNull(source, operations);
|
|
189
|
+
if (!sourceStat)
|
|
190
|
+
return { valid: false, reason: "unavailable" };
|
|
191
|
+
if (sourceStat.isSymbolicLink() || !sourceStat.isFile())
|
|
192
|
+
return { valid: false, reason: "is not a regular file" };
|
|
193
|
+
const content = await operations.readFile(source, "utf8");
|
|
194
|
+
const validation = parseAndValidateLongTaskCodexAgentProfile(content);
|
|
195
|
+
if (!validation.valid)
|
|
196
|
+
return {
|
|
197
|
+
valid: false,
|
|
198
|
+
reason: `is invalid (${validation.errors.join(",")})`,
|
|
199
|
+
};
|
|
200
|
+
return { valid: true, content };
|
|
201
|
+
}
|
|
202
|
+
async function inspectProfileDestination(projectRoot, destination, operations) {
|
|
203
|
+
const lexicalRoot = path.resolve(projectRoot);
|
|
204
|
+
const canonicalRoot = await operations.realpath(lexicalRoot);
|
|
205
|
+
let cursor = lexicalRoot;
|
|
206
|
+
for (const segment of [".codex", "agents"]) {
|
|
207
|
+
cursor = path.join(cursor, segment);
|
|
208
|
+
const status = await lstatOrNull(cursor, operations);
|
|
209
|
+
if (!status)
|
|
210
|
+
continue;
|
|
211
|
+
if (status.isSymbolicLink())
|
|
212
|
+
return { kind: "conflict", reason: `parent_symlink:${segment}` };
|
|
213
|
+
if (!status.isDirectory())
|
|
214
|
+
return { kind: "conflict", reason: `parent_not_directory:${segment}` };
|
|
215
|
+
if (!inside(canonicalRoot, await operations.realpath(cursor)))
|
|
216
|
+
return {
|
|
217
|
+
kind: "conflict",
|
|
218
|
+
reason: `parent_outside_repository:${segment}`,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const status = await lstatOrNull(destination, operations);
|
|
222
|
+
if (!status)
|
|
223
|
+
return { kind: "absent" };
|
|
224
|
+
if (status.isSymbolicLink())
|
|
225
|
+
return { kind: "conflict", reason: "destination_symlink" };
|
|
226
|
+
if (!status.isFile())
|
|
227
|
+
return { kind: "conflict", reason: "destination_not_regular_file" };
|
|
228
|
+
if (!inside(canonicalRoot, await operations.realpath(destination)))
|
|
229
|
+
return { kind: "conflict", reason: "destination_outside_repository" };
|
|
230
|
+
return { kind: "regular" };
|
|
231
|
+
}
|
|
232
|
+
function operationsWith(overrides) {
|
|
233
|
+
return { ...DEFAULT_FILE_OPERATIONS, ...overrides };
|
|
234
|
+
}
|
|
235
|
+
async function lstatOrNull(target, operations) {
|
|
236
|
+
try {
|
|
237
|
+
return await operations.lstat(target);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
if (code(error) === "ENOENT")
|
|
241
|
+
return null;
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function inside(root, candidate) {
|
|
246
|
+
const relative = path.relative(root, candidate);
|
|
247
|
+
return (relative === "" ||
|
|
248
|
+
(!relative.startsWith(`..${path.sep}`) &&
|
|
249
|
+
relative !== ".." &&
|
|
250
|
+
!path.isAbsolute(relative)));
|
|
251
|
+
}
|
|
252
|
+
function record(value) {
|
|
253
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
254
|
+
? value
|
|
255
|
+
: null;
|
|
256
|
+
}
|
|
257
|
+
function nonEmptyString(value) {
|
|
258
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
259
|
+
}
|
|
260
|
+
function staticString(value) {
|
|
261
|
+
return (nonEmptyString(value) &&
|
|
262
|
+
value === value.trim() &&
|
|
263
|
+
!/[\r\n$%{}]/u.test(value));
|
|
264
|
+
}
|
|
265
|
+
function hasManagedMarker(content) {
|
|
266
|
+
return (content.replace(/\r\n/gu, "\n").split("\n", 1)[0] ===
|
|
267
|
+
LONG_TASK_CODEX_AGENT_PROFILE_MANAGED_MARKER);
|
|
268
|
+
}
|
|
269
|
+
function code(error) {
|
|
270
|
+
return typeof error === "object" && error !== null && "code" in error
|
|
271
|
+
? String(error.code)
|
|
272
|
+
: "";
|
|
273
|
+
}
|
|
274
|
+
function message(error) {
|
|
275
|
+
return error instanceof Error ? error.message : String(error);
|
|
276
|
+
}
|