project-tiny-context-harness 0.2.81 → 0.2.83

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 (52) hide show
  1. package/README.md +11 -3
  2. package/assets/README.md +11 -3
  3. package/assets/README.zh-CN.md +9 -1
  4. package/assets/protected-harness-baseline.json +18 -0
  5. package/assets/skills/composite-long-task-workflow/SKILL.md +21 -1
  6. package/assets/skills/composite-long-task-workflow/assets/execution-binding.template.md +10 -0
  7. package/assets/skills/composite-long-task-workflow/assets/goal-objective.template.md +6 -15
  8. package/assets/skills/composite-long-task-workflow/references/composite-long-task-workflow-protocol.md +32 -15
  9. package/dist/commands/composite-long-task.js +45 -2
  10. package/dist/lib/superpowers-task-ac010.d.ts +6 -0
  11. package/dist/lib/superpowers-task-ac010.js +26 -0
  12. package/dist/lib/superpowers-task-assertion-normalizers.js +8 -1
  13. package/dist/lib/superpowers-task-assertions.js +35 -20
  14. package/dist/lib/superpowers-task-attempt.d.ts +4 -0
  15. package/dist/lib/superpowers-task-attempt.js +102 -0
  16. package/dist/lib/superpowers-task-command-specs.d.ts +3 -0
  17. package/dist/lib/superpowers-task-command-specs.js +52 -0
  18. package/dist/lib/superpowers-task-compile.d.ts +4 -1
  19. package/dist/lib/superpowers-task-compile.js +7 -1
  20. package/dist/lib/superpowers-task-contradictions.d.ts +6 -0
  21. package/dist/lib/superpowers-task-contradictions.js +126 -0
  22. package/dist/lib/superpowers-task-current-evidence.d.ts +3 -0
  23. package/dist/lib/superpowers-task-current-evidence.js +154 -0
  24. package/dist/lib/superpowers-task-delivery.js +30 -18
  25. package/dist/lib/superpowers-task-derive.d.ts +1 -0
  26. package/dist/lib/superpowers-task-derive.js +76 -1
  27. package/dist/lib/superpowers-task-evidence-kernel.d.ts +12 -0
  28. package/dist/lib/superpowers-task-evidence-kernel.js +351 -0
  29. package/dist/lib/superpowers-task-evidence-records.d.ts +2 -0
  30. package/dist/lib/superpowers-task-evidence-records.js +55 -0
  31. package/dist/lib/superpowers-task-evidence.d.ts +10 -0
  32. package/dist/lib/superpowers-task-evidence.js +141 -0
  33. package/dist/lib/superpowers-task-fields.d.ts +22 -0
  34. package/dist/lib/superpowers-task-fields.js +276 -0
  35. package/dist/lib/superpowers-task-gates.js +36 -24
  36. package/dist/lib/superpowers-task-harness-drift.d.ts +11 -0
  37. package/dist/lib/superpowers-task-harness-drift.js +86 -0
  38. package/dist/lib/superpowers-task-protected-baseline.d.ts +10 -0
  39. package/dist/lib/superpowers-task-protected-baseline.js +47 -0
  40. package/dist/lib/superpowers-task-source-compile.js +93 -95
  41. package/dist/lib/superpowers-task-source-parser.js +1 -3
  42. package/dist/lib/superpowers-task-state-schema.d.ts +158 -3
  43. package/dist/lib/superpowers-task-state-schema.js +23 -1
  44. package/dist/lib/superpowers-task-state-shape.d.ts +3 -0
  45. package/dist/lib/superpowers-task-state-shape.js +50 -0
  46. package/dist/lib/superpowers-task-state.js +19 -39
  47. package/dist/lib/superpowers-task-status.js +11 -1
  48. package/dist/lib/superpowers-task-under-specified.d.ts +7 -0
  49. package/dist/lib/superpowers-task-under-specified.js +61 -0
  50. package/dist/lib/superpowers-task-validator.js +11 -37
  51. package/package.json +69 -69
  52. package/source-mappings.yaml +3 -0
