project-tiny-context-harness 0.7.3 → 0.7.5

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.
Files changed (105) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +355 -343
  3. package/assets/README.md +539 -494
  4. package/assets/README.zh-CN.md +300 -273
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +55 -53
  7. package/assets/context_templates/architecture.md +33 -33
  8. package/assets/context_templates/area.md +39 -39
  9. package/assets/context_templates/context.toml +30 -30
  10. package/assets/context_templates/deployment.md +35 -35
  11. package/assets/context_templates/global.md +51 -51
  12. package/assets/context_templates/product-surface-contract.md +64 -57
  13. package/assets/context_templates/screen-contract.md +180 -0
  14. package/assets/context_templates/verification.md +32 -32
  15. package/assets/github/.gitkeep +1 -1
  16. package/assets/github/harness.yml +41 -41
  17. package/assets/make/.gitkeep +1 -1
  18. package/assets/make/ty-context.mk +48 -48
  19. package/assets/skills/context_development_engineer/SKILL.md +92 -90
  20. package/assets/skills/context_full_project_export/SKILL.md +70 -70
  21. package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
  22. package/assets/skills/context_product_plan/SKILL.md +77 -76
  23. package/assets/skills/context_surface_contract/SKILL.md +177 -162
  24. package/assets/skills/context_uiux_design/SKILL.md +108 -91
  25. package/assets/skills/long-task-workflow/SKILL.md +83 -83
  26. package/assets/skills/long-task-workflow/agents/openai.yaml +4 -4
  27. package/assets/skills/long-task-workflow/references/authority-lifecycle.md +57 -53
  28. package/assets/skills/long-task-workflow/references/contract-authoring.md +95 -77
  29. package/assets/skills/long-task-workflow/references/evidence-design.md +71 -58
  30. package/assets/skills/normal-long-task/SKILL.md +12 -12
  31. package/assets/skills/source-plan-authoring/SKILL.md +293 -290
  32. package/dist/commands/long-task-authoring.js +25 -0
  33. package/dist/commands/long-task.js +3 -0
  34. package/dist/lib/design-md.d.ts +7 -0
  35. package/dist/lib/design-md.js +47 -6
  36. package/dist/lib/doctor.js +19 -4
  37. package/dist/lib/long-task-activation-validation.js +13 -2
  38. package/dist/lib/long-task-authoring-authority-preview.js +1 -0
  39. package/dist/lib/long-task-authority-material-diff.js +54 -0
  40. package/dist/lib/long-task-authority-materials.d.ts +2 -2
  41. package/dist/lib/long-task-authority-materials.js +20 -0
  42. package/dist/lib/long-task-authority-policy.d.ts +26 -0
  43. package/dist/lib/long-task-authority-policy.js +23 -0
  44. package/dist/lib/long-task-authority-revision-analysis.d.ts +33 -0
  45. package/dist/lib/long-task-authority-revision-analysis.js +91 -0
  46. package/dist/lib/long-task-authority-revision.js +93 -158
  47. package/dist/lib/long-task-authority-types.d.ts +21 -0
  48. package/dist/lib/long-task-authority.js +32 -3
  49. package/dist/lib/long-task-check-evidence-decoder.d.ts +2 -2
  50. package/dist/lib/long-task-check-evidence-decoder.js +11 -1
  51. package/dist/lib/long-task-check-execution-policy.d.ts +3 -0
  52. package/dist/lib/long-task-check-execution-policy.js +5 -0
  53. package/dist/lib/long-task-check-runner.js +2 -0
  54. package/dist/lib/long-task-check-shape.js +33 -3
  55. package/dist/lib/long-task-claim-definitions.js +14 -0
  56. package/dist/lib/long-task-conformance-policy.d.ts +5 -0
  57. package/dist/lib/long-task-conformance-policy.js +35 -0
  58. package/dist/lib/long-task-contract-types.d.ts +28 -4
  59. package/dist/lib/long-task-delivery-compiler.js +1 -0
  60. package/dist/lib/long-task-delivery-parser.js +5 -2
  61. package/dist/lib/long-task-delivery-types.d.ts +2 -0
  62. package/dist/lib/long-task-delivery-types.js +2 -0
  63. package/dist/lib/long-task-delivery-validation.js +11 -0
  64. package/dist/lib/long-task-evidence-capability-codec.d.ts +2 -0
  65. package/dist/lib/long-task-evidence-capability-codec.js +231 -0
  66. package/dist/lib/long-task-evidence-capability-policy.d.ts +8 -0
  67. package/dist/lib/long-task-evidence-capability-policy.js +147 -0
  68. package/dist/lib/long-task-evidence-capability-runtime.d.ts +2 -0
  69. package/dist/lib/long-task-evidence-capability-runtime.js +86 -0
  70. package/dist/lib/long-task-evidence-capability-types.d.ts +74 -0
  71. package/dist/lib/long-task-evidence-capability-types.js +1 -0
  72. package/dist/lib/long-task-evidence-findings.js +5 -1
  73. package/dist/lib/long-task-evidence-v2.js +38 -23
  74. package/dist/lib/long-task-final-v2.js +42 -1
  75. package/dist/lib/long-task-outcome-parser.js +14 -3
  76. package/dist/lib/long-task-playwright-evidence.d.ts +2 -1
  77. package/dist/lib/long-task-playwright-evidence.js +70 -2
  78. package/dist/lib/long-task-product-shape.js +28 -0
  79. package/dist/lib/long-task-progress.js +4 -0
  80. package/dist/lib/long-task-root-shape.d.ts +1 -0
  81. package/dist/lib/long-task-root-shape.js +84 -3
  82. package/dist/lib/long-task-runner-environment.js +1 -1
  83. package/dist/lib/long-task-runner-freeze.d.ts +2 -2
  84. package/dist/lib/long-task-runner-freeze.js +3 -1
  85. package/dist/lib/long-task-runtime-types.d.ts +13 -0
  86. package/dist/lib/long-task-semantic-contract-types.d.ts +36 -0
  87. package/dist/lib/long-task-semantic-contract-types.js +1 -0
  88. package/dist/lib/long-task-semantic-drift-migration.d.ts +3 -0
  89. package/dist/lib/long-task-semantic-drift-migration.js +68 -0
  90. package/dist/lib/long-task-shape-primitives.d.ts +3 -0
  91. package/dist/lib/long-task-shape-primitives.js +25 -0
  92. package/dist/lib/long-task-source-target-index.js +14 -0
  93. package/dist/lib/long-task-stage-policy.d.ts +4 -0
  94. package/dist/lib/long-task-stage-policy.js +120 -0
  95. package/dist/lib/long-task-status-projection.d.ts +4 -1
  96. package/dist/lib/long-task-status-projection.js +63 -3
  97. package/dist/lib/long-task-status-v2.d.ts +11 -1
  98. package/dist/lib/long-task-status-v2.js +25 -3
  99. package/dist/lib/long-task-target-policy.d.ts +6 -0
  100. package/dist/lib/long-task-target-policy.js +127 -0
  101. package/dist/lib/migrations.js +29 -0
  102. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +62 -8
  103. package/migrations/README.md +15 -8
  104. package/package.json +2 -2
  105. package/source-mappings.yaml +25 -25
