@shiftleftpt/sbd-toe-mcp 0.10.1 → 0.20.0-beta.2

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.
@@ -32,6 +32,108 @@ import { getRegulatoryOverlay, resolveRegulatoryFramework } from "./regulatory-o
32
32
  import { expandQueryWithAliases } from "../backend/semantic-index-gateway.js";
33
33
  import { prepareCodegenAffordances } from "../serving/affordances.js";
34
34
  const EVIDENCE_PATTERN_CAP = 25;
35
+ /**
36
+ * v2 token diet, s3 — evidence-pattern cap applied at `detail: "standard" |
37
+ * "minimal"` ON TOP of the classic cap: the dieted list is the deterministic
38
+ * PREFIX (relevance_score desc, id asc — the exact order the core already
39
+ * emits) of the classic top-{@link EVIDENCE_PATTERN_CAP} list. Never silent:
40
+ * `completeness_report` reports total/returned/capped and, when anything was
41
+ * cut, `evidence_patterns_rest` says how to retrieve the rest (same tool,
42
+ * `detail: "full"`).
43
+ */
44
+ const STANDARD_EVIDENCE_PATTERN_CAP = 10;
45
+ /**
46
+ * v2 token diet, s3b (revised per the 2026-07-05 operator ADENDA in
47
+ * agentic/planeado/v2-token-diet/EPIC.md — no top-N, no subsetting of the
48
+ * activated set): at `detail: "minimal"` the evidence cap tightens 10→5 with
49
+ * the SAME s3 mechanism (deterministic prefix, never-silent counts +
50
+ * executable rest-reference). This cap — together with the minimal
51
+ * `manual_grounding` form — is the ONLY divergence from `standard`; the
52
+ * activated scope (requirements/controls/slices/entities, with the verbatim
53
+ * published descriptions) stays COMPLETE and byte-identical to `standard`.
54
+ */
55
+ const MINIMAL_EVIDENCE_PATTERN_CAP = 5;
56
+ /**
57
+ * v2 token diet, s3c (operator ADENDA 2026-07-05, reactivated same day): at
58
+ * `detail: "ultrathin"` NO evidence pattern goes inline (cap 0) — the SAME s3
59
+ * never-silent mechanism still applies in full: `completeness_report` reports
60
+ * total/returned(=0)/capped(=total) and `evidence_patterns_rest` is the
61
+ * executable reference to the CHEAPEST level that returns them inline
62
+ * (detail="minimal" ⇒ top-5; "standard" ⇒ 10; "full" ⇒ classic 25).
63
+ */
64
+ const ULTRATHIN_EVIDENCE_PATTERN_CAP = 0;
65
+ /**
66
+ * Section → source map for the dieted encoding: each list is
67
+ * source-homogeneous BY CONSTRUCTION (the projection types hardcode a single
68
+ * source literal per list), so one entry per list reconstitutes the `source`
69
+ * of every item with no exceptions. Published as part of the
70
+ * `sbd://toe/codegen-instructions/{mode}` resource (s3 moved the verbose
71
+ * legend out of every payload); the inline `provenance_legend` keeps a
72
+ * one-line pointer.
73
+ */
74
+ const PROVENANCE_SOURCES = {
75
+ "activated_scope.requirements": "runtime_v0",
76
+ "activated_scope.controls": "runtime_v0",
77
+ "activated_scope.slices": "runtime_v1",
78
+ "activated_scope.regulatory_obligations": "overlay",
79
+ "g2_context.control_objectives": "runtime_v1",
80
+ "g2_context.mechanisms": "runtime_v1",
81
+ "g2_context.practices": "runtime_v1",
82
+ "g2_context.artifacts": "runtime_v1",
83
+ "g2_context.relations": "runtime_v1",
84
+ "g2_context.evidence_patterns": "runtime_v0",
85
+ "manual_grounding.groups": "runtime_v1",
86
+ "regulatory_overlay.frameworks": "overlay",
87
+ "regulatory_overlay.obligations": "overlay",
88
+ "regulatory_overlay.mappings": "overlay",
89
+ "regulatory_overlay.playbooks": "overlay"
90
+ };
91
+ /**
92
+ * Inline legend for `standard`/`minimal` (s3: slim pointer — the full legend,
93
+ * including the section→source table and every derivation rule of the dieted
94
+ * encoding, lives in the `sbd://toe/codegen-instructions/{mode}` resource,
95
+ * section `detail_encoding`).
96
+ */
97
+ const PROVENANCE_LEGEND = {
98
+ note: "Deduplicated encoding (detail=standard/minimal): per-item `source` fields " +
99
+ "are elided (every list is source-homogeneous), requirement `category` = " +
100
+ "requirement_id prefix, g2_context entity lists are grouped as " +
101
+ "{slice_id: {entity_id: name|null}}, and citations ids are referenced via " +
102
+ "ids_from payload paths. Full legend: MCP resource " +
103
+ "sbd://toe/codegen-instructions/{mode}, section detail_encoding."
104
+ };
105
+ /**
106
+ * Inline legend for `ultrathin` (s3c) — the standard/minimal legend text is
107
+ * NEVER edited (snapshots are byte-frozen); ultrathin carries its own note
108
+ * with the extra cut rules. Full legend: same MCP resource, section
109
+ * `detail_encoding` (incl. the `ultrathin` entry).
110
+ */
111
+ const PROVENANCE_LEGEND_ULTRATHIN = {
112
+ note: "Deduplicated encoding (detail=ultrathin): same rules as detail=standard/" +
113
+ "minimal — per-item `source` elided, requirement `category` = " +
114
+ "requirement_id prefix, g2_context entity lists grouped as " +
115
+ "{slice_id: {entity_id: name|null}}, citations ids via ids_from payload " +
116
+ "paths — PLUS: published `description` fields elided (executable " +
117
+ "activated_scope.descriptions_ref, detail='minimal'), evidence_patterns 0 " +
118
+ "inline (counts + rest-ref in completeness_report), manual_grounding " +
119
+ "aggregate-only (total + sha + groups_ref) and completeness diagnostics " +
120
+ "as exact counts (+ ref). Nothing silently dropped. Full legend: MCP " +
121
+ "resource sbd://toe/codegen-instructions/{mode}, section detail_encoding."
122
+ };
123
+ /**
124
+ * v2 token diet, s4 — cheap turns, not fewer turns: short note (≈50 tokens)
125
+ * appended to every `standard`/`minimal` ready payload. The production
126
+ * write-test-edit loop is legitimate; what must not repeat is the cost of
127
+ * re-requesting THIS payload — an identical call returns a byte-identical
128
+ * result (deterministic, tested), so the context already in the session is
129
+ * the source for the loop. Follow-ups that genuinely need more go through
130
+ * `detail: "minimal"` or a targeted `consult_security_requirements` call —
131
+ * never a repeat of the full payload. `full` carries NO hint (byte-identical
132
+ * to the classic payload, EPIC invariant 1).
133
+ */
134
+ export const REPEAT_CALL_HINT = "Identical input returns this exact payload (deterministic) — reuse the " +
135
+ "context already received instead of re-calling; deepen via " +
136
+ "detail:'minimal' or a targeted consult_security_requirements.";
35
137
  // ---------------------------------------------------------------------------
36
138
  // Activation lexicon (small, auditable; WP6 layers semantic scoring on top)
37
139
  // ---------------------------------------------------------------------------
@@ -926,32 +1028,236 @@ function resolveOverlay(input) {
926
1028
  activatedFrameworks
927
1029
  };
928
1030
  }