@@ -0,0 +1,47 @@
1
+ import { isHarnessPath } from "./superpowers-task-harness-drift.js";
2
+ import { isRecord } from "./superpowers-task-state-schema.js";
3
+ export const PROTECTED_BASELINE_PATHS = [
4
+ "packages/ty-context/assets/protected-harness-baseline.json",
5
+ ".codex/ty-context-managed/protected-harness-baseline.json",
6
+ "packages/ty-context/source-mappings.yaml",
7
+ "packages/ty-context/src/lib/superpowers-task-gates.ts",
8
+ "packages/ty-context/src/lib/superpowers-task-validator.ts",
9
+ "packages/ty-context/src/lib/superpowers-task-derive.ts",
10
+ "packages/ty-context/src/lib/superpowers-task-evidence.ts",
11
+ "packages/ty-context/src/lib/superpowers-task-evidence-kernel.ts",
12
+ "packages/ty-context/src/lib/superpowers-task-state-schema.ts",
13
+ ".codex/ty-context-managed/skills/composite-long-task-workflow/SKILL.md",
14
+ ".codex/ty-context-managed/skills/composite-long-task-workflow/references/composite-long-task-workflow-protocol.md",
15
+ "packages/ty-context/assets/skills/composite-long-task-workflow/SKILL.md",
16
+ "packages/ty-context/assets/skills/composite-long-task-workflow/references/composite-long-task-workflow-protocol.md"
17
+ ];
18
+ export function evaluateProtectedBaseline(state) {
19
+ const attempt = currentAttempt(state);
20
+ const changedFiles = [...new Set((attempt?.changed_files ?? []).map((file) => file.replace(/\\/g, "/")).filter(Boolean))];
21
+ const protectedChanges = changedFiles.filter(isProtectedBaselinePath);
22
+ const mode = attempt?.mode ?? "product_task";
23
+ const errors = [];
24
+ if (mode === "product_task" && protectedChanges.length > 0) {
25
+ errors.push(`protected_baseline_changed: product_task cannot change protected harness baseline paths: ${protectedChanges.join(", ")}`);
26
+ }
27
+ if (mode === "harness_task" && protectedChanges.length > 0 && !protectedBaselineReason(state)) {
28
+ errors.push("protected_baseline_reason_required: harness_task baseline changes must record gates.protected_baseline.reason");
29
+ }
30
+ return {
31
+ protected_baseline_changed: protectedChanges.length > 0,
32
+ product_goal_complete: errors.length === 0,
33
+ changed_files: protectedChanges,
34
+ errors
35
+ };
36
+ }
37
+ export function isProtectedBaselinePath(file) {
38
+ const normalized = file.replace(/\\/g, "/");
39
+ return PROTECTED_BASELINE_PATHS.includes(normalized) || isHarnessPath(normalized);
40
+ }
41
+ function protectedBaselineReason(state) {
42
+ const baseline = state.gates?.protected_baseline;
43
+ return isRecord(baseline) && typeof baseline.reason === "string" && baseline.reason.trim().length > 0;
44
+ }
45
+ function currentAttempt(state) {
46
+ return (state.attempts ?? []).find((item) => item.task_attempt_id === state.current_attempt_id) ?? (state.attempts ?? []).at(-1);
47
+ }
@@ -1,89 +1,38 @@
1
1
  import { MACHINE_VERIFIABLE_PROOF_LAYERS, proofLayerName } from "./superpowers-task-assertions.js";
2
2
  import { compileReportSuffix, missingCategory, throwCompileErrors } from "./superpowers-task-compile-diagnostics.js";
3
+ import { ACCEPTANCE_FIELDS, ACCEPTANCE_SCOPES, fieldSet, isSelectedScopeFitSlice, normalizeProofLayerName, PLAN_DELIVERY_SCOPES, PLAN_FIELDS, PRODUCT_DELIVERY_SCOPES, PRODUCT_FIELDS, SCOPE_FIT_DECISIONS } from "./superpowers-task-fields.js";
3
4
  import { fieldArray, fieldBoolean, fieldLine, fieldText, parseDocumentFields, parseHeadingDefinitions } from "./superpowers-task-source-parser.js";
4
5
  export const DEFAULT_LAYERS = ["code", "test"];