@@ -24,24 +24,52 @@ export function parseControls(value, label) {
24
24
  return array(value, label).map((item, index) => {
25
25
  const itemLabel = `${label}[${index}]`;
26
26
  const row = object(item, itemLabel, ["key", "location"], [
27
+ "surface",
28
+ "region",
29
+ "control_type",
30
+ "label_content",
31
+ "user_task",
32
+ "visibility",
33
+ "availability",
27
34
  "trigger",
28
35
  "input",
36
+ "validation",
37
+ "default_value",
38
+ "interaction",
39
+ "navigation_result",
29
40
  "loading_state",
30
41
  "empty_state",
31
42
  "success_state",
32
43
  "failure_state",
44
+ "recovery",
45
+ "permission",
33
46
  "feedback",
47
+ "accessibility",
34
48
  ]);
35
49
  return {
36
50
  key: key(row.key, `${itemLabel}.key`),
51
+ surface: optionalText(row, "surface", itemLabel),
52
+ region: optionalText(row, "region", itemLabel),
37
53
  location: string(row.location, `${itemLabel}.location`),
54
+ control_type: optionalText(row, "control_type", itemLabel),
55
+ label_content: optionalText(row, "label_content", itemLabel),
56
+ user_task: optionalText(row, "user_task", itemLabel),
57
+ visibility: optionalText(row, "visibility", itemLabel),
58
+ availability: optionalText(row, "availability", itemLabel),
38
59
  trigger: optionalText(row, "trigger", itemLabel),
39
60
  input: optionalText(row, "input", itemLabel),
61
+ validation: optionalText(row, "validation", itemLabel),
62
+ default_value: optionalText(row, "default_value", itemLabel),
63
+ interaction: optionalText(row, "interaction", itemLabel),
64
+ navigation_result: optionalText(row, "navigation_result", itemLabel),
40
65
  loading_state: optionalText(row, "loading_state", itemLabel),
41
66
  empty_state: optionalText(row, "empty_state", itemLabel),
42
67
  success_state: optionalText(row, "success_state", itemLabel),
43
68
  failure_state: optionalText(row, "failure_state", itemLabel),
69
+ recovery: optionalText(row, "recovery", itemLabel),
70
+ permission: optionalText(row, "permission", itemLabel),
44
71
  feedback: optionalText(row, "feedback", itemLabel),
72
+ accessibility: optionalText(row, "accessibility", itemLabel),
45
73
  };
46
74
  });
47
75
  }
@@ -76,6 +76,10 @@ export function checkIdentity(check) {
76
76
  artifact_globs: check.artifact_globs,
77
77
  positive_assertions: check.positive_assertions,
78
78
  negative_assertions: check.negative_assertions,
79
+ journey_roles: check.journey_roles,
80
+ execution_target: check.execution_target,
81
+ execution_target_definition: check.execution_target_definition,
82
+ scenario: check.scenario,
79
83
  environment_requirements: check.environment_requirements,
80
84
  }));