929
- // ---------------------------------------------------------------------------
930
- // LLM instructions
931
- // ---------------------------------------------------------------------------
932
- function buildLlmInstructions(args) {
933
- const instructions = [];
934
- instructions.push("Generate code or review changes ONLY against the deterministic IDs provided in `citation_map`. Do NOT invent SbD-ToE requirement, control, slice, mechanism or obligation IDs.");
935
- instructions.push("For each non-trivial design decision, populate the `security_rationale_template.decisions[].cited_ids` with IDs from `citation_map`. If no ID applies, say so explicitly.");
936
- instructions.push("List concrete validations in `security_rationale_template.validations` (surface, rule, rejection behaviour). Do NOT claim conformity without naming the validation.");
937
- instructions.push("List expected evidence in `security_rationale_template.expected_evidence` (test paths, log shapes, SBOM, attestation, scan reports). Code on its own is NOT evidence of compliance.");
938
- if (args.hasOverlay) {
939
- instructions.push("Regulatory obligations are an EXTERNAL cross-check. Cite obligation IDs in security_rationale only when the change directly addresses them. Do NOT declare GDPR/DORA/CRA/NIS2 compliance.");
940
- }
941
- instructions.push("If the requested task does not match the activated scope, REPLY with `status: needs_clarification` and request specifics — do not fabricate IDs.");
942
- if (args.mode === "review") {
943
- instructions.push("Review mode: enumerate findings per changed_file, mapped to the activated_scope. Each finding must reference at least one citation_map ID or say 'no normative ID covers this'.");
944
- }
945
- if (args.mode === "test-plan") {
946
- instructions.push("Test-plan mode: produce a checklist of tests grouped by validated_id, with input/expectation, and reference evidence_patterns when available.");
1031
+ /**
1032
+ * Ordered instruction slots for a mode. The emission order of
1033
+ * {@link buildLlmInstructions} is EXACTLY this list filtered by active
1034
+ * conditions — the classic (pre-s3) output is byte-identical by construction.
1035
+ */
1036
+ export function instructionSlotsForMode(mode) {
1037
+ const slots = [
1038
+ {
1039
+ when: "always",
1040
+ text: "Generate code or review changes ONLY against the deterministic IDs provided in `citation_map`. Do NOT invent SbD-ToE requirement, control, slice, mechanism or obligation IDs."
1041
+ },
1042
+ {
1043
+ when: "always",
1044
+ text: "For each non-trivial design decision, populate the `security_rationale_template.decisions[].cited_ids` with IDs from `citation_map`. If no ID applies, say so explicitly."
1045
+ },
1046
+ {
1047
+ when: "always",
1048
+ text: "List concrete validations in `security_rationale_template.validations` (surface, rule, rejection behaviour). Do NOT claim conformity without naming the validation."
1049
+ },
1050
+ {
1051
+ when: "always",
1052
+ text: "List expected evidence in `security_rationale_template.expected_evidence` (test paths, log shapes, SBOM, attestation, scan reports). Code on its own is NOT evidence of compliance."
1053
+ },
1054
+ {
1055
+ when: "regulatory_overlay",
1056
+ text: "Regulatory obligations are an EXTERNAL cross-check. Cite obligation IDs in security_rationale only when the change directly addresses them. Do NOT declare GDPR/DORA/CRA/NIS2 compliance."
1057
+ },
1058
+ {
1059
+ when: "always",
1060
+ text: "If the requested task does not match the activated scope, REPLY with `status: needs_clarification` and request specifics — do not fabricate IDs."
1061
+ }
1062
+ ];
1063
+ if (mode === "review") {
1064
+ slots.push({
1065
+ when: "always",
1066
+ text: "Review mode: enumerate findings per changed_file, mapped to the activated_scope. Each finding must reference at least one citation_map ID or say 'no normative ID covers this'."
1067
+ });
947
1068
  }
948
- if (args.riskLevel) {
949
- instructions.push(`Risk level ${args.riskLevel} is the active filter — do not propose controls applicable only at a higher level unless explicitly justified.`);
1069
+ if (mode === "test-plan") {
1070
+ slots.push({
1071
+ when: "always",
1072
+ text: "Test-plan mode: produce a checklist of tests grouped by validated_id, with input/expectation, and reference evidence_patterns when available."
1073
+ });
950
1074
  }
951
- if (args.citedIds.length === 0) {
952
- instructions.push("Citation_map is empty. This is a strong signal the activated scope did not yield deterministic anchors — request clarification before generating code.");
1075
+ for (const level of ["L1", "L2", "L3"]) {
1076
+ slots.push({
1077
+ when: `risk_level:${level}`,
1078
+ text: `Risk level ${level} is the active filter — do not propose controls applicable only at a higher level unless explicitly justified.`
1079
+ });
953
1080
  }
954
- return instructions;
1081
+ slots.push({
1082
+ when: "citation_map_empty",
1083
+ text: "Citation_map is empty. This is a strong signal the activated scope did not yield deterministic anchors — request clarification before generating code."
1084
+ });
1085
+ return slots;
1086
+ }
1087
+ /** Conditional slots active for a call (deterministic, from resolved inputs). */
1088
+ function activeInstructionConditions(args) {
1089
+ const active = [];
1090
+ if (args.hasOverlay)
1091
+ active.push("regulatory_overlay");
1092
+ if (args.riskLevel)
1093
+ active.push(`risk_level:${args.riskLevel}`);
1094
+ if (args.citationMapEmpty)
1095
+ active.push("citation_map_empty");
1096
+ return active;
1097
+ }
1098
+ function buildLlmInstructions(args) {
1099
+ const active = new Set(activeInstructionConditions({
1100
+ hasOverlay: args.hasOverlay,
1101
+ riskLevel: args.riskLevel,
1102
+ citationMapEmpty: args.citedIds.length === 0
1103
+ }));
1104
+ return instructionSlotsForMode(args.mode)
1105
+ .filter((slot) => slot.when === "always" || active.has(slot.when))
1106
+ .map((slot) => slot.text);
1107
+ }
1108
+ /** Constant part of the security_rationale_template (everything except `task`). */
1109
+ const SECURITY_RATIONALE_TEMPLATE_SKELETON = {
1110
+ decisions: [
1111
+ {
1112
+ decision: "<fill: what design choice was made>",
1113
+ rationale: "<fill: why, citing IDs from citation_map>",
1114
+ cited_ids: ["<requirement_id|control_id|slice_id|obligation_id>"]
1115
+ }
1116
+ ],
1117
+ validations: [
1118
+ {
1119
+ surface: "<fill: code path being validated>",
1120
+ rule: "<fill: validation rule>",
1121
+ rejection_behaviour: "<fill: how invalid input is rejected>"
1122
+ }
1123
+ ],
1124
+ expected_evidence: [
1125
+ {
1126
+ artefact: "<fill: test, log, doc, sbom, scan, attestation, ...>",
1127
+ location: "<fill: where to find it>",
1128
+ verifies: "<fill: which control/requirement id>"
1129
+ }
1130
+ ],
1131
+ residual_risk: "<fill: anything NOT addressed by this change>"
1132
+ };
1133
+ function buildSecurityRationaleTemplate(task) {
1134
+ return { task, ...SECURITY_RATIONALE_TEMPLATE_SKELETON };
1135
+ }
1136
+ // ---------------------------------------------------------------------------
1137
+ // MCP resource: sbd://toe/codegen-instructions/{mode} (v2 token diet, s3)
1138
+ // ---------------------------------------------------------------------------
1139
+ export const CODEGEN_INSTRUCTION_MODES = [
1140
+ "codegen",
1141
+ "review",
1142
+ "test-plan"
1143
+ ];
1144
+ export const CODEGEN_INSTRUCTIONS_RESOURCE_URI_PREFIX = "sbd://toe/codegen-instructions/";
1145
+ export function codegenInstructionsResourceUri(mode) {
1146
+ return `${CODEGEN_INSTRUCTIONS_RESOURCE_URI_PREFIX}${mode}`;
1147
+ }
1148
+ /**
1149
+ * Full legend of the dieted (`standard`/`minimal`) encoding, published in the
1150
+ * codegen-instructions resource. Every rule here is a lossless, deterministic
1151
+ * derivation over the SAME payload (or an executable reference) — nothing is
1152
+ * silently dropped (EPIC invariant 2) and no data changes, only serialization
1153
+ * (EPIC invariant 4).
1154
+ */
1155
+ const DETAIL_ENCODING_LEGEND = {
1156
+ note: "How to read a detail=standard/minimal payload of prepare_sbd_toe_codegen_context. " +
1157
+ "Every rule below is a deterministic re-encoding of the same published data: " +
1158
+ "nothing is silently dropped, and detail=full always returns the classic inline payload.",
1159
+ sources: {
1160
+ note: "Per-item `source` fields are elided. Every list below is source-homogeneous " +
1161
+ "(no exceptions): apply the listed source to each of its items. " +
1162
+ "g2_context.relations applies only when relations come inline " +
1163
+ "(include_relations=true); otherwise g2_context.relations_ref is a derived " +
1164
+ "reference to trace_sbd_toe_graph calls, not a source list.",
1165
+ map: PROVENANCE_SOURCES
1166
+ },
1167
+ citations: "citations.<source>.source_data is an ordered run-length map file -> count. " +
1168
+ "The citable ids are NOT repeated: citations.<source>.ids_from is aligned 1:1 " +
1169
+ "with the source_data files, and names the payload path whose ids (in payload " +
1170
+ "order) form that file's run. Paths of the form " +
1171
+ "keys(g2_context.<list>[slice]) iterate the slice groups in order, then the " +
1172
+ "entity-id keys in order. If a file ever has no path mapping, the group " +
1173
+ "carries explicit `ids` instead (lossless fallback).",
1174
+ activated_scope_requirements: "requirement `category` is elided because it equals the requirement_id prefix " +
1175
+ "before the first '-' (verbatim bundle invariant; the field survives inline " +
1176
+ "on any future mismatch). `description` is the verbatim published field from " +
1177
+ "data/publish/runtime/requirements.json — never paraphrased.",
1178
+ activated_scope_controls: "controls with confidence='direct' carry the verbatim published `description` " +
1179
+ "from data/publish/runtime/controls.json.",
1180
+ g2_entities: "g2_context.control_objectives/mechanisms/practices/artifacts are grouped as " +
1181
+ "{slice_id: {entity_id: name|null}}. entity_type is the list the map lives in " +
1182
+ "(ControlObjective/Mechanism/Practice/Artifact), slice_id is the group key, " +
1183
+ "slice_family is activated_scope.slices[].objective_family for that slice_id, " +
1184
+ "and a null name means the entity is unnamed in the published rastreabilidade " +
1185
+ "(the full projection omits `name` for it).",
1186
+ evidence_patterns: "g2_context.evidence_patterns is the deterministic prefix (relevance desc, " +
1187
+ "then id asc; the tool-computed relevance_score is elided — the order carries " +
1188
+ "the ranking) of the classic detail=full list, capped per " +
1189
+ "completeness_report.evidence_pattern_cap. completeness_report reports " +
1190
+ "total/returned/capped and, when anything was cut, evidence_patterns_rest " +
1191
+ "says how to retrieve the rest (same input, detail='full'; with debug=true " +
1192
+ "the ids beyond the classic cap are listed in debug.rejected_candidates).",
1193
+ manual_grounding_minimal: "At detail=minimal, manual_grounding is the aggregated-provenance form " +
1194
+ "(s3b): total_entries, the manual_commit_sha shared by every group " +
1195
+ "(hoisted; a group keeps its own sha inline only if hoisting was not " +
1196
+ "possible), and the (rastreabilidade_role, manual_chapter, manual_file) " +
1197
+ "groups with the exact per-group `entries` COUNT instead of the " +
1198
+ "v1_entity_ids list (counts sum to total_entries — never silent). The " +
1199
+ "grounding id set is already in the same payload (g2_context entity-map " +
1200
+ "keys); manual_grounding.groups_ref is the executable reference (same " +
1201
+ "input, detail='standard') for the per-group id lists — groups align " +
1202
+ "1:1, same order. detail=standard keeps the full grouping inline.",
1203
+ activation_trace: "activation_trace is elided at detail=standard/minimal; " +
1204
+ "activation_trace_ref.entries keeps the exact count. Re-call with debug=true " +
1205
+ "to include the full trace (it is always inline at detail=full).",
1206
+ relations_ref: "Inline g2_context.relations are elided at detail=standard/minimal (re-call " +
1207
+ "with include_relations=true to restore them). Recover the elided graph edges " +
1208
+ "by executing trace_sbd_toe_graph with each {lens, anchor} pair listed " +
1209
+ "(anchors are activated slice/entity ids from the same payload); the " +
1210
+ "belongsToSlice edges counted as coverage.implicit_in_entities are already " +
1211
+ "encoded by the slice grouping key of every g2_context entity; any relation " +
1212
+ "covered by neither stays inline in residual_relations (never silent).",
1213
+ ultrathin: "detail=ultrathin (s3c) applies every rule above PLUS: (1) requirements " +
1214
+ "{requirement_id, name, type} and controls {control_id, name, domain, " +
1215
+ "control_type, confidence} keep the COMPLETE activated set (same ids, " +
1216
+ "same order, name always present) but elide the published `description` " +
1217
+ "— activated_scope.descriptions_ref is the executable reference (same " +
1218
+ "input, detail='minimal') for the verbatim descriptions; (2) " +
1219
+ "g2_context.evidence_patterns is empty (cap 0) — completeness_report " +
1220
+ "keeps total/returned=0/capped=total and evidence_patterns_rest points " +
1221
+ "to detail='minimal' (cheapest level returning patterns inline; " +
1222
+ "'standard' returns 10, 'full' the classic 25); (3) manual_grounding is " +
1223
+ "{total_entries, manual_commit_sha, groups_ref} — the group list is " +
1224
+ "elided (detail='standard' returns the full 1:1 grouping); (4) " +
1225
+ "v1_consistency_mismatches/v1_manifest_warnings text arrays are replaced " +
1226
+ "by exact *_count fields (+ v1_diagnostics_ref when any count > 0, " +
1227
+ "detail='minimal' returns the texts). The citable id set and the " +
1228
+ "citations/ids_from encoding are IDENTICAL to the other dieted levels."
1229
+ };
1230
+ /**
1231
+ * Content of the `sbd://toe/codegen-instructions/{mode}` MCP resource — the
1232
+ * static-per-mode boilerplate that detail=standard/minimal payloads reference
1233
+ * instead of carrying inline. Reconstructing the inline `full` content from
1234
+ * this resource is byte-exact (tested):
1235
+ * - llm_codegen_instructions = slots filtered by `when` ("always" +
1236
+ * codegen_instructions_ref.active_conditions), in order;
1237
+ * - security_rationale_template = template with `task` set to the trimmed
1238
+ * task string (input_echo.task.trim()).
1239
+ */
1240
+ export function buildCodegenInstructionsResourceContent(mode) {
1241
+ return {
1242
+ resource: codegenInstructionsResourceUri(mode),
1243
+ mode,
1244
+ note: "Static per-mode boilerplate for prepare_sbd_toe_codegen_context at " +
1245
+ "detail=standard/minimal (kept inline at detail=full). Also carries the " +
1246
+ "detail_encoding legend for the dieted payload.",
1247
+ llm_codegen_instructions: {
1248
+ assembly: "Include each slot whose `when` is 'always' or appears in this call's " +
1249
+ "codegen_instructions_ref.active_conditions, in the listed order — the " +
1250
+ "result is byte-identical to the detail=full inline llm_codegen_instructions.",
1251
+ slots: instructionSlotsForMode(mode)
1252
+ },
1253
+ security_rationale_template: {
1254
+ assembly: "Set `task` to the trimmed task string (input_echo.task.trim()); every " +
1255
+ "other field is verbatim — the result is byte-identical to the " +
1256
+ "detail=full inline security_rationale_template.",
1257
+ template: { task: null, ...SECURITY_RATIONALE_TEMPLATE_SKELETON }
1258
+ },
1259
+ detail_encoding: DETAIL_ENCODING_LEGEND
1260
+ };
955
1261
  }
956
1262
  // ---------------------------------------------------------------------------
957
1263
  // Main entry point
@@ -976,10 +1282,690 @@ function blocked(input, raw, status, reasons, suggestions, partial, debug) {
976
1282
  }
977
1283
  return result;
978
1284
  }
1285
+ const DETAIL_LEVELS = new Set([
1286
+ "ultrathin",
1287
+ "minimal",
1288
+ "standard",
1289
+ "full"
1290
+ ]);
1291
+ /**
1292
+ * Validate the `detail` input (v2 token diet, s1). Invalid values fail fast
1293
+ * with a JSON-RPC -32602 (same pattern as trace-graph's lens validation);
1294
+ * omission defaults to `full` — the classic, byte-identical payload.
1295
+ */
1296
+ function parseDetail(raw) {
1297
+ const value = typeof raw === "object" && raw !== null
1298
+ ? raw.detail
1299
+ : undefined;
1300
+ if (value === undefined)
1301
+ return "full";
1302
+ if (typeof value === "string" && DETAIL_LEVELS.has(value)) {
1303
+ return value;
1304
+ }
1305
+ throw Object.assign(new Error(`Invalid "detail": ${JSON.stringify(value)}. Use one of: ultrathin, minimal, standard, full.`), {
1306
+ rpcError: {
1307
+ code: -32602,
1308
+ message: 'Invalid "detail". Use one of: ultrathin, minimal, standard, full.'
1309
+ }
1310
+ });
1311
+ }
1312
+ /**
1313
+ * Validate the `include_relations` input (v2 token diet, s2). Only booleans
1314
+ * (or omission = false) are accepted — same fail-fast pattern as parseDetail.
1315
+ */
1316
+ function parseIncludeRelations(raw) {
1317
+ const value = typeof raw === "object" && raw !== null
1318
+ ? raw.include_relations
1319
+ : undefined;
1320
+ if (value === undefined)
1321
+ return false;
1322
+ if (typeof value === "boolean")
1323
+ return value;
1324
+ throw Object.assign(new Error(`Invalid "include_relations": ${JSON.stringify(value)}. Use a boolean.`), {
1325
+ rpcError: {
1326
+ code: -32602,
1327
+ message: 'Invalid "include_relations". Use a boolean.'
1328
+ }
1329
+ });
1330
+ }
1331
+ // Relation predicates published in data/publish/runtime/v1/relations.jsonl —
1332
+ // the same three the RDF projection exposes to trace_sbd_toe_graph lenses.
1333
+ const PRED_BELONGS_TO_SLICE = "belongsToSlice";
1334
+ const PRED_IMPLEMENTED_BY_MECHANISM = "objective_implemented_by_mechanism";
1335
+ const PRED_REALIZED_BY_PRACTICE = "objective_realized_by_practice";
1336
+ // s3: slimmed — the full explanation lives in the codegen-instructions MCP
1337
+ // resource (detail_encoding.relations_ref). Kept URI-free on purpose: the
1338
+ // no-leak gate scans relations_ref for any scheme://.
1339
+ const RELATIONS_REF_NOTE = "Inline g2_context.relations elided; execute each listed trace_sbd_toe_graph " +
1340
+ "{lens, anchor} call to recover them, or re-call with include_relations=true. " +
1341
+ "Encoding details: MCP resource codegen-instructions, detail_encoding.relations_ref.";
1342
+ /**
1343
+ * v2 token diet, s2 — build the `relations_ref` for `detail: "standard" |
1344
+ * "minimal"`. See the {@link RelationsRefLensCall} doc block for the full
1345
+ * relation-kind → lens mapping. Coverage is decided per relation and counted
1346
+ * (never-silent): every inline relation is either recoverable by executing
1347
+ * one of the referenced curated lenses, byte-redundant with an entity's
1348
+ * `slice_id` in this same payload, or kept inline in `residual_relations`.
1349
+ * Deterministic: lens order follows activated_scope.slices order, then sorted
1350
+ * fallback anchors.
1351
+ */
1352
+ function buildRelationsRef(result) {
1353
+ const relations = result.g2_context.relations;
1354
+ const activatedSliceIds = result.activated_scope.slices.map((slice) => slice.slice_id);
1355
+ const activatedSliceIdSet = new Set(activatedSliceIds);
1356
+ const entitySliceById = new Map();
1357
+ const entityTypeById = new Map();
1358
+ for (const list of [
1359
+ result.g2_context.control_objectives,
1360
+ result.g2_context.mechanisms,
1361
+ result.g2_context.practices,
1362
+ result.g2_context.artifacts
1363
+ ]) {
1364
+ for (const entity of list) {
1365
+ entitySliceById.set(entity.entity_id, entity.slice_id);
1366
+ entityTypeById.set(entity.entity_id, entity.entity_type);
1367
+ }
1368
+ }
1369
+ // Objective → activated slice via an explicit belongsToSlice edge (the
1370
+ // pattern slice_implementation anchors on), and objectives that have at
1371
+ // least one mechanism/practice edge (required by that lens's UNION).
1372
+ const sliceEdgeBySubject = new Map();
1373
+ const subjectsWithTargets = new Set();
1374
+ for (const relation of relations) {
1375
+ if (relation.predicate === PRED_BELONGS_TO_SLICE &&
1376
+ activatedSliceIdSet.has(relation.object_id)) {
1377
+ if (!sliceEdgeBySubject.has(relation.subject_id)) {
1378
+ sliceEdgeBySubject.set(relation.subject_id, relation.object_id);
1379
+ }
1380
+ }
1381
+ else if (relation.predicate === PRED_IMPLEMENTED_BY_MECHANISM ||
1382
+ relation.predicate === PRED_REALIZED_BY_PRACTICE) {
1383
+ subjectsWithTargets.add(relation.subject_id);
1384
+ }
1385
+ }
1386
+ const sliceImplementationAnchors = new Set();
1387
+ const objectiveRealizationAnchors = new Set();
1388
+ const mechanismProvenanceAnchors = new Set();
1389
+ let viaLenses = 0;
1390
+ let implicitInEntities = 0;
1391
+ const residual = [];
1392
+ for (const relation of relations) {
1393
+ if (relation.predicate === PRED_BELONGS_TO_SLICE) {
1394
+ if (activatedSliceIdSet.has(relation.object_id) &&
1395
+ subjectsWithTargets.has(relation.subject_id)) {
1396
+ // slice_implementation(anchor=slice) rows carry this edge.
1397
+ sliceImplementationAnchors.add(relation.object_id);
1398
+ viaLenses += 1;
1399
+ }
1400
+ else if (entitySliceById.get(relation.subject_id) === relation.object_id) {
1401
+ // Redundant with the entity's own slice_id in g2_context.
1402
+ implicitInEntities += 1;
1403
+ }
1404
+ else {
1405
+ const { source: _source, ...rest } = relation;
1406
+ residual.push(rest);
1407
+ }
1408
+ continue;
1409
+ }
1410
+ if (relation.predicate === PRED_IMPLEMENTED_BY_MECHANISM ||
1411
+ relation.predicate === PRED_REALIZED_BY_PRACTICE) {
1412
+ const sliceAnchor = sliceEdgeBySubject.get(relation.subject_id);
1413
+ if (sliceAnchor !== undefined) {
1414
+ sliceImplementationAnchors.add(sliceAnchor);
1415
+ viaLenses += 1;
1416
+ }
1417
+ else if (entitySliceById.has(relation.subject_id)) {
1418
+ // Activated objective without a belongsToSlice edge (data gap).
1419
+ objectiveRealizationAnchors.add(relation.subject_id);
1420
+ viaLenses += 1;
1421
+ }
1422
+ else if ((relation.predicate === PRED_IMPLEMENTED_BY_MECHANISM &&
1423
+ entityTypeById.get(relation.object_id) === "Mechanism") ||
1424
+ (relation.predicate === PRED_REALIZED_BY_PRACTICE &&
1425
+ entityTypeById.get(relation.object_id) === "Practice")) {
1426
+ // Only the target is activated (cross-slice edge); the predicate is
1427
+ // recoverable from the target's entity_type in this payload.
1428
+ mechanismProvenanceAnchors.add(relation.object_id);
1429
+ viaLenses += 1;
1430
+ }
1431
+ else {
1432
+ const { source: _source, ...rest } = relation;
1433
+ residual.push(rest);
1434
+ }
1435
+ continue;
1436
+ }
1437
+ // Unknown predicate — never silently dropped.
1438
+ const { source: _source, ...rest } = relation;
1439
+ residual.push(rest);
1440
+ }
1441
+ const lenses = [
1442
+ ...activatedSliceIds
1443
+ .filter((sliceId) => sliceImplementationAnchors.has(sliceId))
1444
+ .map((anchor) => ({ lens: "slice_implementation", anchor })),
1445
+ ...[...objectiveRealizationAnchors]
1446
+ .sort()
1447
+ .map((anchor) => ({ lens: "objective_realization", anchor })),
1448
+ ...[...mechanismProvenanceAnchors]
1449
+ .sort()
1450
+ .map((anchor) => ({ lens: "mechanism_provenance", anchor }))
1451
+ ];
1452
+ const relationsRef = {
1453
+ tool: "trace_sbd_toe_graph",
1454
+ lenses,
1455
+ total_relations: relations.length,
1456
+ coverage: {
1457
+ via_lenses: viaLenses,
1458
+ implicit_in_entities: implicitInEntities,
1459
+ residual_inline: residual.length
1460
+ },
1461
+ note: RELATIONS_REF_NOTE
1462
+ };
1463
+ if (residual.length > 0)
1464
+ relationsRef.residual_relations = residual;
1465
+ return relationsRef;
1466
+ }
1467
+ function stripSource(items) {
1468
+ return items.map(({ source: _source, ...rest }) => rest);
1469
+ }
1470
+ /**
1471
+ * Static map published-file → payload path whose ids, in payload order, are
1472
+ * exactly the citation_map run for that file (the citation_map is BUILT by
1473
+ * iterating those very lists, in this order — see the core's citation block).
1474
+ * Paths use the mini-syntax documented in the resource's
1475
+ * `detail_encoding.citations` legend. No file outside this table is expected;
1476
+ * if one ever appears, the group falls back to explicit `ids` (lossless).
1477
+ */
1478
+ const CITATION_FILE_TO_PAYLOAD_PATH = {
1479
+ "data/publish/runtime/requirements.json": "activated_scope.requirements[].requirement_id",
1480
+ "data/publish/runtime/controls.json": "activated_scope.controls[].control_id",
1481
+ "data/publish/runtime/v1/slices.json": "activated_scope.slices[].slice_id",
1482
+ "data/publish/runtime/v1/control_objectives.json": "keys(g2_context.control_objectives[slice])",
1483
+ "data/publish/runtime/v1/mechanisms.json": "keys(g2_context.mechanisms[slice])",
1484
+ "data/publish/runtime/v1/practices.json": "keys(g2_context.practices[slice])",
1485
+ "data/publish/runtime/v1/artifacts.json": "keys(g2_context.artifacts[slice])",
1486
+ "data/publish/overlay/external_frameworks.json": "regulatory_overlay.frameworks[].framework_id",
1487
+ "data/publish/overlay/external_obligations.json": "activated_scope.regulatory_obligations[].obligation_id"
1488
+ };
1489
+ /**
1490
+ * Invert the classic `citation_map` (id → {source, source_data}) into
1491
+ * source-grouped `citations` (see {@link CitationsGroup}). Pure re-encoding:
1492
+ * the exact per-id source and source_data are reconstructible from the
1493
+ * ordered run-length `source_data` map — nothing is dropped. s3: ids already
1494
+ * present verbatim in a payload section are referenced via `ids_from` instead
1495
+ * of repeated; a group keeps explicit `ids` only if one of its files has no
1496
+ * payload-path mapping (never expected for the published bundle).
1497
+ */
1498
+ function invertCitationMap(citationMap) {
1499
+ const bySource = new Map();
1500
+ for (const [id, entry] of Object.entries(citationMap)) {
1501
+ let files = bySource.get(entry.source);
1502
+ if (!files) {
1503
+ files = new Map();
1504
+ bySource.set(entry.source, files);
1505
+ }
1506
+ let ids = files.get(entry.source_data);
1507
+ if (!ids) {
1508
+ ids = [];
1509
+ files.set(entry.source_data, ids);
1510
+ }
1511
+ ids.push(id);
1512
+ }
1513
+ const citations = {};
1514
+ for (const [source, files] of bySource) {
1515
+ const source_data = {};
1516
+ const ids = [];
1517
+ const idsFrom = [];
1518
+ let allFilesMapped = true;
1519
+ for (const [file, fileIds] of files) {
1520
+ source_data[file] = fileIds.length;
1521
+ ids.push(...fileIds);
1522
+ const path = CITATION_FILE_TO_PAYLOAD_PATH[file];
1523
+ if (path === undefined)
1524
+ allFilesMapped = false;
1525
+ else
1526
+ idsFrom.push(path);
1527
+ }
1528
+ citations[source] = allFilesMapped
1529
+ ? { source_data, ids_from: idsFrom }
1530
+ : { source_data, ids };
1531
+ }
1532
+ return citations;
1533
+ }
1534
+ /**
1535
+ * Group the flat `manual_grounding` entries by the tuple that repeats
1536
+ * verbatim: (rastreabilidade_role, manual_chapter, manual_file,
1537
+ * manual_commit_sha). Names are elided ONLY when recoverable from the
1538
+ * `g2_context` entity lists in the same payload (they come from the same
1539
+ * rastreabilidade source); any non-recoverable name is kept explicitly in
1540
+ * `v1_entity_names`, so no information is lost.
1541
+ */
1542
+ function groupManualGrounding(result) {
1543
+ const g2Names = new Map();
1544
+ for (const list of [
1545
+ result.g2_context.control_objectives,
1546
+ result.g2_context.mechanisms,
1547
+ result.g2_context.practices,
1548
+ result.g2_context.artifacts
1549
+ ]) {
1550
+ for (const entity of list)
1551
+ g2Names.set(entity.entity_id, entity.name);
1552
+ }
1553
+ // Object sentinel: serializes unlike any string/null value, so an absent
1554
+ // field can never collide with a real published value in the group key.
1555
+ const ABSENT = { absent: true };
1556
+ const groups = new Map();
1557
+ const ungrouped = [];
1558
+ for (const entry of result.manual_grounding) {
1559
+ if (!entry.v1_entity_id) {
1560
+ // Lossless guard — the loader keys entries by v1_entity_id, so this is
1561
+ // not expected; if it ever happens the entry survives verbatim.
1562
+ const { source: _source, ...rest } = entry;
1563
+ ungrouped.push(rest);
1564
+ continue;
1565
+ }
1566
+ const hasChapter = "manual_chapter" in entry;
1567
+ const hasFile = "manual_file" in entry;
1568
+ const hasSha = entry.manual_commit_sha !== undefined;
1569
+ const key = JSON.stringify([
1570
+ entry.rastreabilidade_role,
1571
+ hasChapter ? entry.manual_chapter ?? null : ABSENT,
1572
+ hasFile ? entry.manual_file ?? null : ABSENT,
1573
+ hasSha ? entry.manual_commit_sha : ABSENT
1574
+ ]);
1575
+ let group = groups.get(key);
1576
+ if (!group) {
1577
+ group = {
1578
+ rastreabilidade_role: entry.rastreabilidade_role,
1579
+ ...(hasChapter ? { manual_chapter: entry.manual_chapter ?? null } : {}),
1580
+ ...(hasFile ? { manual_file: entry.manual_file ?? null } : {}),
1581
+ ...(hasSha ? { manual_commit_sha: entry.manual_commit_sha } : {}),
1582
+ v1_entity_ids: []
1583
+ };
1584
+ groups.set(key, group);
1585
+ }
1586
+ group.v1_entity_ids.push(entry.v1_entity_id);
1587
+ if (entry.v1_entity_name &&
1588
+ g2Names.get(entry.v1_entity_id) !== entry.v1_entity_name) {
1589
+ (group.v1_entity_names ??= {})[entry.v1_entity_id] = entry.v1_entity_name;
1590
+ }
1591
+ }
1592
+ const grouped = {
1593
+ total_entries: result.manual_grounding.length,
1594
+ groups: [...groups.values()]
1595
+ };
1596
+ if (ungrouped.length > 0)
1597
+ grouped.ungrouped = ungrouped;
1598
+ return grouped;
1599
+ }
1600
+ // s3b: kept URI-free on purpose (no-leak discipline, same as RELATIONS_REF_NOTE).
1601
+ const GROUNDING_GROUPS_REF_NOTE = "Per-group v1_entity_ids elided at detail=minimal (each group carries its " +
1602
+ "exact `entries` count). The grounding id set is already in this payload — " +
1603
+ "every grounding id is an entity-id key of the g2_context maps. Re-call " +
1604
+ "with the same input at detail='standard' for the per-group id lists " +
1605
+ "(groups align 1:1, same order).";
1606
+ /**
1607
+ * v2 token diet, s3b (revised ADENDA 2026-07-05) — minimal-form
1608
+ * `manual_grounding`, derived from the detail="standard" grouping (so the 1:1
1609
+ * group alignment holds by construction). Serialization-only cut, never
1610
+ * silent:
1611
+ * - per-group `v1_entity_ids` → exact `entries` count (Σ == total_entries);
1612
+ * - `manual_commit_sha` hoisted to the top level iff EVERY group carries
1613
+ * the same sha (expected always: one published manual commit); otherwise
1614
+ * each group keeps its own sha inline (lossless guard);
1615
+ * - `v1_entity_names` (never expected) and `ungrouped` (never expected)
1616
+ * survive verbatim — no name or entry can be lost;
1617
+ * - `groups_ref` is the executable reference to the full grouping.
1618
+ * Invariant-3 note: grounding ids never feed `citations`/`ids_from`, and the
1619
+ * id set stays reconstructible from this same payload's g2_context entity
1620
+ * maps without any extra call.
1621
+ */
1622
+ function buildMinimalGrounding(grouped) {
1623
+ const shas = grouped.groups.map((group) => group.manual_commit_sha);
1624
+ const hoistedSha = grouped.groups.length > 0 &&
1625
+ shas[0] !== undefined &&
1626
+ shas.every((sha) => sha === shas[0])
1627
+ ? shas[0]
1628
+ : undefined;
1629
+ const minimal = {
1630
+ total_entries: grouped.total_entries,
1631
+ ...(hoistedSha !== undefined ? { manual_commit_sha: hoistedSha } : {}),
1632
+ groups: grouped.groups.map((group) => ({
1633
+ rastreabilidade_role: group.rastreabilidade_role,
1634
+ ...("manual_chapter" in group ? { manual_chapter: group.manual_chapter } : {}),
1635
+ ...("manual_file" in group ? { manual_file: group.manual_file } : {}),
1636
+ ...(hoistedSha === undefined && group.manual_commit_sha !== undefined
1637
+ ? { manual_commit_sha: group.manual_commit_sha }
1638
+ : {}),
1639
+ entries: group.v1_entity_ids.length,
1640
+ ...(group.v1_entity_names ? { v1_entity_names: group.v1_entity_names } : {})
1641
+ })),
1642
+ groups_ref: {
1643
+ tool: "prepare_sbd_toe_codegen_context",
1644
+ with: { detail: "standard" },
1645
+ note: GROUNDING_GROUPS_REF_NOTE
1646
+ }
1647
+ };
1648
+ if (grouped.ungrouped)
1649
+ minimal.ungrouped = grouped.ungrouped;
1650
+ return minimal;
1651
+ }
1652
+ // s3c notes — all NEW constants (the s1–s4 note texts are byte-frozen by the
1653
+ // standard/minimal golden snapshots and are never edited). Kept URI-free
1654
+ // (no-leak discipline, same as RELATIONS_REF_NOTE).
1655
+ const GROUNDING_GROUPS_REF_NOTE_ULTRATHIN = "Grounding group list elided at detail=ultrathin (total_entries is the " +
1656
+ "exact flat entry count; manual_commit_sha is the shared published manual " +
1657
+ "commit). The grounding id set is already in this payload — every " +
1658
+ "grounding id is an entity-id key of the g2_context maps. Re-call with the " +
1659
+ "same input at detail='standard' for the full (role, chapter, file) groups " +
1660
+ "with per-group v1_entity_ids; detail='minimal' returns the groups with " +
1661
+ "per-group counts.";
1662
+ const DESCRIPTIONS_REF_NOTE = "Published `description` fields (the 'how') elided at detail=ultrathin — " +
1663
+ "the requirement/control lists themselves are COMPLETE (same ids, same " +
1664
+ "order, name always present). Re-call with the same input at " +
1665
+ "detail='minimal' for the same complete scope WITH the verbatim published " +
1666
+ "descriptions (requirements + direct controls).";
1667
+ const EVIDENCE_PATTERNS_REST_NOTE_ULTRATHIN = "No evidence pattern goes inline at detail=ultrathin (returned=0; " +
1668
+ "capped=total). Re-call with the same input at detail='minimal' for the " +
1669
+ "deterministic top-5 (cheapest level that returns patterns inline); " +
1670
+ "detail='standard' returns the top-10 and detail='full' the classic " +
1671
+ "top-25 (each list is a deterministic prefix of the next).";
1672
+ const ACTIVATION_TRACE_REF_NOTE_ULTRATHIN = "activation_trace elided at detail=ultrathin — re-call with debug=true to " +
1673
+ "include it (always inline at detail=full).";
1674
+ const V1_DIAGNOSTICS_REF_NOTE = "v1_consistency_mismatches/v1_manifest_warnings texts elided at " +
1675
+ "detail=ultrathin (exact counts inline). Re-call with the same input at " +
1676
+ "detail='minimal' for the full text arrays in completeness_report.";
1677
+ /**
1678
+ * v2 token diet, s3c — ultrathin-form `manual_grounding`, derived from the
1679
+ * s3b minimal form (so `total_entries`, the hoisted sha and the ungrouped
1680
+ * guard are byte-identical by construction). Serialization-only cut, never
1681
+ * silent: the (role, chapter, file) group list with per-group counts is
1682
+ * elided; `total_entries` keeps the exact flat count and `groups_ref` is the
1683
+ * executable reference to the full grouping (same input, detail="standard").
1684
+ * Lossless guards (expected never): if the sha was not hoistable or any group
1685
+ * carries `v1_entity_names`, the minimal `groups` list survives inline.
1686
+ */
1687
+ function buildUltrathinGrounding(minimal) {
1688
+ const mustKeepGroups = minimal.manual_commit_sha === undefined ||
1689
+ minimal.groups.some((group) => group.v1_entity_names !== undefined || group.manual_commit_sha !== undefined);
1690
+ const ultrathin = {
1691
+ total_entries: minimal.total_entries,
1692
+ ...(minimal.manual_commit_sha !== undefined
1693
+ ? { manual_commit_sha: minimal.manual_commit_sha }
1694
+ : {}),
1695
+ ...(mustKeepGroups && minimal.groups.length > 0 ? { groups: minimal.groups } : {}),
1696
+ groups_ref: {
1697
+ tool: "prepare_sbd_toe_codegen_context",
1698
+ with: { detail: "standard" },
1699
+ note: GROUNDING_GROUPS_REF_NOTE_ULTRATHIN
1700
+ }
1701
+ };
1702
+ if (minimal.ungrouped)
1703
+ ultrathin.ungrouped = minimal.ungrouped;
1704
+ return ultrathin;
1705
+ }
1706
+ /**
1707
+ * v2 token diet, s3c — trim the completeness report for `detail: "ultrathin"`.
1708
+ * Every COUNT survives verbatim (never-silent backbone: expected/returned per
1709
+ * entity kind, m_recall, named/unnamed, evidence total/returned/capped/cap and
1710
+ * the rest-ref); only the two diagnostic TEXT arrays are re-encoded as exact
1711
+ * counts + the executable `v1_diagnostics_ref` (see
1712
+ * {@link UltrathinCompletenessReport} for what is cut and why).
1713
+ */
1714
+ function trimCompletenessForUltrathin(report) {
1715
+ const { v1_consistency_mismatches, v1_manifest_warnings, ...kept } = report;
1716
+ return {
1717
+ ...kept,
1718
+ v1_consistency_mismatches_count: v1_consistency_mismatches.length,
1719
+ v1_manifest_warnings_count: v1_manifest_warnings.length,
1720
+ ...(v1_consistency_mismatches.length + v1_manifest_warnings.length > 0
1721
+ ? {
1722
+ v1_diagnostics_ref: {
1723
+ tool: "prepare_sbd_toe_codegen_context",
1724
+ with: { detail: "minimal" },
1725
+ note: V1_DIAGNOSTICS_REF_NOTE
1726
+ }
1727
+ }
1728
+ : {})
1729
+ };
1730
+ }
1731
+ /** Slice-grouped, name-only entity encoding (see {@link SliceGroupedEntityNames}). */
1732
+ function groupEntitiesBySlice(entities) {
1733
+ const grouped = {};
1734
+ for (const entity of entities) {
1735
+ (grouped[entity.slice_id] ??= {})[entity.entity_id] = entity.name ?? null;
1736
+ }
1737
+ return grouped;
1738
+ }
1739
+ /** `category` is derivable iff it equals the requirement_id prefix before the
1740
+ * first "-" (bundle-wide invariant, guarded per item). */
1741
+ function categoryIsDerivable(requirementId, category) {
1742
+ const dash = requirementId.indexOf("-");
1743
+ return dash > 0 && requirementId.slice(0, dash) === category;
1744
+ }
1745
+ /** Dieted requirements: `source`/derivable `category` elided, verbatim
1746
+ * published `description` appended (s3 — the "how"). s3c: at
1747
+ * `detail: "ultrathin"` (`includeDescriptions: false`) the description is
1748
+ * elided too — each item is exactly {requirement_id, name, type} (plus the
1749
+ * unchanged `category` lossless guard) with the executable
1750
+ * `activated_scope.descriptions_ref` pointing at detail="minimal". */
1751
+ function dietRequirements(requirements, includeDescriptions) {
1752
+ const descriptionById = new Map();
1753
+ if (includeDescriptions) {
1754
+ for (const requirement of getOntologyData().requirements) {
1755
+ if (requirement.description) {
1756
+ descriptionById.set(requirement.requirement_id, requirement.description);
1757
+ }
1758
+ }
1759
+ }
1760
+ return requirements.map((item) => {
1761
+ const { source: _source, category, ...rest } = item;
1762
+ const description = descriptionById.get(item.requirement_id);
1763
+ return {
1764
+ ...rest,
1765
+ ...(categoryIsDerivable(item.requirement_id, category) ? {} : { category }),
1766
+ ...(description ? { description } : {})
1767
+ };
1768
+ });
1769
+ }
1770
+ /** Dieted controls: `source` elided; `direct` controls carry the verbatim
1771
+ * published `description` (s3 — the "how"). s3c: at `detail: "ultrathin"`
1772
+ * (`includeDescriptions: false`) the description is elided — each item is
1773
+ * exactly {control_id, name, domain, control_type, confidence} (every
1774
+ * non-description published field: small, useful, and required to keep the
1775
+ * item more than id-only). */
1776
+ function dietControls(controls, includeDescriptions) {
1777
+ const descriptionById = new Map();
1778
+ if (includeDescriptions) {
1779
+ for (const control of getOntologyData().controls) {
1780
+ if (control.description)
1781
+ descriptionById.set(control.control_id, control.description);
1782
+ }
1783
+ }
1784
+ return controls.map((item) => {
1785
+ const { source: _source, ...rest } = item;
1786
+ const description = item.confidence === "direct" ? descriptionById.get(item.control_id) : undefined;
1787
+ return { ...rest, ...(description ? { description } : {}) };
1788
+ });
1789
+ }
1790
+ /**
1791
+ * v2 token diet, s1+s2+s3 — dieted encoding for `detail: "standard" |
1792
+ * "minimal"`. Pure post-processing over the byte-identical full result. The
1793
+ * citable ID set is EXACTLY the full one (invariant 3; the omitted evidence
1794
+ * patterns carry no citation_map ids — verified by tests). Every cut is
1795
+ * either a lossless derivable-field re-encoding documented in the
1796
+ * codegen-instructions resource legend, or an explicit bound with
1797
+ * total/returned/omitted counts plus an executable reference to the rest
1798
+ * (invariant 2 — never silent):
1799
+ * - s1: inverted citations, grouped grounding, per-item `source` legend;
1800
+ * - s2: relations on-demand via `relations_ref` (include_relations restores);
1801
+ * - s3: evidence cap 25→10 (deterministic prefix; counts + rest-ref in
1802
+ * completeness_report), instructions/template → MCP resource, trace only
1803
+ * with debug, verbatim published `description` on requirements + direct
1804
+ * controls, and derivable-field dedup (category, entity_type/slice_family
1805
+ * via slice-grouped entity maps, relevance_score, citation id repeats);
1806
+ * - s3b (revised ADENDA 2026-07-05 — no top-N): `minimal` keeps the
1807
+ * activated scope byte-identical to `standard` and diverges ONLY on
1808
+ * traceability serialization — evidence cap 10→5 (same mechanism) and
1809
+ * `manual_grounding` in the minimal form (counts + hoisted sha +
1810
+ * executable groups_ref);
1811
+ * - s3c (`ultrathin`, operator reactivation 2026-07-05): same complete
1812
+ * activated set, but descriptions elided (descriptions_ref →
1813
+ * detail="minimal"), evidence cap 5→0 (rest-ref → detail="minimal"),
1814
+ * grounding aggregate-only and completeness diagnostics as counts + ref.
1815
+ */
1816
+ function applyStructuralDiet(result, detail, includeRelations) {
1817
+ // s3/s3b/s3c evidence cap (standard 10, minimal 5, ultrathin 0):
1818
+ // deterministic prefix of the classic (already sorted: relevance_score desc,
1819
+ // id asc) list; each dieted list is by construction a prefix of the next
1820
+ // level's. Never-silent counts below; the rest-ref points to detail="full"
1821
+ // (classic top-25) at standard/minimal and to detail="minimal" (the
1822
+ // CHEAPEST level that returns patterns inline) at ultrathin.
1823
+ const ultrathin = detail === "ultrathin";
1824
+ const evidenceCap = ultrathin
1825
+ ? ULTRATHIN_EVIDENCE_PATTERN_CAP
1826
+ : detail === "minimal"
1827
+ ? MINIMAL_EVIDENCE_PATTERN_CAP
1828
+ : STANDARD_EVIDENCE_PATTERN_CAP;
1829
+ const evidenceKept = result.g2_context.evidence_patterns.slice(0, evidenceCap);
1830
+ const evidenceTotal = result.completeness_report.evidence_patterns_total;
1831
+ const evidenceCapped = evidenceTotal - evidenceKept.length;
1832
+ const completeness = {
1833
+ ...result.completeness_report,
1834
+ evidence_patterns_returned: evidenceKept.length,
1835
+ evidence_patterns_capped: evidenceCapped,
1836
+ evidence_pattern_cap: evidenceCap,
1837
+ ...(evidenceCapped > 0
1838
+ ? {
1839
+ evidence_patterns_rest: (ultrathin
1840
+ ? {
1841
+ tool: "prepare_sbd_toe_codegen_context",
1842
+ with: { detail: "minimal" },
1843
+ note: EVIDENCE_PATTERNS_REST_NOTE_ULTRATHIN
1844
+ }
1845
+ : {
1846
+ tool: "prepare_sbd_toe_codegen_context",
1847
+ with: { detail: "full" },
1848
+ note: "Re-call with the same input at detail='full' for the classic inline " +
1849
+ `top-${EVIDENCE_PATTERN_CAP} evidence_patterns (this list is its ` +
1850
+ "deterministic prefix); with debug=true, ids beyond the classic cap " +
1851
+ "are listed in debug.rejected_candidates."
1852
+ })
1853
+ }
1854
+ : {})
1855
+ };
1856
+ // s3 instructions → resource: conditions computed from the SAME resolved
1857
+ // inputs the core used, so resource + active_conditions reconstruct the
1858
+ // inline full content byte-identically.
1859
+ const echoedRisk = result.input_echo.risk_level;
1860
+ const riskLevel = echoedRisk === "L1" || echoedRisk === "L2" || echoedRisk === "L3"
1861
+ ? echoedRisk
1862
+ : undefined;
1863
+ const instructionsRef = {
1864
+ resource: codegenInstructionsResourceUri(result.mode),
1865
+ active_conditions: activeInstructionConditions({
1866
+ hasOverlay: result.activated_scope.regulatory_obligations.length > 0,
1867
+ riskLevel,
1868
+ citationMapEmpty: Object.keys(result.citation_map).length === 0
1869
+ }),
1870
+ note: "Read this MCP resource for llm_codegen_instructions (slots filtered by " +
1871
+ "active_conditions) and security_rationale_template (task = " +
1872
+ "input_echo.task trimmed) — byte-identical to the detail=full inline " +
1873
+ "content — plus the detail_encoding legend for this payload."
1874
+ };
1875
+ const dieted = {
1876
+ status: result.status,
1877
+ mode: result.mode,
1878
+ // Echo the requested detail (and the include_relations escape hatch, when
1879
+ // active) for audit; the FULL result never echoes either (explicit "full"
1880
+ // must stay byte-identical to the omitted form).
1881
+ input_echo: {
1882
+ ...result.input_echo,
1883
+ detail,
1884
+ ...(includeRelations ? { include_relations: true } : {})
1885
+ },
1886
+ // s3: activation_trace only with debug=true; never-silent counter otherwise
1887
+ // (s3c: ultrathin carries its own note — the standard/minimal text is
1888
+ // byte-frozen by the golden snapshots).
1889
+ ...(result.debug
1890
+ ? { activation_trace: result.activation_trace }
1891
+ : {
1892
+ activation_trace_ref: {
1893
+ entries: result.activation_trace.length,
1894
+ note: ultrathin
1895
+ ? ACTIVATION_TRACE_REF_NOTE_ULTRATHIN
1896
+ : "activation_trace elided at detail=standard/minimal — re-call with " +
1897
+ "debug=true to include it (always inline at detail=full)."
1898
+ }
1899
+ }),
1900
+ provenance_legend: ultrathin ? PROVENANCE_LEGEND_ULTRATHIN : PROVENANCE_LEGEND,
1901
+ // s3c: ultrathin elides the published descriptions (executable
1902
+ // descriptions_ref → detail="minimal"); the lists stay COMPLETE.
1903
+ activated_scope: {
1904
+ requirements: dietRequirements(result.activated_scope.requirements, !ultrathin),
1905
+ controls: dietControls(result.activated_scope.controls, !ultrathin),
1906
+ slices: stripSource(result.activated_scope.slices),
1907
+ regulatory_obligations: stripSource(result.activated_scope.regulatory_obligations),
1908
+ ...(ultrathin
1909
+ ? {
1910
+ descriptions_ref: {
1911
+ tool: "prepare_sbd_toe_codegen_context",
1912
+ with: { detail: "minimal" },
1913
+ note: DESCRIPTIONS_REF_NOTE
1914
+ }
1915
+ }
1916
+ : {})
1917
+ },
1918
+ g2_context: {
1919
+ control_objectives: groupEntitiesBySlice(result.g2_context.control_objectives),
1920
+ mechanisms: groupEntitiesBySlice(result.g2_context.mechanisms),
1921
+ practices: groupEntitiesBySlice(result.g2_context.practices),
1922
+ artifacts: groupEntitiesBySlice(result.g2_context.artifacts),
1923
+ ...(includeRelations
1924
+ ? { relations: stripSource(result.g2_context.relations) }
1925
+ : { relations_ref: buildRelationsRef(result) }),
1926
+ evidence_patterns: evidenceKept.map(({ source: _source, relevance_score: _score, ...rest }) => rest)
1927
+ },
1928
+ // s3b: minimal serves the count+provenance form (executable groups_ref);
1929
+ // standard keeps the full grouping; s3c: ultrathin serves the aggregate
1930
+ // form only (total + hoisted sha + groups_ref, group list elided).
1931
+ manual_grounding: ultrathin
1932
+ ? buildUltrathinGrounding(buildMinimalGrounding(groupManualGrounding(result)))
1933
+ : detail === "minimal"
1934
+ ? buildMinimalGrounding(groupManualGrounding(result))
1935
+ : groupManualGrounding(result),
1936
+ regulatory_overlay: {
1937
+ frameworks: stripSource(result.regulatory_overlay.frameworks),
1938
+ obligations: stripSource(result.regulatory_overlay.obligations),
1939
+ mappings: stripSource(result.regulatory_overlay.mappings),
1940
+ playbooks: stripSource(result.regulatory_overlay.playbooks)
1941
+ },
1942
+ citations: invertCitationMap(result.citation_map),
1943
+ // s3c: ultrathin trims the diagnostic text arrays to exact counts + ref.
1944
+ completeness_report: ultrathin
1945
+ ? trimCompletenessForUltrathin(completeness)
1946
+ : completeness,
1947
+ codegen_instructions_ref: instructionsRef,
1948
+ // s4: identical re-call is deterministic — point the client back at the
1949
+ // context it already holds (full stays byte-identical: no hint there).
1950
+ repeat_call_hint: REPEAT_CALL_HINT,
1951
+ provenance: result.provenance
1952
+ };
1953
+ if (result.debug)
1954
+ dieted.debug = result.debug;
1955
+ return dieted;
1956
+ }
979
1957
  export function handlePrepareCodegenContext(raw) {
980
- // RF-H: append the advisory band (status-aware, pure) around the deterministic result.
1958
+ // v2 token diet (s1/s2): `detail` and `include_relations` select the
1959
+ // response ENCODING only — they are validated up-front and never influence
1960
+ // activation/resolution.
1961
+ const detail = parseDetail(raw);
1962
+ const includeRelations = parseIncludeRelations(raw);
981
1963
  const result = prepareCodegenContextCore(raw);
982
- return { ...result, next: prepareCodegenAffordances(result.status) };
1964
+ const shaped = detail !== "full" && result.status === "ready_for_codegen"
1965
+ ? applyStructuralDiet(result, detail, includeRelations)
1966
+ : result;
1967
+ // RF-H: append the advisory band (status-aware, pure) around the deterministic result.
1968
+ return { ...shaped, next: prepareCodegenAffordances(result.status) };
983
1969
  }
984
1970
  function prepareCodegenContextCore(raw) {
985
1971
  const input = normalizeInput(raw);
@@ -1262,31 +2248,7 @@ function prepareCodegenContextCore(raw) {
1262
2248
  hasOverlay: overlayResolution.activatedObligations.length > 0,
1263
2249
  riskLevel: input.risk_level
1264
2250
  });
1265
- const security_rationale_template = {
1266
- task: input.taskTrimmed,
1267
- decisions: [
1268
- {
1269
- decision: "<fill: what design choice was made>",
1270
- rationale: "<fill: why, citing IDs from citation_map>",
1271
- cited_ids: ["<requirement_id|control_id|slice_id|obligation_id>"]
1272
- }
1273
- ],
1274
- validations: [
1275
- {
1276
- surface: "<fill: code path being validated>",
1277
- rule: "<fill: validation rule>",
1278
- rejection_behaviour: "<fill: how invalid input is rejected>"
1279
- }
1280
- ],
1281
- expected_evidence: [
1282
- {
1283
- artefact: "<fill: test, log, doc, sbom, scan, attestation, ...>",
1284
- location: "<fill: where to find it>",
1285
- verifies: "<fill: which control/requirement id>"
1286
- }
1287
- ],
1288
- residual_risk: "<fill: anything NOT addressed by this change>"
1289
- };
2251
+ const security_rationale_template = buildSecurityRationaleTemplate(input.taskTrimmed);
1290
2252
  const result = {
1291
2253
  status: "ready_for_codegen",
1292
2254
  mode: input.mode,