5
- const PRODUCT_DELIVERY_SCOPES = new Set(["system_capability_build", "representative_sample_validation", "full_population_operation", "mixed_scope_requires_boundary"]);
6
- const PLAN_DELIVERY_SCOPES = new Set(["system_capability_build", "representative_sample_validation", "full_population_operation", "out_of_scope_backlog"]);
7
- const ACCEPTANCE_SCOPES = new Set(["system_capability_build", "representative_sample_validation", "full_population_operation", "full_population_not_required"]);
8
- const PRODUCT_FIELDS = new Set([
9
- "delivery_scope",
10
- "full_population_required",
11
- "representative_samples_validate",
12
- "representative_samples_do_not_validate",
13
- "out_of_scope_backlog",
14
- "source_authority",
15
- "product_goal",
16
- "surface_ia_lock",
17
- "decision_lock",
18
- "context_delta",
19
- "source_to_context_coverage",
20
- "acceptance_semantics",
21
- "impact"
22
- ]);
23
- const PLAN_FIELDS = new Set([
24
- "delivery_scope",
25
- "capability_target",
26
- "representative_samples",
27
- "full_population_boundary",
28
- "non_required_population",
29
- "owner_surfaces",
30
- "forbidden_surfaces",
31
- "implementation_paths",
32
- "required_tests",
33
- "related_acs",
34
- "requirement_ref",
35
- "decision_id",
36
- "proof_layer_ids",
37
- "api_schema_changes",
38
- "state_machine",
39
- "data_flow",
40
- "worker_runtime_behavior",
41
- "ui_ia_changes",
42
- "migration_plan",
43
- "evidence_artifacts",
44
- "explicit_no_test_scope",
45
- "non_completing_shortcuts",
46
- "substitution_policy",
47
- "drift_severity",
48
- "partial_conditions",
49
- "blockers",
50
- "context_fact_refs"
51
- ]);
52
- const ACCEPTANCE_FIELDS = new Set([
53
- "checklist_source",
54
- "acceptance_scope",
55
- "ac_validates",
56
- "ac_does_not_validate",
57
- "sample_boundary",
58
- "full_population_required",
59
- "related_plan_items",
60
- "required_proof_layers",
61
- "ac_type",
62
- "proof_chain",
63
- "verification_method",
64
- "fail_conditions",
65
- "invalid_evidence",
66
- "substitution_policy",
67
- "missing_layer_downgrade",
68
- "auditor_expectation",
69
- "out_of_scope_na_approval_source",
70
- "required_test_ids",
71
- "explicit_no_test_scope",
72
- "hard_blockers",
73
- "validates_explanation",
74
- "does_not_validate_explanation",
75
- "final_evidence_expected",
76
- "test_cases"
77
- ]);
6
+ const PRODUCT_FIELD_SET = fieldSet(PRODUCT_FIELDS);
7
+ const PLAN_FIELD_SET = fieldSet(PLAN_FIELDS);
8
+ const ACCEPTANCE_FIELD_SET = fieldSet(ACCEPTANCE_FIELDS);
78
9
  export function parseProductArchitectureScope(content, sourceFile) {
79
- const fields = parseDocumentFields(content, sourceFile, PRODUCT_FIELDS);
10
+ const fields = parseDocumentFields(content, sourceFile, PRODUCT_FIELD_SET);
80
11
  const errors = [];
12
+ const selectedScopeFitSlice = requireText(errors, "Product / Architecture Source", "selected_scope_fit_slice", fields, sourceFile, 1);
13
+ if (selectedScopeFitSlice && !isSelectedScopeFitSlice(selectedScopeFitSlice)) {
14
+ errors.push(`Product / Architecture Source invalid selected_scope_fit_slice: ${selectedScopeFitSlice} at ${sourceFile}:${fieldLine(fields, "selected_scope_fit_slice") ?? 1}; allowed: none or SFC-###${compileReportSuffix("blocking_unparseable_object", sourceFile, fieldLine(fields, "selected_scope_fit_slice") ?? 1, "selected_scope_fit_slice", "value must be none or an SFC-### id", "fix selected_scope_fit_slice and rerun compile")}`);
15
+ }
81
16
  const scope = {
82
17
  delivery_scope: requireEnum(errors, "Product / Architecture Source", "delivery_scope", fields, PRODUCT_DELIVERY_SCOPES, sourceFile, 1),
83
18
  full_population_required: requireBoolean(errors, "Product / Architecture Source", "full_population_required", fields, sourceFile, 1),
84
19
  representative_samples_validate: requireArray(errors, "Product / Architecture Source", "representative_samples_validate", fields, sourceFile, 1),
85
20
  representative_samples_do_not_validate: requireArray(errors, "Product / Architecture Source", "representative_samples_do_not_validate", fields, sourceFile, 1),
86
- out_of_scope_backlog: requireArray(errors, "Product / Architecture Source", "out_of_scope_backlog", fields, sourceFile, 1)
21
+ out_of_scope_backlog: requireArray(errors, "Product / Architecture Source", "out_of_scope_backlog", fields, sourceFile, 1),
22
+ scope_fit_decision: requireEnum(errors, "Product / Architecture Source", "scope_fit_decision", fields, SCOPE_FIT_DECISIONS, sourceFile, 1),
23
+ selected_scope_fit_slice: selectedScopeFitSlice,
24
+ owner_boundary: requireText(errors, "Product / Architecture Source", "owner_boundary", fields, sourceFile, 1),
25
+ primary_capability_path: requireText(errors, "Product / Architecture Source", "primary_capability_path", fields, sourceFile, 1),
26
+ non_completing_outcomes: requireArray(errors, "Product / Architecture Source", "non_completing_outcomes", fields, sourceFile, 1),
27
+ assertion_policy: requireText(errors, "Product / Architecture Source", "assertion_policy", fields, sourceFile, 1),
28
+ source_authority: requireText(errors, "Product / Architecture Source", "source_authority", fields, sourceFile, 1),
29
+ product_goal: requireText(errors, "Product / Architecture Source", "product_goal", fields, sourceFile, 1),
30
+ surface_ia_lock: optionalText(fields, "surface_ia_lock"),
31
+ decision_lock: optionalText(fields, "decision_lock"),
32
+ context_delta: optionalText(fields, "context_delta"),
33
+ source_to_context_coverage: optionalText(fields, "source_to_context_coverage"),
34
+ acceptance_semantics: optionalText(fields, "acceptance_semantics"),
35
+ impact: optionalText(fields, "impact")
87
36
  };
88
37
  throwCompileErrors(errors);
89
38
  return scope;
@@ -91,7 +40,7 @@ export function parseProductArchitectureScope(content, sourceFile) {
91
40
  export function parsePlanItems(content, sourceFile) {
92
41
  const items = {};
93
42
  const errors = [];
94
- for (const definition of parseHeadingDefinitions(content, { kind: "PI", sourceFile, allowedFields: PLAN_FIELDS })) {
43
+ for (const definition of parseHeadingDefinitions(content, { kind: "PI", sourceFile, allowedFields: PLAN_FIELD_SET })) {
95
44
  const fields = definition.fields;
96
45
  items[definition.id] = {
97
46
  requirement: definition.title,
@@ -103,13 +52,33 @@ export function parsePlanItems(content, sourceFile) {
103
52
  representative_samples: requireArray(errors, definition.id, "representative_samples", fields, sourceFile, definition.source_start_line),
104
53
  full_population_boundary: requireText(errors, definition.id, "full_population_boundary", fields, sourceFile, definition.source_start_line),
105
54
  non_required_population: requireArray(errors, definition.id, "non_required_population", fields, sourceFile, definition.source_start_line),
55
+ owner_boundary: requireText(errors, definition.id, "owner_boundary", fields, sourceFile, definition.source_start_line),
56
+ primary_capability_path: requireText(errors, definition.id, "primary_capability_path", fields, sourceFile, definition.source_start_line),
57
+ trigger_contract: requireText(errors, definition.id, "trigger_contract", fields, sourceFile, definition.source_start_line),
58
+ state_transition_contract: requireText(errors, definition.id, "state_transition_contract", fields, sourceFile, definition.source_start_line),
59
+ observable_result_contract: requireText(errors, definition.id, "observable_result_contract", fields, sourceFile, definition.source_start_line),
60
+ assertion_support: requireText(errors, definition.id, "assertion_support", fields, sourceFile, definition.source_start_line),
61
+ required_assertion_commands: requireArray(errors, definition.id, "required_assertion_commands", fields, sourceFile, definition.source_start_line),
62
+ invalid_implementation_shortcuts: requireArray(errors, definition.id, "invalid_implementation_shortcuts", fields, sourceFile, definition.source_start_line),
106
63
  owner_surfaces: optionalArray(fields, "owner_surfaces"),
107
64
  forbidden_surfaces: optionalArray(fields, "forbidden_surfaces"),
108
- implementation_paths: optionalArray(fields, "implementation_paths"),
65
+ implementation_paths: requireArray(errors, definition.id, "implementation_paths", fields, sourceFile, definition.source_start_line),
109
66
  required_tests: optionalArray(fields, "required_tests"),
110
- proof_layer_ids: optionalArray(fields, "proof_layer_ids").map(normalizeLayer),
67
+ proof_layer_ids: optionalArray(fields, "proof_layer_ids").map(normalizeLayerId),
68
+ requirement_ref: optionalText(fields, "requirement_ref"),
69
+ decision_id: optionalText(fields, "decision_id"),
70
+ api_schema_changes: optionalText(fields, "api_schema_changes"),
71
+ state_machine: optionalText(fields, "state_machine"),
72
+ data_flow: optionalText(fields, "data_flow"),
73
+ worker_runtime_behavior: optionalText(fields, "worker_runtime_behavior"),
74
+ ui_ia_changes: optionalText(fields, "ui_ia_changes"),
75
+ migration_plan: optionalText(fields, "migration_plan"),
76
+ evidence_artifacts: optionalArray(fields, "evidence_artifacts"),
111
77
  non_completing_shortcuts: optionalArray(fields, "non_completing_shortcuts"),
112
78
  substitution_policy: optionalArray(fields, "substitution_policy"),
79
+ drift_severity: optionalText(fields, "drift_severity"),
80
+ partial_conditions: optionalArray(fields, "partial_conditions"),
81
+ blockers: optionalArray(fields, "blockers"),
113
82
  explicit_no_test_scope: fieldBoolean(fields, "explicit_no_test_scope") === true,
114
83
  context_fact_refs: optionalArray(fields, "context_fact_refs"),
115
84
  status: "not_started",
@@ -123,9 +92,9 @@ export function parsePlanItems(content, sourceFile) {
123
92
  export function parseAcceptanceCriteria(content, sourceFile) {
124
93
  const items = {};
125
94
  const errors = [];
126
- for (const definition of parseHeadingDefinitions(content, { kind: "AC", sourceFile, allowedFields: ACCEPTANCE_FIELDS })) {
95
+ for (const definition of parseHeadingDefinitions(content, { kind: "AC", sourceFile, allowedFields: ACCEPTANCE_FIELD_SET })) {
127
96
  const fields = definition.fields;
128
- const layers = optionalArray(fields, "required_proof_layers").map(normalizeLayer).filter(Boolean);
97
+ const layers = requireArray(errors, definition.id, "required_proof_layers", fields, sourceFile, definition.source_start_line).map(normalizeLayer).filter(Boolean);
129
98
  const requiredProofLayers = layers.length > 0 ? layers : DEFAULT_LAYERS;
130
99
  items[definition.id] = {
131
100
  scope: definition.title,
@@ -137,13 +106,31 @@ export function parseAcceptanceCriteria(content, sourceFile) {
137
106
  ac_does_not_validate: requireArray(errors, definition.id, "ac_does_not_validate", fields, sourceFile, definition.source_start_line),
138
107
  sample_boundary: requireText(errors, definition.id, "sample_boundary", fields, sourceFile, definition.source_start_line),
139
108
  full_population_required: requireBoolean(errors, definition.id, "full_population_required", fields, sourceFile, definition.source_start_line),
140
- related_plan_items: optionalArray(fields, "related_plan_items").map((item) => item.toUpperCase()),
109
+ related_plan_items: requireArray(errors, definition.id, "related_plan_items", fields, sourceFile, definition.source_start_line).map((item) => item.toUpperCase()),
141
110
  required_proof_layers: requiredProofLayers,
142
111
  assertion_requirements: assertionRequirements(fields, requiredProofLayers),
112
+ assertion_command: requireText(errors, definition.id, "assertion_command", fields, sourceFile, definition.source_start_line),
113
+ assertion_artifacts: requireArray(errors, definition.id, "assertion_artifacts", fields, sourceFile, definition.source_start_line),
114
+ positive_assertions: requireArray(errors, definition.id, "positive_assertions", fields, sourceFile, definition.source_start_line),
115
+ negative_assertions: requireArray(errors, definition.id, "negative_assertions", fields, sourceFile, definition.source_start_line),
116
+ machine_blocking: requireBoolean(errors, definition.id, "machine_blocking", fields, sourceFile, definition.source_start_line),
117
+ invalid_completion_signals: requireArray(errors, definition.id, "invalid_completion_signals", fields, sourceFile, definition.source_start_line),
118
+ assertion_result_required: requireBoolean(errors, definition.id, "assertion_result_required", fields, sourceFile, definition.source_start_line),
119
+ ac_type: optionalText(fields, "ac_type"),
120
+ proof_chain: optionalArray(fields, "proof_chain").map(normalizeLayerId),
143
121
  required_test_ids: optionalArray(fields, "required_test_ids"),
144
122
  fail_conditions: optionalArray(fields, "fail_conditions"),
145
123
  invalid_evidence: optionalArray(fields, "invalid_evidence"),
124
+ substitution_policy: optionalArray(fields, "substitution_policy"),
125
+ missing_layer_downgrade: optionalText(fields, "missing_layer_downgrade"),
126
+ auditor_expectation: optionalText(fields, "auditor_expectation"),
127
+ out_of_scope_na_approval_source: optionalText(fields, "out_of_scope_na_approval_source"),
128
+ hard_blockers: optionalArray(fields, "hard_blockers"),
129
+ validates_explanation: optionalText(fields, "validates_explanation"),
130
+ does_not_validate_explanation: optionalText(fields, "does_not_validate_explanation"),
146
131
  final_evidence_expected: optionalArray(fields, "final_evidence_expected"),
132
+ verification_method: optionalArray(fields, "verification_method"),
133
+ test_cases: optionalArray(fields, "test_cases"),
147
134
  explicit_no_test_scope: fieldBoolean(fields, "explicit_no_test_scope") === true,
148
135
  status: "not_run"
149
136
  };
@@ -152,28 +139,36 @@ export function parseAcceptanceCriteria(content, sourceFile) {
152
139
  return items;
153
140
  }
154
141
  function normalizeLayer(value) {
155
- return value.trim().toLowerCase().replace(/[- ]+/g, "_");
142
+ return normalizeProofLayerName(value);
143
+ }
144
+ function normalizeLayerId(value) {
145
+ const trimmed = value.trim();
146
+ if (!trimmed.includes(".")) {
147
+ return normalizeLayer(trimmed);
148
+ }
149
+ const acId = trimmed.slice(0, trimmed.lastIndexOf(".")).toUpperCase();
150
+ const layer = trimmed.slice(trimmed.lastIndexOf(".") + 1);
151
+ return `${acId}.${normalizeLayer(layer)}`;
156
152
  }
157
153
  function assertionRequirements(fields, layers) {
158
154
  const requiredTestIds = optionalArray(fields, "required_test_ids");
159
- const positiveAssertions = unique([
160
- ...fieldArray(fields, "ac_validates"),
161
- ...requiredTestIds,
162
- ...optionalArray(fields, "test_cases"),
163
- ...optionalArray(fields, "verification_method"),
164
- ...optionalArray(fields, "final_evidence_expected")
165
- ]);
166
- const negativeAssertions = unique([
167
- ...fieldArray(fields, "ac_does_not_validate"),
168
- ...optionalArray(fields, "fail_conditions"),
169
- ...optionalArray(fields, "invalid_evidence")
170
- ]);
155
+ const positiveAssertions = unique(optionalArray(fields, "positive_assertions"));
156
+ const negativeAssertions = unique(optionalArray(fields, "negative_assertions"));
157
+ const assertionCommand = fieldText(fields, "assertion_command");
158
+ const assertionArtifacts = optionalArray(fields, "assertion_artifacts");
159
+ const machineBlocking = fieldBoolean(fields, "machine_blocking");
160
+ const assertionResultRequired = fieldBoolean(fields, "assertion_result_required");
161
+ const invalidCompletionSignals = optionalArray(fields, "invalid_completion_signals");
171
162
  return layers.map((layer) => {
172
163
  const normalized = proofLayerName(normalizeLayer(layer));
173
164
  return {
174
165
  proof_layer: normalized,
175
166
  required: true,
176
- machine_blocking: MACHINE_VERIFIABLE_PROOF_LAYERS.has(normalized),
167
+ machine_blocking: machineBlocking ?? MACHINE_VERIFIABLE_PROOF_LAYERS.has(normalized),
168
+ assertion_result_required: assertionResultRequired ?? MACHINE_VERIFIABLE_PROOF_LAYERS.has(normalized),
169
+ assertion_command: assertionCommand,
170
+ assertion_artifacts: assertionArtifacts,
171
+ invalid_completion_signals: invalidCompletionSignals,
177
172
  required_test_ids: requiredTestIds,
178
173
  positive_assertions: positiveAssertions,
179
174
  negative_assertions: negativeAssertions
@@ -223,6 +218,9 @@ function requireBoolean(errors, label, name, fields, sourceFile, fallbackLine) {
223
218
  function optionalArray(fields, name) {
224
219
  return fields[name] ? fieldArray(fields, name) : [];
225
220
  }
221
+ function optionalText(fields, name) {
222
+ return fields[name] ? fieldText(fields, name) : "";
223
+ }
226
224
  function unique(values) {
227
225
  return [...new Set(values.filter(Boolean))];
228
226
  }
@@ -86,9 +86,7 @@ function parseFields(lines, sourceFile, startLine, allowedFields, errors) {
86
86
  }
87
87
  const name = match[1];
88
88
  if (!allowedFields.has(name)) {
89
- if (name.includes("_")) {
90
- errors.push(compileError(`${sourceFile}:${lineNumber} unknown field ${name}`, "blocking_unparseable_object", sourceFile, lineNumber, name, "unknown fields may hide required source semantics", "rename the field to a supported canonical key"));
91
- }
89
+ errors.push(compileError(`${sourceFile}:${lineNumber} unknown field ${name}`, "blocking_unparseable_object", sourceFile, lineNumber, name, "unknown fields may hide required source semantics", "rename the field to a supported canonical key"));
92
90
  continue;
93
91
  }
94
92
  if (fields[name]) {
@@ -4,7 +4,7 @@ export declare const SUPERPOWERS_TASK_STATE_JSON_SCHEMA: {
4
4
  readonly $id: "https://project-tiny-context-harness.local/superpowers-task-state.schema.json";
5
5
  readonly title: "Superpowers Long-Task State";
6
6
  readonly type: "object";
7
- readonly required: readonly ["meta", "sources", "context", "delivery", "graph", "slices", "evidence", "gates", "progress", "blockers", "final"];
7
+ readonly required: readonly ["meta", "sources", "context", "delivery", "graph", "attempts", "current_attempt_id", "required_command_specs", "command_runs", "negative_evidence_records", "slices", "evidence", "gates", "progress", "blockers", "final"];
8
8
  readonly properties: {
9
9
  readonly meta: {
10
10
  readonly type: "object";
@@ -33,6 +33,21 @@ export declare const SUPERPOWERS_TASK_STATE_JSON_SCHEMA: {
33
33
  readonly graph: {
34
34
  readonly type: "object";
35
35
  };
36
+ readonly attempts: {
37
+ readonly type: "array";
38
+ };
39
+ readonly current_attempt_id: {
40
+ readonly type: "string";
41
+ };
42
+ readonly required_command_specs: {
43
+ readonly type: "array";
44
+ };
45
+ readonly command_runs: {
46
+ readonly type: "array";
47
+ };
48
+ readonly negative_evidence_records: {
49
+ readonly type: "array";
50
+ };
36
51
  readonly slices: {
37
52
  readonly type: "array";
38
53
  };
@@ -55,10 +70,12 @@ export declare const SUPERPOWERS_TASK_STATE_JSON_SCHEMA: {
55
70
  };
56
71
  export type SuperpowersProofLayerStatus = "missing" | "satisfied" | "invalidated" | "blocked";
57
72
  export type SuperpowersPlanItemStatus = "not_started" | "in_progress" | "complete" | "partial" | "blocked" | "invalidated" | "out_of_scope_NA";
58
- export type SuperpowersAcceptanceStatus = "not_run" | "complete" | "partial" | "blocked" | "invalidated" | "out_of_scope_NA";
73
+ export type SuperpowersAcceptanceStatus = "not_run" | "complete" | "partial" | "blocked" | "invalidated" | "under_specified" | "out_of_scope_NA";
74
+ export type SuperpowersAttemptMode = "product_task" | "harness_task";
59
75
  export type SuperpowersProductDeliveryScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "mixed_scope_requires_boundary";
60
76
  export type SuperpowersPlanDeliveryScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "out_of_scope_backlog";
61
77
  export type SuperpowersAcceptanceScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "full_population_not_required";
78
+ export type SuperpowersScopeFitDecision = "fit_for_three_inputs" | "selected_from_split" | "blocked_for_decision" | "";
62
79
  export interface SuperpowersTaskState {
63
80
  meta: {
64
81
  task_id: string;
@@ -85,6 +102,11 @@ export interface SuperpowersTaskState {
85
102
  proof_layers: Record<string, SuperpowersProofLayer>;
86
103
  edges: SuperpowersGraphEdge[];
87
104
  };
105
+ attempts: ExecutionAttempt[];
106
+ current_attempt_id: string;
107
+ required_command_specs: RequiredCommandSpec[];
108
+ command_runs: CommandRunRecord[];
109
+ negative_evidence_records: NegativeEvidenceRecord[];
88
110
  slices: SuperpowersSliceRecord[];
89
111
  evidence: SuperpowersEvidenceRecord[];
90
112
  gates: Record<string, unknown>;
@@ -98,6 +120,60 @@ export interface SuperpowersTaskState {
98
120
  next_required_actions?: string[];
99
121
  };
100
122
  }
123
+ export interface ExecutionAttempt {
124
+ task_attempt_id: string;
125
+ source_bundle_hash: string;
126
+ product_source_hash: string;
127
+ technical_plan_hash: string;
128
+ acceptance_checklist_hash: string;
129
+ git_head: string;
130
+ git_status_short: string;
131
+ tracked_diff_hash: string;
132
+ relevant_untracked_hash: string;
133
+ untracked_relevant_hash?: string;
134
+ worktree_fingerprint: string;
135
+ started_at: string;
136
+ ended_at: string | null;
137
+ finalized_at?: string | null;
138
+ required_command_specs_hash: string;
139
+ mode: SuperpowersAttemptMode;
140
+ changed_files?: string[];
141
+ }
142
+ export interface RequiredCommandSpec {
143
+ command_spec_id: string;
144
+ ac_id: string;
145
+ proof_layers: string[];
146
+ command: string;
147
+ assertion_artifacts: string[];
148
+ required_test_ids: string[];
149
+ machine_blocking: boolean;
150
+ assertion_result_required: boolean;
151
+ positive_assertions: string[];
152
+ negative_assertions: string[];
153
+ invalid_completion_signals: string[];
154
+ final_evidence_expected: string[];
155
+ }
156
+ export interface CommandRunRecord {
157
+ command_run_id: string;
158
+ task_attempt_id: string;
159
+ command_spec_id: string;
160
+ ac_id: string;
161
+ proof_layer: string;
162
+ command_line: string;
163
+ exit_code: number;
164
+ started_at: string;
165
+ ended_at: string;
166
+ artifact_paths: string[];
167
+ }
168
+ export interface NegativeEvidenceRecord {
169
+ negative_evidence_id: string;
170
+ task_attempt_id: string;
171
+ target_ac_ids: string[];
172
+ target_proof_layers: string[];
173
+ artifact_path: string;
174
+ artifact_sha256?: string;
175
+ status: "passed" | "failed" | "blocked" | "stale";
176
+ }
101
177
  export interface SuperpowersSourceRecord {
102
178
  path: string;
103
179
  sha256: string;
@@ -113,6 +189,20 @@ export interface SuperpowersProductArchitectureScope {
113
189
  representative_samples_validate: string[];
114
190
  representative_samples_do_not_validate: string[];
115
191
  out_of_scope_backlog: string[];
192
+ scope_fit_decision: SuperpowersScopeFitDecision;
193
+ selected_scope_fit_slice: string;
194
+ owner_boundary: string;
195
+ primary_capability_path: string;
196
+ non_completing_outcomes: string[];
197
+ assertion_policy: string;
198
+ source_authority: string;
199
+ product_goal: string;
200
+ surface_ia_lock?: string;
201
+ decision_lock?: string;
202
+ context_delta?: string;
203
+ source_to_context_coverage?: string;
204
+ acceptance_semantics?: string;
205
+ impact?: string;
116
206
  }
117
207
  export interface SuperpowersProgressState {
118
208
  system_capability_progress: Record<string, unknown>;
@@ -131,13 +221,33 @@ export interface SuperpowersPlanItem {
131
221
  representative_samples: string[];
132
222
  full_population_boundary: string;
133
223
  non_required_population: string[];
224
+ owner_boundary: string;
225
+ primary_capability_path: string;
226
+ trigger_contract: string;
227
+ state_transition_contract: string;
228
+ observable_result_contract: string;
229
+ assertion_support: string;
230
+ required_assertion_commands: string[];
231
+ invalid_implementation_shortcuts: string[];
134
232
  owner_surfaces: string[];
135
233
  forbidden_surfaces: string[];
136
234
  implementation_paths: string[];
137
235
  required_tests: string[];
138
236
  proof_layer_ids?: string[];
237
+ requirement_ref?: string;
238
+ decision_id?: string;
239
+ api_schema_changes?: string;
240
+ state_machine?: string;
241
+ data_flow?: string;
242
+ worker_runtime_behavior?: string;
243
+ ui_ia_changes?: string;
244
+ migration_plan?: string;
245
+ evidence_artifacts?: string[];
139
246
  non_completing_shortcuts?: string[];
140
247
  substitution_policy?: string[];
248
+ drift_severity?: string;
249
+ partial_conditions?: string[];
250
+ blockers?: string[];
141
251
  explicit_no_test_scope?: boolean;
142
252
  context_fact_refs?: string[];
143
253
  status: SuperpowersPlanItemStatus;
@@ -157,10 +267,28 @@ export interface SuperpowersAcceptanceCriterion {
157
267
  related_plan_items: string[];
158
268
  required_proof_layers: string[];
159
269
  assertion_requirements?: AssertionRequirement[];
270
+ assertion_command?: string;
271
+ assertion_artifacts?: string[];
272
+ positive_assertions?: string[];
273
+ negative_assertions?: string[];
274
+ machine_blocking?: boolean | null;
275
+ invalid_completion_signals?: string[];
276
+ assertion_result_required?: boolean | null;
277
+ ac_type?: string;
278
+ proof_chain?: string[];
160
279
  required_test_ids?: string[];
161
280
  fail_conditions?: string[];
162
281
  invalid_evidence?: string[];
282
+ substitution_policy?: string[];
283
+ missing_layer_downgrade?: string;
284
+ auditor_expectation?: string;
285
+ out_of_scope_na_approval_source?: string;
286
+ hard_blockers?: string[];
287
+ validates_explanation?: string;
288
+ does_not_validate_explanation?: string;
163
289
  final_evidence_expected?: string[];
290
+ verification_method?: string[];
291
+ test_cases?: string[];
164
292
  explicit_no_test_scope?: boolean;
165
293
  status: SuperpowersAcceptanceStatus;
166
294
  }
@@ -168,6 +296,10 @@ export interface AssertionRequirement {
168
296
  proof_layer: string;
169
297
  required: boolean;
170
298
  machine_blocking: boolean;
299
+ assertion_result_required?: boolean;
300
+ assertion_command?: string;
301
+ assertion_artifacts?: string[];
302
+ invalid_completion_signals?: string[];
171
303
  required_test_ids: string[];
172
304
  positive_assertions: string[];
173
305
  negative_assertions: string[];
@@ -201,7 +333,24 @@ export interface SuperpowersSliceRecord {
201
333
  };
202
334
  }
203
335
  export interface SuperpowersEvidenceRecord {
336
+ schema_version?: "evidence-record-v1" | "evidence-record-v2" | string;
204
337
  evidence_id: string;
338
+ task_attempt_id?: string;
339
+ source_bundle_hash?: string;
340
+ product_source_hash?: string;
341
+ technical_plan_hash?: string;
342
+ acceptance_checklist_hash?: string;
343
+ git_head?: string;
344
+ worktree_fingerprint?: string;
345
+ command_spec_id?: string;
346
+ command_run_id?: string;
347
+ command_line?: string;
348
+ artifact_path?: string;
349
+ artifact_sha256?: string;
350
+ artifact_mtime?: string;
351
+ target_ac_ids?: string[];
352
+ target_pi_ids?: string[];
353
+ target_proof_layers?: string[];
205
354
  slice_id: string;
206
355
  type: string;
207
356
  freshness: {
@@ -228,17 +377,21 @@ export interface SuperpowersEvidenceRecord {
228
377
  sibling_substitution_approval_source?: string;
229
378
  }
230
379
  export interface AssertionResult {
231
- schema_version: "assertion-result-v1";
380
+ schema_version: "assertion-result-v1" | "assertion-result-v2";
232
381
  status: "passed" | "failed" | "blocked" | "stale";
233
382
  runner: string;
234
383
  exit_code: number;
235
384
  target_ac_ids: string[];
385
+ target_pi_ids?: string[];
236
386
  target_proof_layers: string[];
237
387
  owner_surface?: string;
238
388
  route?: string;
239
389
  action?: string;
240
390
  positive_assertions: AssertionCheck[];
241
391
  negative_assertions: AssertionCheck[];
392
+ invalid_completion_signals?: AssertionCheck[];
393
+ negative_evidence_scan?: NegativeEvidenceScan;
394
+ required_test_ids?: string[];
242
395
  artifacts?: string[];
243
396
  }
244
397
  export interface AssertionCheck {
@@ -252,6 +405,8 @@ export interface NegativeEvidenceScan {
252
405
  schema_version: "negative-evidence-scan-v1";
253
406
  status: "passed" | "failed" | "blocked" | "stale";
254
407
  target_ac_ids: string[];
408
+ target_proof_layers?: string[];
409
+ invalid_completion_signals_checked?: string[];
255
410
  owner_surface?: string;
256
411
  route?: string;
257
412
  forbidden_findings: NegativeFinding[];
@@ -4,7 +4,24 @@ export const SUPERPOWERS_TASK_STATE_JSON_SCHEMA = {
4
4
  $id: "https://project-tiny-context-harness.local/superpowers-task-state.schema.json",
5
5
  title: "Superpowers Long-Task State",
6
6
  type: "object",
7
- required: ["meta", "sources", "context", "delivery", "graph", "slices", "evidence", "gates", "progress", "blockers", "final"],
7
+ required: [
8
+ "meta",
9
+ "sources",
10
+ "context",
11
+ "delivery",
12
+ "graph",
13
+ "attempts",
14
+ "current_attempt_id",
15
+ "required_command_specs",
16
+ "command_runs",
17
+ "negative_evidence_records",
18
+ "slices",
19
+ "evidence",
20
+ "gates",
21
+ "progress",
22
+ "blockers",
23
+ "final"
24
+ ],
8
25
  properties: {
9
26
  meta: {
10
27
  type: "object",
@@ -19,6 +36,11 @@ export const SUPERPOWERS_TASK_STATE_JSON_SCHEMA = {
19
36
  context: { type: "object" },
20
37
  delivery: { type: "object" },
21
38
  graph: { type: "object" },
39
+ attempts: { type: "array" },
40
+ current_attempt_id: { type: "string" },
41
+ required_command_specs: { type: "array" },
42
+ command_runs: { type: "array" },
43
+ negative_evidence_records: { type: "array" },
22
44
  slices: { type: "array" },
23
45
  evidence: { type: "array" },
24
46
  gates: { type: "object" },
@@ -0,0 +1,3 @@
1
+ import { type SuperpowersTaskState } from "./superpowers-task-state-schema.js";
2
+ export declare function validateShape(state: SuperpowersTaskState, errors: string[]): void;
3
+ export declare function hasUsableShape(state: SuperpowersTaskState): boolean;