81
85
  }
@@ -1,4 +1,5 @@
1
1
  import type { DeliveryContractV2 } from "./long-task-delivery-types.js";
2
2
  export declare function parseTask(value: unknown): DeliveryContractV2["task"];
3
+ export declare function parseStages(value: unknown): DeliveryContractV2["stages"];
3
4
  export declare function parseRisk(value: unknown): DeliveryContractV2["risk"];
4
5
  export declare function parseGlobal(value: unknown): DeliveryContractV2["global"];
@@ -1,6 +1,6 @@
1
1
  import { parseGlobalCounterfactuals } from "./long-task-acceptance-shape.js";
2
2
  import { parseCheck } from "./long-task-check-shape.js";
3
- import { array, key, literal, object, parseKeyedPaths, parseKeyedStatements, repositoryFiles, string, strings, } from "./long-task-delivery-shape.js";
3
+ import { array, boolean, key, literal, object, parseKeyedPaths, parseKeyedStatements, repositoryFiles, string, strings, } from "./long-task-delivery-shape.js";
4
4
  const RISK_FACTS = [
5
5
  "public_api_or_schema_change",
6
6
  "persistent_data_change",
@@ -14,11 +14,59 @@ const RISK_FACTS = [
14
14
  "weak_observability",
15
15
  ];
16
16
  export function parseTask(value) {
17
- const row = object(value, "task", ["id", "title", "goal", "source_paths", "context_refs"], ["context_snapshot_mode"]);
17
+ const row = object(value, "task", [
18
+ "id",
19
+ "title",
20
+ "goal",
21
+ "target_profile",
22
+ "execution_targets",
23
+ "source_paths",
24
+ "context_refs",
25
+ ], ["context_snapshot_mode"]);
26
+ const targetProfile = object(row.target_profile, "task.target_profile", [
27
+ "key",
28
+ "description",
29
+ "required_state",
30
+ "required_target_refs",
31
+ ]);
18
32
  return {
19
33
  id: key(row.id, "task.id"),
20
34
  title: string(row.title, "task.title"),
21
35
  goal: string(row.goal, "task.goal"),
36
+ target_profile: {
37
+ key: key(targetProfile.key, "task.target_profile.key"),
38
+ description: string(targetProfile.description, "task.target_profile.description"),
39
+ required_state: literal(targetProfile.required_state, [
40
+ "implementation_complete",
41
+ "target_profile_usable",
42
+ "production_release_ready",
43
+ ], "task.target_profile.required_state"),
44
+ required_target_refs: strings(targetProfile.required_target_refs, "task.target_profile.required_target_refs").map((item, index) => key(item, `task.target_profile.required_target_refs[${index}]`)),
45
+ },
46
+ execution_targets: array(row.execution_targets, "task.execution_targets").map((item, index) => {
47
+ const label = `task.execution_targets[${index}]`;
48
+ const target = object(item, label, [
49
+ "key",
50
+ "description",
51
+ "role",
52
+ "runtime_family",
53
+ "root_entrypoint",
54
+ ]);
55
+ return {
56
+ key: key(target.key, `${label}.key`),
57
+ description: string(target.description, `${label}.description`),
58
+ role: literal(target.role, ["product", "support", "observer"], `${label}.role`),
59
+ runtime_family: literal(target.runtime_family, [
60
+ "browser",
61
+ "native",
62
+ "desktop",
63
+ "service",
64
+ "process",
65
+ "external",
66
+ ], `${label}.runtime_family`),
67
+ root_entrypoint: string(target.root_entrypoint, `${label}.root_entrypoint`),
68
+ };
69
+ }),
22
70
  source_paths: repositoryFiles(row.source_paths, "task.source_paths"),
23
71
  context_refs: repositoryFiles(row.context_refs, "task.context_refs"),
24
72
  context_snapshot_mode: Object.hasOwn(row, "context_snapshot_mode")
@@ -26,6 +74,23 @@ export function parseTask(value) {
26
74
  : "referenced",
27
75
  };
28
76
  }
77
+ export function parseStages(value) {
78
+ return array(value, "stages").map((item, index) => {
79
+ const label = `stages[${index}]`;
80
+ const row = object(item, label, [
81
+ "key",
82
+ "title",
83
+ "depends_on",
84
+ "gate_outcome",
85
+ ]);
86
+ return {
87
+ key: key(row.key, `${label}.key`),
88
+ title: string(row.title, `${label}.title`),
89
+ depends_on: strings(row.depends_on, `${label}.depends_on`).map((entry, dependencyIndex) => key(entry, `${label}.depends_on[${dependencyIndex}]`)),
90
+ gate_outcome: key(row.gate_outcome, `${label}.gate_outcome`),
91
+ };
92
+ });
93
+ }
29
94
  export function parseRisk(value) {
30
95
  const row = object(value, "risk", ["facts"], ["requested_level"]);
31
96
  const facts = object(row.facts, "risk.facts", [], [...RISK_FACTS]);
@@ -73,11 +138,27 @@ export function parseGlobal(value) {
73
138
  external_confirmations: Object.hasOwn(acceptance, "external_confirmations")
74
139
  ? array(acceptance.external_confirmations, "global.acceptance.external_confirmations").map((item, index) => {
75
140
  const label = `global.acceptance.external_confirmations[${index}]`;
76
- const entry = object(item, label, ["key", "description", "owner"]);
141
+ const entry = object(item, label, [
142
+ "key",
143
+ "description",
144
+ "owner",
145
+ "kind",
146
+ "impact_claims",
147
+ "blocks_target",
148
+ ]);
77
149
  return {
78
150
  key: key(entry.key, `${label}.key`),
79
151
  description: string(entry.description, `${label}.description`),
80
152
  owner: string(entry.owner, `${label}.owner`),
153
+ kind: literal(entry.kind, [
154
+ "functional_prerequisite",
155
+ "field_validation",
156
+ "production_release_gate",
157
+ "commercial_activation",
158
+ "expert_authority",
159
+ ], `${label}.kind`),
160
+ impact_claims: strings(entry.impact_claims, `${label}.impact_claims`),
161
+ blocks_target: boolean(entry.blocks_target, `${label}.blocks_target`),
81
162
  };
82
163
  })
83
164
  : [],
@@ -23,7 +23,7 @@ const BASE_ENVIRONMENT_KEYS = [
23
23
  ];
24
24
  export function runnerEnvironment(requirements) {
25
25
  const environment = {
26
- TY_CONTEXT_CHECK_PROTOCOL: "long-task-check-result-v2",
26
+ TY_CONTEXT_CHECK_PROTOCOL: "long-task-check-result-v3",
27
27
  };
28
28
  for (const key of BASE_ENVIRONMENT_KEYS)
29
29
  copyEnvironmentValue(environment, key);
@@ -1,2 +1,2 @@
1
- import type { CompiledCheckV2, DeliveryCheckV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
2
- export declare function freezeDeliveryCheck(check: DeliveryCheckV2, outcomeKey: string | null, repository: string, baseline: WorkspaceManifestV2): Promise<CompiledCheckV2>;
1
+ import type { CompiledCheckV2, DeliveryCheckV2, ExecutionTargetV2, 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[]): Promise<CompiledCheckV2>;
@@ -7,7 +7,7 @@ import { nearestRunnerFile, npmCliPath, npxCliPath, } from "./long-task-runner-f
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
- export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline) {
10
+ export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets) {
11
11
  const prefix = outcomeKey ? `CHECK.${outcomeKey}` : "CHECK.GLOBAL";
12
12
  const expectedOutputs = check.expected_output_paths.map((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.expected_output_paths[${index}]`));
13
13
  for (const [index, pattern] of check.input_paths.entries()) {
@@ -30,6 +30,8 @@ export async function freezeDeliveryCheck(check, outcomeKey, repository, baselin
30
30
  evidence_adapter: evidenceAdapterForRunner(check.runner.type),
31
31
  runner: await freezeRunner(check, repository, cwd, target, verificationInputHashes),
32
32
  verification_input_hashes: verificationInputHashes,
33
+ execution_target_definition: executionTarget,
34
+ known_execution_targets: knownExecutionTargets,
33
35
  };
34
36
  return {
35
37
  ...compiled,
@@ -1,6 +1,8 @@
1
1
  import type { DeliveryCheckV2, DeliveryContractV2, DeliveryOutcomeV2, DeliveryRunnerV2, ProofSurface } from "./long-task-contract-types.js";
2
+ import type { EvidenceCapabilityV2, ExecutionTargetV2 } from "./long-task-semantic-contract-types.js";
2
3
  import type { AuthorityHashesV2, ContextAuthoritySnapshotV2, InitialTaskBaseV2, NextAuthorityMaterialsV2, VerifierIdentityV2 } from "./long-task-authority-types.js";
3
4
  import type { EvidenceAdapter } from "./long-task-evidence-adapter-types.js";
5
+ import type { EvidenceCapabilityRecordV2 } from "./long-task-evidence-capability-types.js";
4
6
  import type { EffectiveRiskLevel, RiskFactName } from "./long-task-risk-types.js";
5
7
  import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
6
8
  import type { WorkspaceManifestV2 } from "./long-task-workspace-runtime-types.js";
@@ -21,6 +23,8 @@ export interface CompiledCheckV2 extends Omit<DeliveryCheckV2, "runner"> {
21
23
  evidence_adapter: EvidenceAdapter;
22
24
  verification_input_hashes: Record<string, string>;
23
25
  raw_execution_identity: string;
26
+ execution_target_definition: ExecutionTargetV2;
27
+ known_execution_targets: ExecutionTargetV2[];
24
28
  }
25
29
  export interface ProductClaimV2 {
26
30
  id: string;
@@ -88,6 +92,7 @@ export interface CompiledDeliveryContractV2 {
88
92
  task: DeliveryContractV2["task"];
89
93
  risk: DeliveryContractV2["risk"];
90
94
  source_claims: DeliveryContractV2["source_claims"];
95
+ stages: DeliveryContractV2["stages"];
91
96
  global: Omit<DeliveryContractV2["global"], "acceptance"> & {
92
97
  acceptance: {
93
98
  checks: CompiledCheckV2[];
@@ -123,6 +128,8 @@ export interface AssertionResultV2 {
123
128
  passed: boolean;
124
129
  claims: string[];
125
130
  observation: string;
131
+ evidence_capabilities: EvidenceCapabilityV2[];
132
+ evidence_complete: boolean;
126
133
  status: "passed" | "observation_missing" | "observation_type_mismatch" | "assertion_value_mismatch";
127
134
  expected?: unknown;
128
135
  actual?: unknown;
@@ -133,6 +140,7 @@ export interface RawCommandExecutionV2 {
133
140
  execution_status: "completed" | "blocked_external" | "infrastructure_error" | "invalid_evidence";
134
141
  exit_code: number;
135
142
  observations: Record<string, unknown>;
143
+ evidence_records: EvidenceCapabilityRecordV2[];
136
144
  stdout_sha256: string;
137
145
  stderr_sha256: string;
138
146
  attempts: number;
@@ -148,6 +156,7 @@ export interface CheckExecutionResultV2 {
148
156
  execution_identity: string;
149
157
  assertion_results: AssertionResultV2[];
150
158
  observations: Record<string, unknown>;
159
+ evidence_records: EvidenceCapabilityRecordV2[];
151
160
  artifact_hashes: Record<string, string>;
152
161
  claim_proofs: ClaimProofV2[];
153
162
  findings: LongTaskFindingV2[];
@@ -185,12 +194,16 @@ export interface TargetedVerificationResultV2 {
185
194
  completed_at: string;
186
195
  }
187
196
  export type OutcomeStatusV2 = "unverified" | "progress_passing" | "progress_failing" | "progress_stale" | "blocked_external";
197
+ export type StageStatusV2 = "locked" | "ready" | "unverified" | "progress_passing" | "progress_failing" | "progress_stale" | "blocked_external";
188
198
  export interface FinalReceiptV2 {
189
199
  schema_version: "long-task-final-receipt-v2";
190
200
  receipt_sha256: string;
191
201
  authority_scope: "audit_only";
192
202
  reusable_for_acceptance: false;
193
203
  workflow_status: "machine_accepted" | "machine_accepted_external_pending" | "needs_work" | "blocked_external";
204
+ target_profile: DeliveryContractV2["task"]["target_profile"];
205
+ target_state: DeliveryContractV2["task"]["target_profile"]["required_state"] | "not_accepted" | "blocked_external";
206
+ stage_results: Record<string, "passed" | "failed" | "blocked_external" | "blocked_dependency">;
194
207
  compiled_identity: string;
195
208
  contract_sha256: string;
196
209
  snapshot_sha256: string;
@@ -0,0 +1,36 @@
1
+ export interface KeyedStatementV2 {
2
+ key: string;
3
+ statement: string;
4
+ }
5
+ export type ExternalConfirmationKindV2 = "functional_prerequisite" | "field_validation" | "production_release_gate" | "commercial_activation" | "expert_authority";
6
+ export type TargetCompletionStateV2 = "implementation_complete" | "target_profile_usable" | "production_release_ready";
7
+ export type ExecutionTargetRuntimeFamilyV2 = "browser" | "native" | "desktop" | "service" | "process" | "external";
8
+ export interface TargetProfileV2 {
9
+ key: string;
10
+ description: string;
11
+ required_state: TargetCompletionStateV2;
12
+ required_target_refs: string[];
13
+ }
14
+ export interface ExecutionTargetV2 {
15
+ key: string;
16
+ description: string;
17
+ role: "product" | "support" | "observer";
18
+ runtime_family: ExecutionTargetRuntimeFamilyV2;
19
+ root_entrypoint: string;
20
+ }
21
+ export interface DeliveryStageV2 {
22
+ key: string;
23
+ title: string;
24
+ depends_on: string[];
25
+ gate_outcome: string;
26
+ }
27
+ export type DeliveryJourneyRoleV2 = "success" | "degradation" | "recovery" | "stage_gate" | "conformance";
28
+ export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "target_runtime" | "input_variation";
29
+ export interface CheckExecutionTargetV2 {
30
+ target_ref: string;
31
+ entrypoint: "root" | "internal";
32
+ }
33
+ export interface DeliveryScenarioV2 {
34
+ given: KeyedStatementV2[];
35
+ when: KeyedStatementV2[];
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare function semanticDriftMigrationFields(value: unknown): string[];
2
+ export declare function semanticDriftOutcomeMigrationFields(value: unknown, label: string): string[];
3
+ export declare function assertNoSemanticDriftMigration(fields: string[]): void;
@@ -0,0 +1,68 @@
1
+ export function semanticDriftMigrationFields(value) {
2
+ const root = row(value);
3
+ if (!root || root.schema_version !== "long-task-delivery-v2")
4
+ return [];
5
+ const missing = [];
6
+ required(root, "$", ["stages"], missing);
7
+ const task = row(root.task);
8
+ if (task) {
9
+ required(task, "task", ["target_profile", "execution_targets"], missing);
10
+ const profile = row(task.target_profile);
11
+ if (profile)
12
+ required(profile, "task.target_profile", ["required_target_refs"], missing);
13
+ }
14
+ for (const [index, outcome] of rows(root.outcomes).entries())
15
+ collectOutcome(outcome, `outcomes[${index}]`, missing);
16
+ const global = row(root.global);
17
+ const globalAcceptance = row(global?.acceptance);
18
+ collectChecks(globalAcceptance?.checks, "global.acceptance.checks", missing);
19
+ for (const [index, confirmation] of rows(globalAcceptance?.external_confirmations).entries())
20
+ required(confirmation, `global.acceptance.external_confirmations[${index}]`, ["kind", "impact_claims", "blocks_target"], missing);
21
+ return [...new Set(missing)].sort();
22
+ }
23
+ export function semanticDriftOutcomeMigrationFields(value, label) {
24
+ const missing = [];
25
+ const outcome = row(value);
26
+ if (outcome)
27
+ collectOutcome(outcome, label, missing);
28
+ return [...new Set(missing)].sort();
29
+ }
30
+ export function assertNoSemanticDriftMigration(fields) {
31
+ if (!fields.length)
32
+ return;
33
+ const detail = fields.slice(0, 24).join(",");
34
+ const suffix = fields.length > 24 ? `,+${fields.length - 24}-more` : "";
35
+ throw new Error(`long_task_delivery_v2_semantic_drift_migration_required:${detail}${suffix}`);
36
+ }
37
+ function collectOutcome(outcome, label, missing) {
38
+ required(outcome, label, ["stage"], missing);
39
+ const product = row(outcome.product);
40
+ if (product)
41
+ required(product, `${label}.product`, ["success_path_required", "degradation_path_required"], missing);
42
+ const acceptance = row(outcome.acceptance);
43
+ collectChecks(acceptance?.checks, `${label}.acceptance.checks`, missing);
44
+ }
45
+ function collectChecks(value, label, missing) {
46
+ for (const [index, check] of rows(value).entries()) {
47
+ const checkLabel = `${label}[${index}]`;
48
+ required(check, checkLabel, ["journey_roles", "execution_target", "scenario"], missing);
49
+ for (const polarity of ["positive_assertions", "negative_assertions"])
50
+ for (const [assertionIndex, assertion] of rows(check[polarity]).entries())
51
+ required(assertion, `${checkLabel}.${polarity}[${assertionIndex}]`, ["evidence_capabilities"], missing);
52
+ }
53
+ }
54
+ function required(value, label, keys, missing) {
55
+ for (const key of keys)
56
+ if (!Object.hasOwn(value, key))
57
+ missing.push(`${label}.${key}`);
58
+ }
59
+ function rows(value) {
60
+ return Array.isArray(value)
61
+ ? value.map(row).filter((item) => item !== null)
62
+ : [];
63
+ }
64
+ function row(value) {
65
+ return value && typeof value === "object" && !Array.isArray(value)
66
+ ? value
67
+ : null;
68
+ }
@@ -3,6 +3,7 @@ export declare function object(value: unknown, label: string, required: string[]
3
3
  export declare function array(value: unknown, label: string): unknown[];
4
4
  export declare function string(value: unknown, label: string): string;
5
5
  export declare function text(value: unknown, label: string): string;
6
+ export declare function boolean(value: unknown, label: string): boolean;
6
7
  export declare function strings(value: unknown, label: string): string[];
7
8
  export declare function repositoryFile(value: unknown, label: string): string;
8
9
  export declare function repositoryFiles(value: unknown, label: string): string[];
@@ -14,4 +15,6 @@ export declare function literal<T extends string>(value: unknown, allowed: reado
14
15
  export declare function key(value: unknown, label: string): string;
15
16
  export declare function nullable<T>(value: unknown, parser: (value: unknown) => T): T | null;
16
17
  export declare const PROOF_SURFACES: readonly ["ui_browser", "runtime_behavior", "api_contract", "data_state", "security_boundary", "population_coverage", "implementation_structure"];
18
+ export declare const JOURNEY_ROLES: readonly ["success", "degradation", "recovery", "stage_gate", "conformance"];
19
+ export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "target_runtime", "input_variation"];
17
20
  export declare function fail(label: string, message: string): never;
@@ -27,6 +27,11 @@ export function text(value, label) {
27
27
  fail(label, "must be a string");
28
28
  return value;
29
29
  }
30
+ export function boolean(value, label) {
31
+ if (typeof value !== "boolean")
32
+ fail(label, "must be a boolean");
33
+ return value;
34
+ }
30
35
  export function strings(value, label) {
31
36
  return array(value, label).map((item, index) => string(item, `${label}[${index}]`));
32
37
  }
@@ -76,6 +81,26 @@ export const PROOF_SURFACES = [
76
81
  "population_coverage",
77
82
  "implementation_structure",
78
83
  ];
84
+ export const JOURNEY_ROLES = [
85
+ "success",
86
+ "degradation",
87
+ "recovery",
88
+ "stage_gate",
89
+ "conformance",
90
+ ];
91
+ export const EVIDENCE_CAPABILITIES = [
92
+ "presence",
93
+ "interaction_trace",
94
+ "state_delta",
95
+ "cross_surface_consistency",
96
+ "durable_readback",
97
+ "boundary_invocation",
98
+ "external_side_effect",
99
+ "failure_injection",
100
+ "visual_render",
101
+ "target_runtime",
102
+ "input_variation",
103
+ ];
79
104
  export function fail(label, message) {
80
105
  throw new Error(`delivery_contract_invalid:${label}:${message}`);
81
106
  }
@@ -59,14 +59,28 @@ function target(ref, kind, text, outcomeKey, scope) {
59
59
  }
60
60
  function controlFields(control) {
61
61
  return [
62
+ ["surface", control.surface],
63
+ ["region", control.region],
62
64
  ["location", control.location],
65
+ ["control_type", control.control_type],
66
+ ["label_content", control.label_content],
67
+ ["user_task", control.user_task],
68
+ ["visibility", control.visibility],
69
+ ["availability", control.availability],
63
70
  ["trigger", control.trigger],
64
71
  ["input", control.input],
72
+ ["validation", control.validation],
73
+ ["default_value", control.default_value],
74
+ ["interaction", control.interaction],
75
+ ["navigation_result", control.navigation_result],
65
76
  ["loading", control.loading_state],
66
77
  ["empty", control.empty_state],
67
78
  ["success", control.success_state],
68
79
  ["failure", control.failure_state],
80
+ ["recovery", control.recovery],
81
+ ["permission", control.permission],
69
82
  ["feedback", control.feedback],
83
+ ["accessibility", control.accessibility],
70
84
  ];
71
85
  }
72
86
  export function sourceKindForTarget(target) {
@@ -0,0 +1,4 @@
1
+ import type { DeliveryContractV2 } from "./long-task-delivery-types.js";
2
+ type Reporter = (message: string) => void;
3
+ export declare function validateDeliveryStages(contract: DeliveryContractV2, report?: Reporter): void;
4
+ export {};
@@ -0,0 +1,120 @@
1
+ export function validateDeliveryStages(contract, report) {
2
+ unique(contract.stages.map((stage) => stage.key), "stage_key_duplicate", report);
3
+ const stages = new Map(contract.stages.map((stage) => [stage.key, stage]));
4
+ const outcomes = new Map(contract.outcomes.map((outcome) => [outcome.key, outcome]));
5
+ for (const stage of contract.stages) {
6
+ for (const dependency of stage.depends_on) {
7
+ if (dependency === stage.key)
8
+ issue(report, "stage_dependency_self", stage.key);
9
+ else if (!stages.has(dependency))
10
+ issue(report, "stage_dependency_unknown", `${stage.key}:${dependency}`);
11
+ }
12
+ const gate = outcomes.get(stage.gate_outcome);
13
+ if (!gate)
14
+ issue(report, "stage_gate_outcome_unknown", `${stage.key}:${stage.gate_outcome}`);
15
+ else if (gate.stage !== stage.key)
16
+ issue(report, "stage_gate_outcome_mismatch", `${stage.key}:${gate.key}`);
17
+ }
18
+ for (const outcome of contract.outcomes)
19
+ if (!stages.has(outcome.stage))
20
+ issue(report, "outcome_stage_unknown", `${outcome.key}:${outcome.stage}`);
21
+ validateStageCycles(contract, report);
22
+ validateStageGateClosure(contract, report);
23
+ }
24
+ function validateStageCycles(contract, report) {
25
+ const stages = new Map(contract.stages.map((stage) => [stage.key, stage]));
26
+ const visiting = new Set();
27
+ const visited = new Set();
28
+ const visit = (key) => {
29
+ if (visiting.has(key)) {
30
+ issue(report, "stage_dependency_cycle", key);
31
+ return;
32
+ }
33
+ if (visited.has(key))
34
+ return;
35
+ visiting.add(key);
36
+ for (const dependency of stages.get(key)?.depends_on ?? [])
37
+ if (stages.has(dependency))
38
+ visit(dependency);
39
+ visiting.delete(key);
40
+ visited.add(key);
41
+ };
42
+ for (const stage of stages.keys())
43
+ visit(stage);
44
+ }
45
+ function validateStageGateClosure(contract, report) {
46
+ const outcomes = new Map(contract.outcomes.map((outcome) => [outcome.key, outcome]));
47
+ for (const stage of contract.stages) {
48
+ const gate = outcomes.get(stage.gate_outcome);
49
+ if (!gate || gate.stage !== stage.key)
50
+ continue;
51
+ for (const outcome of contract.outcomes.filter((candidate) => candidate.stage === stage.key && candidate.key !== gate.key))
52
+ if (!outcomeDependsOn(gate.key, outcome.key, outcomes))
53
+ issue(report, "stage_gate_missing_outcome_dependency", `${stage.key}:${gate.key}:${outcome.key}`);
54
+ for (const dependency of stage.depends_on) {
55
+ const dependencyGate = contract.stages.find((candidate) => candidate.key === dependency)?.gate_outcome;
56
+ if (!dependencyGate)
57
+ continue;
58
+ for (const outcome of contract.outcomes.filter((candidate) => candidate.stage === stage.key))
59
+ if (!outcomeDependsOn(outcome.key, dependencyGate, outcomes))
60
+ issue(report, "stage_outcome_missing_gate_dependency", `${stage.key}:${outcome.key}:${dependencyGate}`);
61
+ }
62
+ const stageGateChecks = gate.acceptance.checks.filter((check) => check.journey_roles.includes("stage_gate"));
63
+ if (!stageGateChecks.length)
64
+ issue(report, "stage_gate_check_required", `${stage.key}:${gate.key}`);
65
+ else if (!stageGateChecks.some((check) => provesGate(check, gate)))
66
+ issue(report, "stage_gate_target_runtime_result_required", `${stage.key}:${gate.key}`);
67
+ for (const targetRef of contract.task.target_profile.required_target_refs)
68
+ if (!stageGateChecks.some((check) => check.execution_target.target_ref === targetRef &&
69
+ check.execution_target.entrypoint === "root" &&
70
+ provesGate(check, gate)))
71
+ issue(report, "stage_gate_required_target_proof_missing", `${stage.key}:${targetRef}`);
72
+ const stageOutcomes = contract.outcomes.filter((candidate) => candidate.stage === stage.key);
73
+ if (stageOutcomes.length > 1 &&
74
+ !stageGateChecks.some((check) => [...check.positive_assertions, ...check.negative_assertions].some((assertion) => assertion.evidence_capabilities.includes("cross_surface_consistency"))))
75
+ issue(report, "stage_gate_cross_surface_consistency_required", `${stage.key}:${stageOutcomes.map((outcome) => outcome.key).join(",")}`);
76
+ }
77
+ for (const outcome of contract.outcomes)
78
+ for (const check of outcome.acceptance.checks)
79
+ if (check.journey_roles.includes("stage_gate") &&
80
+ !contract.stages.some((stage) => stage.gate_outcome === outcome.key))
81
+ issue(report, "stage_gate_role_on_non_gate", `${outcome.key}:${check.key}`);
82
+ }
83
+ function provesGate(check, gate) {
84
+ const assertions = [
85
+ ...check.positive_assertions,
86
+ ...check.negative_assertions,
87
+ ];
88
+ const provesResult = assertions.some((assertion) => assertion.claims.includes("result")) ||
89
+ (gate.acceptance.population?.check_key === check.key &&
90
+ gate.acceptance.population.claims.includes("result"));
91
+ return (provesResult &&
92
+ assertions.some((assertion) => assertion.evidence_capabilities.includes("target_runtime")));
93
+ }
94
+ function outcomeDependsOn(start, target, outcomes) {
95
+ const seen = new Set();
96
+ const visit = (key) => {
97
+ if (key === target)
98
+ return true;
99
+ if (seen.has(key))
100
+ return false;
101
+ seen.add(key);
102
+ return (outcomes.get(key)?.depends_on ?? []).some(visit);
103
+ };
104
+ return visit(start);
105
+ }
106
+ function unique(values, code, report) {
107
+ const seen = new Set();
108
+ for (const value of values) {
109
+ if (seen.has(value))
110
+ issue(report, code, value);
111
+ seen.add(value);
112
+ }
113
+ }
114
+ function issue(report, code, detail) {
115
+ const message = `delivery_contract_invalid:${code}:${detail}`;
116
+ if (report)
117
+ report(message);
118
+ else
119
+ throw new Error(message);
120
+ }
@@ -1,4 +1,4 @@
1
- import type { CompiledDeliveryContractV2, FinalReceiptV2, LongTaskFindingV2, OutcomeStatusV2, ProgressRecordV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
1
+ import type { CompiledDeliveryContractV2, FinalReceiptV2, LongTaskFindingV2, OutcomeStatusV2, ProgressRecordV2, StageStatusV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
2
2
  interface StatusProjectionInputV2 {
3
3
  compiled: CompiledDeliveryContractV2;
4
4
  manifest: WorkspaceManifestV2;
@@ -11,7 +11,10 @@ export type AuditGateStatusV2 = "no_final_gate" | "last_gate_passed" | "last_gat
11
11
  export declare function projectDeliveryStatus(input: StatusProjectionInputV2): {
12
12
  finalResult: AuditGateStatusV2;
13
13
  finalWorkflowStatus: FinalReceiptV2["workflow_status"] | null;
14
+ targetState: FinalReceiptV2["target_state"];
14
15
  outcomes: Record<string, OutcomeStatusV2>;
16
+ stages: Record<string, StageStatusV2>;
17
+ readyStages: string[];
15
18
  readyOutcomes: string[];
16
19
  needsReverify: string[];
17
20
  progressPassing: string[];