project-tiny-context-harness 0.8.11 → 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 -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-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
|
@@ -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
|
}
|
|
@@ -3,3 +3,5 @@ import type { PlaywrightCase } from "./long-task-playwright-case-evidence.js";
|
|
|
3
3
|
export declare function evidenceRecordsForPlaywrightCases(check: CompiledCheckV2, cases: PlaywrightCase[]): EvidenceCapabilityRecordV2[];
|
|
4
4
|
export declare function semanticFactAttachmentName(proofRef: string): string;
|
|
5
5
|
export declare function designMethodAttachmentName(target: string, method: string, condition: string, kind: "record" | "observation"): string;
|
|
6
|
+
export declare function symbolicDesignMethodAttachmentName(target: string, method: string): string;
|
|
7
|
+
export declare function symbolicDesignCertificateAttachmentName(target: string): string;
|
|
@@ -8,7 +8,7 @@ export function evidenceRecordsForPlaywrightCases(check, cases) {
|
|
|
8
8
|
].find((candidate) => candidate.key === item.id);
|
|
9
9
|
if (!assertion)
|
|
10
10
|
continue;
|
|
11
|
-
records.push(...baseEvidenceRecords(check, item, assertion), ...designConformanceRecords(check, item, assertion), ...designMethodRecords(check, item, assertion), ...semanticFactRecords(check, item, assertion));
|
|
11
|
+
records.push(...baseEvidenceRecords(check, item, assertion), ...designConformanceRecords(check, item, assertion), ...designMethodRecords(check, item, assertion), ...symbolicDesignEvidenceRecords(check, item, assertion), ...semanticFactRecords(check, item, assertion));
|
|
12
12
|
}
|
|
13
13
|
return records;
|
|
14
14
|
}
|
|
@@ -41,7 +41,8 @@ function designConformanceRecords(check, item, assertion) {
|
|
|
41
41
|
return [];
|
|
42
42
|
return (check.design_conformance_targets ?? [])
|
|
43
43
|
.filter((candidate) => candidate.conformance_assertion_ref === assertion.key ||
|
|
44
|
-
candidate.verification_method_bindings.some((binding) => binding.assertion_ref === assertion.key)
|
|
44
|
+
candidate.verification_method_bindings.some((binding) => binding.assertion_ref === assertion.key) ||
|
|
45
|
+
(candidate.symbolic_method_bindings ?? []).some((binding) => binding.assertion_ref === assertion.key))
|
|
45
46
|
.map((target) => ({
|
|
46
47
|
assertion_key: assertion.key,
|
|
47
48
|
capability: "design_conformance",
|
|
@@ -58,6 +59,8 @@ function designMethodRecords(check, item, assertion) {
|
|
|
58
59
|
return [];
|
|
59
60
|
const records = [];
|
|
60
61
|
for (const target of check.design_conformance_targets ?? []) {
|
|
62
|
+
if (target.fact_model === "symbolic_rules_v2")
|
|
63
|
+
continue;
|
|
61
64
|
const binding = target.verification_method_bindings.find((candidate) => candidate.assertion_ref === assertion.key);
|
|
62
65
|
if (!binding)
|
|
63
66
|
continue;
|
|
@@ -93,6 +96,69 @@ function designMethodRecords(check, item, assertion) {
|
|
|
93
96
|
}
|
|
94
97
|
return records;
|
|
95
98
|
}
|
|
99
|
+
function symbolicDesignEvidenceRecords(check, item, assertion) {
|
|
100
|
+
if (!item.executed)
|
|
101
|
+
return [];
|
|
102
|
+
const records = [];
|
|
103
|
+
for (const target of check.design_conformance_targets ?? []) {
|
|
104
|
+
if (target.fact_model !== "symbolic_rules_v2")
|
|
105
|
+
continue;
|
|
106
|
+
records.push(...symbolicMethodEvidenceRecords(target, item, assertion));
|
|
107
|
+
const certificate = symbolicCertificateEvidenceRecord(target, item, assertion);
|
|
108
|
+
if (certificate)
|
|
109
|
+
records.push(certificate);
|
|
110
|
+
}
|
|
111
|
+
return records;
|
|
112
|
+
}
|
|
113
|
+
function symbolicMethodEvidenceRecords(target, item, assertion) {
|
|
114
|
+
if (!assertion.evidence_capabilities.includes("design_method"))
|
|
115
|
+
return [];
|
|
116
|
+
const records = [];
|
|
117
|
+
for (const binding of target.symbolic_method_bindings ?? []) {
|
|
118
|
+
if (binding.assertion_ref !== assertion.key)
|
|
119
|
+
continue;
|
|
120
|
+
const attachmentName = symbolicDesignMethodAttachmentName(target.key, binding.method);
|
|
121
|
+
if (!item.attachment_names.includes(attachmentName))
|
|
122
|
+
continue;
|
|
123
|
+
const record = typedEvidenceAttachment(item.attachment_payloads[attachmentName], "design_method");
|
|
124
|
+
if (record?.capability === "design_method" &&
|
|
125
|
+
"fact_model" in record &&
|
|
126
|
+
record.assertion_key === assertion.key &&
|
|
127
|
+
record.design_target_ref === target.key &&
|
|
128
|
+
record.method === binding.method)
|
|
129
|
+
records.push(record);
|
|
130
|
+
}
|
|
131
|
+
return records;
|
|
132
|
+
}
|
|
133
|
+
function symbolicCertificateEvidenceRecord(target, item, assertion) {
|
|
134
|
+
const binding = target.symbolic_certificate_binding;
|
|
135
|
+
if (binding?.assertion_ref !== assertion.key ||
|
|
136
|
+
!assertion.evidence_capabilities.includes("design_symbolic_certificate"))
|
|
137
|
+
return null;
|
|
138
|
+
const attachmentName = symbolicDesignCertificateAttachmentName(target.key);
|
|
139
|
+
if (!item.attachment_names.includes(attachmentName))
|
|
140
|
+
return null;
|
|
141
|
+
const record = typedEvidenceAttachment(item.attachment_payloads[attachmentName], "design_symbolic_certificate");
|
|
142
|
+
return record?.capability === "design_symbolic_certificate" &&
|
|
143
|
+
record.assertion_key === assertion.key &&
|
|
144
|
+
record.design_target_ref === target.key
|
|
145
|
+
? record
|
|
146
|
+
: null;
|
|
147
|
+
}
|
|
148
|
+
function typedEvidenceAttachment(payload, capability) {
|
|
149
|
+
if (!payload)
|
|
150
|
+
return null;
|
|
151
|
+
try {
|
|
152
|
+
const records = decodeEvidenceCapabilityRecords([JSON.parse(payload)]);
|
|
153
|
+
const record = records[0];
|
|
154
|
+
return records.length === 1 && record.capability === capability
|
|
155
|
+
? record
|
|
156
|
+
: null;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
96
162
|
function semanticFactRecords(check, item, assertion) {
|
|
97
163
|
if (!item.executed ||
|
|
98
164
|
!assertion.evidence_capabilities.includes("semantic_fact"))
|
|
@@ -144,3 +210,9 @@ function designFactResultAttachment(content, label) {
|
|
|
144
210
|
export function designMethodAttachmentName(target, method, condition, kind) {
|
|
145
211
|
return `ty-context-design-method:${target}:${method}:${condition}:${kind}`;
|
|
146
212
|
}
|
|
213
|
+
export function symbolicDesignMethodAttachmentName(target, method) {
|
|
214
|
+
return `ty-context-design-symbolic-method:${target}:${method}:record`;
|
|
215
|
+
}
|
|
216
|
+
export function symbolicDesignCertificateAttachmentName(target) {
|
|
217
|
+
return `ty-context-design-symbolic-certificate:${target}:record`;
|
|
218
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { CompiledCheckV2, CompiledDesignTargetV2, DeliveryCheckV2, ExecutionTargetV2, SemanticFactExpectationV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
|
|
2
|
-
export declare function freezeDeliveryCheck(check: DeliveryCheckV2, outcomeKey: string | null, repository: string, baseline: WorkspaceManifestV2, executionTarget: ExecutionTargetV2, knownExecutionTargets: ExecutionTargetV2[], designConformanceTargets: CompiledDesignTargetV2[], semanticFactExpectations: SemanticFactExpectationV2[]): Promise<CompiledCheckV2>;
|
|
2
|
+
export declare function freezeDeliveryCheck(check: DeliveryCheckV2, outcomeKey: string | null, repository: string, baseline: WorkspaceManifestV2, executionTarget: ExecutionTargetV2, knownExecutionTargets: ExecutionTargetV2[], designConformanceTargets: CompiledDesignTargetV2[], semanticFactExpectations: SemanticFactExpectationV2[], protectedAuthorityPaths?: readonly string[]): Promise<CompiledCheckV2>;
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { computeRawExecutionIdentity } from "./long-task-check-execution-policy.js";
|
|
4
|
-
import { assertRepositoryPattern, classifyRepositoryPatternOverlap, matchesRepoPattern, } from "./long-task-paths.js";
|
|
4
|
+
import { assertRepositoryPattern, classifyRepositoryPatternOverlap, matchesRepoPattern, normalizeRepositoryFile, } from "./long-task-paths.js";
|
|
5
5
|
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
6
6
|
import { nearestRunnerFile, npmCliPath, npxCliPath, } from "./long-task-runner-files.js";
|
|
7
7
|
import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
|
|
8
8
|
import { repoRelative, resolveInsideRepository, } from "./long-task-workspace.js";
|
|
9
9
|
import { evidenceAdapterForRunner } from "./long-task-evidence-adapter-policy.js";
|
|
10
10
|
import { freezeLocalVerifierDependencyClosure, packageScriptVerifierRoots, } from "./long-task-verifier-dependency-closure.js";
|
|
11
|
-
export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets, designConformanceTargets, semanticFactExpectations) {
|
|
11
|
+
export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets, designConformanceTargets, semanticFactExpectations, protectedAuthorityPaths = []) {
|
|
12
12
|
const prefix = outcomeKey ? `CHECK.${outcomeKey}` : "CHECK.GLOBAL";
|
|
13
13
|
const expectedOutputs = check.expected_output_paths.map((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.expected_output_paths[${index}]`));
|
|
14
|
+
const protectedAuthorityFiles = protectedAuthorityPaths.map((file, index) => normalizeRepositoryFile(file, `${check.key}.protected_authority_paths[${index}]`));
|
|
14
15
|
for (const [index, pattern] of check.input_paths.entries()) {
|
|
15
16
|
const normalized = assertRepositoryPattern(repository, pattern, `${check.key}.input_paths[${index}]`);
|
|
16
17
|
if (!baseline.files.some((file) => matchesRepoPattern(file.path, normalized)) &&
|
|
18
|
+
!protectedAuthorityFiles.some((file) => matchesRepoPattern(file, normalized)) &&
|
|
17
19
|
!expectedOutputs.some((output) => classifyRepositoryPatternOverlap(output, normalized).status ===
|
|
18
20
|
"proven_overlap"))
|
|
19
21
|
throw new Error(`input_path_not_found:${check.key}:${pattern}`);
|
|
@@ -42,7 +42,7 @@ export interface ClaimApplicabilityV2 {
|
|
|
42
42
|
given_refs: string[];
|
|
43
43
|
when_refs: string[];
|
|
44
44
|
}
|
|
45
|
-
export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "design_conformance" | "design_method" | "semantic_fact" | "target_runtime" | "input_variation";
|
|
45
|
+
export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "design_conformance" | "design_method" | "design_symbolic_certificate" | "semantic_fact" | "target_runtime" | "input_variation";
|
|
46
46
|
export interface CheckExecutionTargetV2 {
|
|
47
47
|
target_ref: string;
|
|
48
48
|
entrypoint: "root" | "internal";
|
|
@@ -8,11 +8,13 @@ export interface SemanticFactManifestRefV2 {
|
|
|
8
8
|
}
|
|
9
9
|
export interface SemanticFactBindingV2 {
|
|
10
10
|
fact_ref: string;
|
|
11
|
+
fact_revision_digest?: string;
|
|
11
12
|
claim_ref: string;
|
|
12
13
|
applicability_ref: string;
|
|
13
14
|
}
|
|
14
15
|
export type SemanticFactProofBindingV2 = {
|
|
15
16
|
proof_ref: string;
|
|
17
|
+
obligation_revision_digest?: string;
|
|
16
18
|
fact_ref: string;
|
|
17
19
|
method: string;
|
|
18
20
|
proof_surface: ProofSurface;
|
|
@@ -22,6 +24,7 @@ export type SemanticFactProofBindingV2 = {
|
|
|
22
24
|
assertion_ref: string;
|
|
23
25
|
} | {
|
|
24
26
|
proof_ref: string;
|
|
27
|
+
obligation_revision_digest?: string;
|
|
25
28
|
fact_ref: string;
|
|
26
29
|
method: string;
|
|
27
30
|
proof_surface: ProofSurface;
|
|
@@ -37,6 +40,11 @@ export interface SemanticFactOutcomeBindingsV2 {
|
|
|
37
40
|
export interface SemanticFactExpectationV2 {
|
|
38
41
|
manifest_ref: string;
|
|
39
42
|
manifest_sha256: string;
|
|
43
|
+
fact_key: string;
|
|
44
|
+
fact_revision_digest: string;
|
|
45
|
+
obligation_key: string;
|
|
46
|
+
obligation_revision_digest: string;
|
|
47
|
+
revision_identity_required: boolean;
|
|
40
48
|
fact_ref: string;
|
|
41
49
|
proof_ref: string;
|
|
42
50
|
method: string;
|
|
@@ -14,7 +14,10 @@ export async function validateLongTaskSemanticFactClosure(contract, repository,
|
|
|
14
14
|
await validateSemanticFactInputInventory(repository, sourceItems, contextFiles, manifest, designOwnedSourceItems);
|
|
15
15
|
validateSemanticFactBasisClosure(manifest, sourceItems);
|
|
16
16
|
await validateSemanticFactLocatedValues(repository, manifest, sourceItems);
|
|
17
|
-
const expectations = validateSemanticFactContractProjection(contract, manifest, index)
|
|
17
|
+
const expectations = validateSemanticFactContractProjection(contract, manifest, index, new Map(parsed.fact_revisions.map((item) => [item.key, item.revision_digest])), new Map(parsed.obligation_revisions.map((item) => [
|
|
18
|
+
item.key,
|
|
19
|
+
item.revision_digest,
|
|
20
|
+
])), parsed.carrier === "compact_v1");
|
|
18
21
|
return {
|
|
19
22
|
manifest,
|
|
20
23
|
manifest_sha256: parsed.sha256,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { DeliveryContractV2 } from "./long-task-delivery-types.js";
|
|
2
2
|
import type { SemanticFactManifestIndexV1 } from "./semantic-fact-policy.js";
|
|
3
3
|
import type { SemanticFactExpectationV2, SemanticFactManifestV1 } from "./semantic-fact-types.js";
|
|
4
|
-
export declare function validateSemanticFactContractProjection(contract: DeliveryContractV2, manifest: SemanticFactManifestV1, index: SemanticFactManifestIndexV1): Map<string, SemanticFactExpectationV2[]>;
|
|
4
|
+
export declare function validateSemanticFactContractProjection(contract: DeliveryContractV2, manifest: SemanticFactManifestV1, index: SemanticFactManifestIndexV1, factRevisions: Map<string, string>, obligationRevisions: Map<string, string>, sourceRequiresRevisions: boolean): Map<string, SemanticFactExpectationV2[]>;
|