project-tiny-context-harness 0.2.81 → 0.2.82

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.
@@ -0,0 +1,276 @@
1
+ export const PRODUCT_FIELDS = [
2
+ "delivery_scope",
3
+ "full_population_required",
4
+ "representative_samples_validate",
5
+ "representative_samples_do_not_validate",
6
+ "out_of_scope_backlog",
7
+ "scope_fit_decision",
8
+ "selected_scope_fit_slice",
9
+ "owner_boundary",
10
+ "primary_capability_path",
11
+ "non_completing_outcomes",
12
+ "assertion_policy",
13
+ "source_authority",
14
+ "product_goal",
15
+ "surface_ia_lock",
16
+ "decision_lock",
17
+ "context_delta",
18
+ "source_to_context_coverage",
19
+ "acceptance_semantics",
20
+ "impact"
21
+ ];
22
+ export const PLAN_FIELDS = [
23
+ "delivery_scope",
24
+ "capability_target",
25
+ "representative_samples",
26
+ "full_population_boundary",
27
+ "non_required_population",
28
+ "owner_surfaces",
29
+ "forbidden_surfaces",
30
+ "owner_boundary",
31
+ "primary_capability_path",
32
+ "trigger_contract",
33
+ "state_transition_contract",
34
+ "observable_result_contract",
35
+ "assertion_support",
36
+ "required_assertion_commands",
37
+ "invalid_implementation_shortcuts",
38
+ "implementation_paths",
39
+ "required_tests",
40
+ "related_acs",
41
+ "requirement_ref",
42
+ "decision_id",
43
+ "proof_layer_ids",
44
+ "api_schema_changes",
45
+ "state_machine",
46
+ "data_flow",
47
+ "worker_runtime_behavior",
48
+ "ui_ia_changes",
49
+ "migration_plan",
50
+ "evidence_artifacts",
51
+ "explicit_no_test_scope",
52
+ "non_completing_shortcuts",
53
+ "substitution_policy",
54
+ "drift_severity",
55
+ "partial_conditions",
56
+ "blockers",
57
+ "context_fact_refs"
58
+ ];
59
+ export const ACCEPTANCE_FIELDS = [
60
+ "acceptance_scope",
61
+ "ac_validates",
62
+ "ac_does_not_validate",
63
+ "sample_boundary",
64
+ "full_population_required",
65
+ "related_plan_items",
66
+ "required_proof_layers",
67
+ "assertion_command",
68
+ "assertion_artifacts",
69
+ "positive_assertions",
70
+ "negative_assertions",
71
+ "machine_blocking",
72
+ "invalid_completion_signals",
73
+ "assertion_result_required",
74
+ "ac_type",
75
+ "proof_chain",
76
+ "verification_method",
77
+ "fail_conditions",
78
+ "invalid_evidence",
79
+ "substitution_policy",
80
+ "missing_layer_downgrade",
81
+ "auditor_expectation",
82
+ "out_of_scope_na_approval_source",
83
+ "required_test_ids",
84
+ "explicit_no_test_scope",
85
+ "hard_blockers",
86
+ "validates_explanation",
87
+ "does_not_validate_explanation",
88
+ "final_evidence_expected",
89
+ "test_cases"
90
+ ];
91
+ export const PRODUCT_REQUIRED_FIELDS = [
92
+ "delivery_scope",
93
+ "full_population_required",
94
+ "representative_samples_validate",
95
+ "representative_samples_do_not_validate",
96
+ "out_of_scope_backlog",
97
+ "scope_fit_decision",
98
+ "selected_scope_fit_slice",
99
+ "owner_boundary",
100
+ "primary_capability_path",
101
+ "non_completing_outcomes",
102
+ "assertion_policy",
103
+ "source_authority",
104
+ "product_goal"
105
+ ];
106
+ export const PLAN_REQUIRED_FIELDS = [
107
+ "delivery_scope",
108
+ "capability_target",
109
+ "representative_samples",
110
+ "full_population_boundary",
111
+ "non_required_population",
112
+ "owner_boundary",
113
+ "primary_capability_path",
114
+ "trigger_contract",
115
+ "state_transition_contract",
116
+ "observable_result_contract",
117
+ "assertion_support",
118
+ "required_assertion_commands",
119
+ "invalid_implementation_shortcuts",
120
+ "implementation_paths"
121
+ ];
122
+ export const ACCEPTANCE_REQUIRED_FIELDS = [
123
+ "acceptance_scope",
124
+ "ac_validates",
125
+ "ac_does_not_validate",
126
+ "sample_boundary",
127
+ "full_population_required",
128
+ "related_plan_items",
129
+ "required_proof_layers",
130
+ "assertion_command",
131
+ "assertion_artifacts",
132
+ "positive_assertions",
133
+ "negative_assertions",
134
+ "machine_blocking",
135
+ "invalid_completion_signals",
136
+ "assertion_result_required"
137
+ ];
138
+ export const PRODUCT_FIELD_TYPES = {
139
+ delivery_scope: "enum",
140
+ full_population_required: "boolean",
141
+ representative_samples_validate: "array",
142
+ representative_samples_do_not_validate: "array",
143
+ out_of_scope_backlog: "array",
144
+ scope_fit_decision: "enum",
145
+ selected_scope_fit_slice: "text",
146
+ owner_boundary: "text",
147
+ primary_capability_path: "text",
148
+ non_completing_outcomes: "array",
149
+ assertion_policy: "text",
150
+ source_authority: "text",
151
+ product_goal: "text",
152
+ surface_ia_lock: "text",
153
+ decision_lock: "text",
154
+ context_delta: "text",
155
+ source_to_context_coverage: "text",
156
+ acceptance_semantics: "text",
157
+ impact: "text"
158
+ };
159
+ export const PLAN_FIELD_TYPES = {
160
+ delivery_scope: "enum",
161
+ capability_target: "text",
162
+ representative_samples: "array",
163
+ full_population_boundary: "text",
164
+ non_required_population: "array",
165
+ owner_surfaces: "array",
166
+ forbidden_surfaces: "array",
167
+ owner_boundary: "text",
168
+ primary_capability_path: "text",
169
+ trigger_contract: "text",
170
+ state_transition_contract: "text",
171
+ observable_result_contract: "text",
172
+ assertion_support: "text",
173
+ required_assertion_commands: "array",
174
+ invalid_implementation_shortcuts: "array",
175
+ implementation_paths: "array",
176
+ required_tests: "array",
177
+ related_acs: "array",
178
+ requirement_ref: "text",
179
+ decision_id: "text",
180
+ proof_layer_ids: "array",
181
+ api_schema_changes: "text",
182
+ state_machine: "text",
183
+ data_flow: "text",
184
+ worker_runtime_behavior: "text",
185
+ ui_ia_changes: "text",
186
+ migration_plan: "text",
187
+ evidence_artifacts: "array",
188
+ explicit_no_test_scope: "boolean",
189
+ non_completing_shortcuts: "array",
190
+ substitution_policy: "array",
191
+ drift_severity: "text",
192
+ partial_conditions: "array",
193
+ blockers: "array",
194
+ context_fact_refs: "array"
195
+ };
196
+ export const ACCEPTANCE_FIELD_TYPES = {
197
+ acceptance_scope: "enum",
198
+ ac_validates: "array",
199
+ ac_does_not_validate: "array",
200
+ sample_boundary: "text",
201
+ full_population_required: "boolean",
202
+ related_plan_items: "array",
203
+ required_proof_layers: "array",
204
+ assertion_command: "text",
205
+ assertion_artifacts: "array",
206
+ positive_assertions: "array",
207
+ negative_assertions: "array",
208
+ machine_blocking: "boolean",
209
+ invalid_completion_signals: "array",
210
+ assertion_result_required: "boolean",
211
+ ac_type: "text",
212
+ proof_chain: "array",
213
+ verification_method: "array",
214
+ fail_conditions: "array",
215
+ invalid_evidence: "array",
216
+ substitution_policy: "array",
217
+ missing_layer_downgrade: "text",
218
+ auditor_expectation: "text",
219
+ out_of_scope_na_approval_source: "text",
220
+ required_test_ids: "array",
221
+ explicit_no_test_scope: "boolean",
222
+ hard_blockers: "array",
223
+ validates_explanation: "text",
224
+ does_not_validate_explanation: "text",
225
+ final_evidence_expected: "array",
226
+ test_cases: "array"
227
+ };
228
+ export const PRODUCT_DELIVERY_SCOPES = new Set([
229
+ "system_capability_build", "representative_sample_validation", "full_population_operation", "mixed_scope_requires_boundary"
230
+ ]);
231
+ export const PLAN_DELIVERY_SCOPES = new Set([
232
+ "system_capability_build", "representative_sample_validation", "full_population_operation", "out_of_scope_backlog"
233
+ ]);
234
+ export const ACCEPTANCE_SCOPES = new Set([
235
+ "system_capability_build", "representative_sample_validation", "full_population_operation", "full_population_not_required"
236
+ ]);
237
+ export const SCOPE_FIT_DECISIONS = new Set(["fit_for_three_inputs", "selected_from_split", "blocked_for_decision"]);
238
+ export const CANONICAL_PROOF_LAYERS = [
239
+ "code",
240
+ "api_schema",
241
+ "worker_runtime",
242
+ "data_artifact",
243
+ "integration",
244
+ "ui_browser",
245
+ "security_redaction",
246
+ "all_provider_all_runner",
247
+ "cleanup_stale_scan",
248
+ "test"
249
+ ];
250
+ export const LEGACY_PROOF_LAYER_ALIASES = {
251
+ runtime: "worker_runtime",
252
+ browser: "ui_browser",
253
+ api: "api_schema",
254
+ data: "data_artifact",
255
+ security: "security_redaction"
256
+ };
257
+ export const MACHINE_VERIFIABLE_LAYER_NAMES = new Set(CANONICAL_PROOF_LAYERS.filter((layer) => layer !== "code"));
258
+ export function fieldSet(fields) {
259
+ return new Set(fields);
260
+ }
261
+ export function normalizeProofLayerName(layer) {
262
+ const normalized = layer.trim().toLowerCase().replace(/[- ]+/g, "_");
263
+ return LEGACY_PROOF_LAYER_ALIASES[normalized] ?? normalized;
264
+ }
265
+ export function normalizeProofLayerId(layerId) {
266
+ const value = layerId.trim();
267
+ if (!value.includes(".")) {
268
+ return normalizeProofLayerName(value);
269
+ }
270
+ const acId = value.slice(0, value.lastIndexOf("."));
271
+ const layer = value.slice(value.lastIndexOf(".") + 1);
272
+ return `${acId}.${normalizeProofLayerName(layer)}`;
273
+ }
274
+ export function isSelectedScopeFitSlice(value) {
275
+ return value === "none" || /^SFC-\d{3,}$/i.test(value);
276
+ }
@@ -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]) {
@@ -59,6 +59,7 @@ export type SuperpowersAcceptanceStatus = "not_run" | "complete" | "partial" | "
59
59
  export type SuperpowersProductDeliveryScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "mixed_scope_requires_boundary";
60
60
  export type SuperpowersPlanDeliveryScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "out_of_scope_backlog";
61
61
  export type SuperpowersAcceptanceScope = "system_capability_build" | "representative_sample_validation" | "full_population_operation" | "full_population_not_required";
62
+ export type SuperpowersScopeFitDecision = "fit_for_three_inputs" | "selected_from_split" | "blocked_for_decision" | "";
62
63
  export interface SuperpowersTaskState {
63
64
  meta: {
64
65
  task_id: string;
@@ -113,6 +114,20 @@ export interface SuperpowersProductArchitectureScope {
113
114
  representative_samples_validate: string[];
114
115
  representative_samples_do_not_validate: string[];
115
116
  out_of_scope_backlog: string[];
117
+ scope_fit_decision: SuperpowersScopeFitDecision;
118
+ selected_scope_fit_slice: string;
119
+ owner_boundary: string;
120
+ primary_capability_path: string;
121
+ non_completing_outcomes: string[];
122
+ assertion_policy: string;
123
+ source_authority: string;
124
+ product_goal: string;
125
+ surface_ia_lock?: string;
126
+ decision_lock?: string;
127
+ context_delta?: string;
128
+ source_to_context_coverage?: string;
129
+ acceptance_semantics?: string;
130
+ impact?: string;
116
131
  }
117
132
  export interface SuperpowersProgressState {
118
133
  system_capability_progress: Record<string, unknown>;
@@ -131,13 +146,33 @@ export interface SuperpowersPlanItem {
131
146
  representative_samples: string[];
132
147
  full_population_boundary: string;
133
148
  non_required_population: string[];
149
+ owner_boundary: string;
150
+ primary_capability_path: string;
151
+ trigger_contract: string;
152
+ state_transition_contract: string;
153
+ observable_result_contract: string;
154
+ assertion_support: string;
155
+ required_assertion_commands: string[];
156
+ invalid_implementation_shortcuts: string[];
134
157
  owner_surfaces: string[];
135
158
  forbidden_surfaces: string[];
136
159
  implementation_paths: string[];
137
160
  required_tests: string[];
138
161
  proof_layer_ids?: string[];
162
+ requirement_ref?: string;
163
+ decision_id?: string;
164
+ api_schema_changes?: string;
165
+ state_machine?: string;
166
+ data_flow?: string;
167
+ worker_runtime_behavior?: string;
168
+ ui_ia_changes?: string;
169
+ migration_plan?: string;
170
+ evidence_artifacts?: string[];
139
171
  non_completing_shortcuts?: string[];
140
172
  substitution_policy?: string[];
173
+ drift_severity?: string;
174
+ partial_conditions?: string[];
175
+ blockers?: string[];
141
176
  explicit_no_test_scope?: boolean;
142
177
  context_fact_refs?: string[];
143
178
  status: SuperpowersPlanItemStatus;
@@ -157,10 +192,28 @@ export interface SuperpowersAcceptanceCriterion {
157
192
  related_plan_items: string[];
158
193
  required_proof_layers: string[];
159
194
  assertion_requirements?: AssertionRequirement[];
195
+ assertion_command?: string;
196
+ assertion_artifacts?: string[];
197
+ positive_assertions?: string[];
198
+ negative_assertions?: string[];
199
+ machine_blocking?: boolean | null;
200
+ invalid_completion_signals?: string[];
201
+ assertion_result_required?: boolean | null;
202
+ ac_type?: string;
203
+ proof_chain?: string[];
160
204
  required_test_ids?: string[];
161
205
  fail_conditions?: string[];
162
206
  invalid_evidence?: string[];
207
+ substitution_policy?: string[];
208
+ missing_layer_downgrade?: string;
209
+ auditor_expectation?: string;
210
+ out_of_scope_na_approval_source?: string;
211
+ hard_blockers?: string[];
212
+ validates_explanation?: string;
213
+ does_not_validate_explanation?: string;
163
214
  final_evidence_expected?: string[];
215
+ verification_method?: string[];
216
+ test_cases?: string[];
164
217
  explicit_no_test_scope?: boolean;
165
218
  status: SuperpowersAcceptanceStatus;
166
219
  }
@@ -168,6 +221,10 @@ export interface AssertionRequirement {
168
221
  proof_layer: string;
169
222
  required: boolean;
170
223
  machine_blocking: boolean;
224
+ assertion_result_required?: boolean;
225
+ assertion_command?: string;
226
+ assertion_artifacts?: string[];
227
+ invalid_completion_signals?: string[];
171
228
  required_test_ids: string[];
172
229
  positive_assertions: string[];
173
230
  negative_assertions: string[];
@@ -252,6 +309,8 @@ export interface NegativeEvidenceScan {
252
309
  schema_version: "negative-evidence-scan-v1";
253
310
  status: "passed" | "failed" | "blocked" | "stale";
254
311
  target_ac_ids: string[];
312
+ target_proof_layers?: string[];
313
+ invalid_completion_signals_checked?: string[];
255
314
  owner_surface?: string;
256
315
  route?: string;
257
316
  forbidden_findings: NegativeFinding[];