@c4a/context-cli 0.5.39-beta.1 → 0.5.39-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -28425,8 +28425,8 @@ function stripEvidenceUrls(text5) {
28425
28425
  }
28426
28426
  var URL_RE, TRAILING_URL_PUNCTUATION_RE, TRACKING_QUERY_PARAM_RE;
28427
28427
  var init_evidenceUrls = __esm(() => {
28428
- URL_RE = /https?:\/\/[^\s)\]}>"')】》」』,。;:!?]+/giu;
28429
- TRAILING_URL_PUNCTUATION_RE = /[.,;:!?)\]\}>"',。;:!?)】》」』]+$/u;
28428
+ URL_RE = /https?:\/\/[^\s`*)\]}>"')】》」』,。;:!?]+/giu;
28429
+ TRAILING_URL_PUNCTUATION_RE = /[`*.,;:!?)\]\}>"',。;:!?)】》」』]+$/u;
28430
28430
  TRACKING_QUERY_PARAM_RE = /^(?:utm_|fbclid$|gclid$|mc_cid$|mc_eid$)/iu;
28431
28431
  });
28432
28432
 
@@ -52772,7 +52772,7 @@ function rejectLegacy(path13, message) {
52772
52772
  }]
52773
52773
  });
52774
52774
  }
52775
- function stringValue(value) {
52775
+ function stringValue2(value) {
52776
52776
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
52777
52777
  }
52778
52778
  function stringArray2(value) {
@@ -54856,6 +54856,7 @@ var init_alignWorkflowSchemas = __esm(() => {
54856
54856
  "CLI compiles section_groups[] into canonical sections[] and generates section_id values.",
54857
54857
  "nodes[].planned_sections defaults to the distinct section_groups[].section_kind values for that owner. Nodes with no section_groups must explicitly set planned_sections: [] to express no-write intent.",
54858
54858
  "section_groups[] only accepts block_ids[]. Do not use source_window_ids, ranges, headings, or heading globs for Section evidence selection.",
54859
+ "section_groups[].block_ids may express one semantic grouping, but finalized ownership splits non-contiguous citation-eligible runs into draft-ready section plans. During compile, keep those emitted draft_action_templates separate unless one Section truly consumes every intervening citation-eligible block.",
54859
54860
  "Every owned/shared citation evidence block selected by ownership_groups[] must appear in some section_groups[].block_ids, unless it is explicitly reclassified as context_only or ignored.",
54860
54861
  "ownership_groups[].scope must be exactly one of: {source_id}, {source_id, structural_role}, or {block_ids}. Do not add except clauses or arbitrary filter expressions.",
54861
54862
  "Ownership precedence is block_ids > source_id + structural_role > source_id; same specificity uses later group; explicit block_ownership[] patches override all groups.",
@@ -55009,7 +55010,8 @@ var init_alignWorkflowSchemas = __esm(() => {
55009
55010
  ...TERM_ENTITY_NOTES,
55010
55011
  "Use align-segments.generation_policy when choosing node.title, node.summary, rationale prose, and planned Section wording.",
55011
55012
  "nodes[].contains_parent is the only hierarchy field; edges[] only accepts depends_on.",
55012
- "domain nodes need domain_gate; unresolved or weak domain gates are downgraded to entity.",
55013
+ "domain nodes need domain_gate with resolvable child_refs; invalid domain gates block validation instead of being auto-downgraded to entity. If the evidence is not a grouping scope, submit entity with agent-chosen tags.",
55014
+ "action nodes need action_probe and structured action_gate.inference_sources; invalid action gates block validation instead of being auto-downgraded to entity. If the evidence is not a repeatable process, submit entity or write the process wording as a Section under its owner.",
55013
55015
  "When align-segments.incremental.mode is incremental, finalize preserves previous finalized ownership for unscanned sources. The current decision should describe only the scanned evidence while referencing previous active Nodes when needed.",
55014
55016
  "In incremental mode, absence of an old Node or edge is not a deletion signal; use a full align, drop source, or explicit structure correction path for removals.",
55015
55017
  "Incremental finalize may reference previous active Nodes from nodes[].contains_parent, edges[].from/to, domain_gate.child_refs, and block_ownership owners/visible_to/primary_owner. Do not redeclare an old parent/domain just to attach new children.",
@@ -55166,7 +55168,7 @@ function isNavigationExternalReference(block) {
55166
55168
  return externalReferenceDisposition(block) === "navigation_reference";
55167
55169
  }
55168
55170
  function ownershipDefaultForBlock(raw, blockId, block) {
55169
- const role = stringValue(raw.ownership_role);
55171
+ const role = stringValue2(raw.ownership_role);
55170
55172
  if (role !== "owned" && role !== "shared") {
55171
55173
  return { ...raw, block_id: blockId };
55172
55174
  }
@@ -55176,14 +55178,14 @@ function ownershipDefaultForBlock(raw, blockId, block) {
55176
55178
  const visibleTo2 = uniqueStrings3([
55177
55179
  ...stringArray2(raw.visible_to),
55178
55180
  ...stringArray2(raw.owners),
55179
- ...stringValue(raw.primary_owner) !== undefined ? [stringValue(raw.primary_owner)] : []
55181
+ ...stringValue2(raw.primary_owner) !== undefined ? [stringValue2(raw.primary_owner)] : []
55180
55182
  ]);
55181
55183
  const next2 = {
55182
55184
  ...raw,
55183
55185
  block_id: blockId,
55184
55186
  ownership_role: structuralDefaultRole,
55185
55187
  visible_to: visibleTo2,
55186
- reason: stringValue(raw.reason) ?? `mechanical ${structuralRole} block does not need Section citation`,
55188
+ reason: stringValue2(raw.reason) ?? `mechanical ${structuralRole} block does not need Section citation`,
55187
55189
  provenance: "cli_demote"
55188
55190
  };
55189
55191
  Reflect.deleteProperty(next2, "owners");
@@ -55195,14 +55197,14 @@ function ownershipDefaultForBlock(raw, blockId, block) {
55195
55197
  const visibleTo = uniqueStrings3([
55196
55198
  ...stringArray2(raw.visible_to),
55197
55199
  ...stringArray2(raw.owners),
55198
- ...stringValue(raw.primary_owner) !== undefined ? [stringValue(raw.primary_owner)] : []
55200
+ ...stringValue2(raw.primary_owner) !== undefined ? [stringValue2(raw.primary_owner)] : []
55199
55201
  ]);
55200
55202
  const next = {
55201
55203
  ...raw,
55202
55204
  block_id: blockId,
55203
55205
  ownership_role: "context_only",
55204
55206
  visible_to: visibleTo,
55205
- reason: stringValue(raw.reason) ?? "navigation/reference-only block kept as context_only",
55207
+ reason: stringValue2(raw.reason) ?? "navigation/reference-only block kept as context_only",
55206
55208
  provenance: "cli_demote"
55207
55209
  };
55208
55210
  Reflect.deleteProperty(next, "owners");
@@ -55239,7 +55241,7 @@ function expandOwnershipDefaults(input) {
55239
55241
  blocks.push(blockId);
55240
55242
  blocksBySource.set(sourceId, blocks);
55241
55243
  }
55242
- const explicitBlockIds = new Set(input.blockOwnership.filter(isRecord18).map((entry) => stringValue(entry.block_id)).filter((blockId) => blockId !== undefined));
55244
+ const explicitBlockIds = new Set(input.blockOwnership.filter(isRecord18).map((entry) => stringValue2(entry.block_id)).filter((blockId) => blockId !== undefined));
55243
55245
  const issues = [];
55244
55246
  const defaultsBySource = new Set;
55245
55247
  const expanded = [];
@@ -55256,7 +55258,7 @@ function expandOwnershipDefaults(input) {
55256
55258
  });
55257
55259
  return;
55258
55260
  }
55259
- const sourceId = stringValue(raw.source_id);
55261
+ const sourceId = stringValue2(raw.source_id);
55260
55262
  if (sourceId === undefined) {
55261
55263
  issues.push({
55262
55264
  path: `block_ownership_defaults[${index2}].source_id`,
@@ -55327,8 +55329,8 @@ function normalizeOwnership(value, refs, slugs, coverableBlockIds, coverableBloc
55327
55329
  push2(`block_ownership[${index2}]`, "block ownership must be an object");
55328
55330
  return;
55329
55331
  }
55330
- const blockId = stringValue(raw.block_id);
55331
- const rawRole = stringValue(raw.ownership_role);
55332
+ const blockId = stringValue2(raw.block_id);
55333
+ const rawRole = stringValue2(raw.ownership_role);
55332
55334
  const role = rawRole !== undefined && ["owned", "shared", "context_only", "ignored", "unresolved"].includes(rawRole) ? rawRole : undefined;
55333
55335
  if (blockId === undefined) {
55334
55336
  push2(`block_ownership[${index2}].block_id`, "block_id is required", { availableBlockIds: coverableBlockIds });
@@ -55435,7 +55437,7 @@ ${BLOCK_OWNERSHIP_CANONICAL_SHAPES.unresolved}`
55435
55437
  });
55436
55438
  entryHasIssues = true;
55437
55439
  }
55438
- const rawPrimaryOwner = stringValue(raw.primary_owner);
55440
+ const rawPrimaryOwner = stringValue2(raw.primary_owner);
55439
55441
  const primaryOwner = rawPrimaryOwner === undefined ? undefined : tryResolve(rawPrimaryOwner, `block_ownership[${index2}].primary_owner`);
55440
55442
  if (role === "shared" && (owners.length < 2 || primaryOwner === undefined)) {
55441
55443
  push2(`block_ownership[${index2}].primary_owner`, "shared block must have at least two owners and primary_owner", {
@@ -55477,8 +55479,8 @@ ${BLOCK_OWNERSHIP_CANONICAL_SHAPES.unresolved}`
55477
55479
  });
55478
55480
  entryHasIssues = true;
55479
55481
  }
55480
- const reason = stringValue(raw.reason);
55481
- const provenance = stringValue(raw.provenance);
55482
+ const reason = stringValue2(raw.reason);
55483
+ const provenance = stringValue2(raw.provenance);
55482
55484
  if ((role === "shared" || role === "unresolved") && reason === undefined) {
55483
55485
  push2(`block_ownership[${index2}].reason`, `${role} block requires reason`, {
55484
55486
  reasonCode: "missing-ownership-reason",
@@ -55487,7 +55489,7 @@ ${BLOCK_OWNERSHIP_CANONICAL_SHAPES.unresolved}`
55487
55489
  });
55488
55490
  entryHasIssues = true;
55489
55491
  }
55490
- const questionId = stringValue(raw.question_id);
55492
+ const questionId = stringValue2(raw.question_id);
55491
55493
  if (role === "unresolved" && questionId === undefined) {
55492
55494
  push2(`block_ownership[${index2}].question_id`, "unresolved block requires question_id", {
55493
55495
  reasonCode: "missing-question-id",
@@ -55553,7 +55555,7 @@ var init_alignStructureOwnership = __esm(() => {
55553
55555
  });
55554
55556
 
55555
55557
  // src/workflow/alignBlockStructuralRole.ts
55556
- function stringValue2(value) {
55558
+ function stringValue3(value) {
55557
55559
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
55558
55560
  }
55559
55561
  function blockText(block) {
@@ -55612,7 +55614,7 @@ function isNavigationReferenceQuote(blockKind, lines) {
55612
55614
  return blockKind === "quote" && lines.length > 0 && lines.every((line) => isExternalReferenceLine(stripMarkdownQuotePrefix(line)));
55613
55615
  }
55614
55616
  function alignBlockStructuralRole(block) {
55615
- const blockKind = stringValue2(block.block_kind);
55617
+ const blockKind = stringValue3(block.block_kind);
55616
55618
  const text6 = blockText(block);
55617
55619
  if (text6 === undefined)
55618
55620
  return "content";
@@ -59330,6 +59332,7 @@ var init_compileDraftSourceRefs = __esm(() => {
59330
59332
  CONTIGUITY_SKIPPABLE_STRUCTURAL_ROLES = new Set([
59331
59333
  "embed_tag",
59332
59334
  "embedded_asset",
59335
+ "heading_only",
59333
59336
  "navigation_reference",
59334
59337
  "marker_quote"
59335
59338
  ]);
@@ -59808,6 +59811,42 @@ var init_compileDraftTemplateValidation = __esm(() => {
59808
59811
  init_compileTemplateDetection();
59809
59812
  });
59810
59813
 
59814
+ // src/workflow/markdownFormatSignals.ts
59815
+ function markdownListItemCount(value) {
59816
+ return [...value.matchAll(MARKDOWN_LIST_ITEM_RE)].length;
59817
+ }
59818
+ function markdownFormatSignals(value) {
59819
+ if (typeof value !== "string" || value.trim().length === 0) {
59820
+ return { format_sensitive: false };
59821
+ }
59822
+ const containsList = markdownListItemCount(value) >= 2;
59823
+ const containsTable = TABLE_SEPARATOR_RE.test(value);
59824
+ const containsFencedCode = FENCED_CODE_RE.test(value);
59825
+ return {
59826
+ format_sensitive: containsList || containsTable || containsFencedCode,
59827
+ ...containsList ? { contains_markdown_list: true } : {},
59828
+ ...containsTable ? { contains_markdown_table: true } : {},
59829
+ ...containsFencedCode ? { contains_fenced_code: true } : {}
59830
+ };
59831
+ }
59832
+ function collapsedMarkdownListLikely(input) {
59833
+ const rawListItems = markdownListItemCount(input.raw);
59834
+ if (rawListItems < 2)
59835
+ return false;
59836
+ const contentLineListItems = markdownListItemCount(input.content);
59837
+ if (contentLineListItems >= rawListItems)
59838
+ return false;
59839
+ const compact2 = input.content.replace(/\s+/g, " ").trim();
59840
+ const bulletFragments = compact2.match(/(?:^|\s)(?:[-*+]\s+|\d+[.)]\s+)\S/gu) ?? [];
59841
+ return bulletFragments.length >= 2;
59842
+ }
59843
+ var MARKDOWN_LIST_ITEM_RE, FENCED_CODE_RE, TABLE_SEPARATOR_RE;
59844
+ var init_markdownFormatSignals = __esm(() => {
59845
+ MARKDOWN_LIST_ITEM_RE = /^\s{0,6}(?:[-*+]\s+|\d+[.)]\s+)\S/mgu;
59846
+ FENCED_CODE_RE = /(?:^|\n)\s{0,6}(?:```|~~~)/u;
59847
+ TABLE_SEPARATOR_RE = /^\s*\|?(?:\s*:?-{3,}:?\s*\|)+\s*:?-{3,}:?\s*\|?\s*$/mu;
59848
+ });
59849
+
59811
59850
  // src/workflow/compileDraftWarningHints.ts
59812
59851
  function pushSummaryWarnings(input) {
59813
59852
  const content3 = input.content;
@@ -59832,6 +59871,19 @@ function pushSummaryWarnings(input) {
59832
59871
  }
59833
59872
  if (summary2 === undefined)
59834
59873
  return;
59874
+ if (PLACEHOLDER_SUMMARY_RE.test(summary2.trim())) {
59875
+ input.state.warnings.push({
59876
+ code: "compile-section-summary-placeholder",
59877
+ severity: "warning",
59878
+ message: `${input.label}.summary looks like a generated placeholder, not a reader/query summary.`,
59879
+ next_action: `Replace ${input.label}.summary with a meaningful short summary, or omit summary entirely. Empty summary is better than a template placeholder.`,
59880
+ path: `${input.label}.summary`,
59881
+ diagnostics: {
59882
+ submitted_summary: summary2,
59883
+ summary_policy: "summary is optional reader/query aid; omit it when no meaningful summary is available"
59884
+ }
59885
+ });
59886
+ }
59835
59887
  if (/\r|\n/u.test(summary2) || /```|~~~|^#{1,6}\s|^\s*[-*+]\s/mu.test(summary2)) {
59836
59888
  input.state.warnings.push({
59837
59889
  code: "compile-section-summary-format",
@@ -59962,18 +60014,56 @@ function collectDraftPlannedSectionWarnings(output, context, state) {
59962
60014
  });
59963
60015
  }
59964
60016
  }
60017
+ function pushMarkdownListFormatWarning(input) {
60018
+ if (input.content === undefined || input.sourceRefs.length === 0)
60019
+ return;
60020
+ const requested = new Set(input.sourceRefs);
60021
+ const affected = input.context.raw_snippets.filter((snippet) => typeof snippet.source_ref === "string" && requested.has(snippet.source_ref) && collapsedMarkdownListLikely({ raw: snippet.quote, content: input.content })).map((snippet) => ({
60022
+ source_ref: snippet.source_ref,
60023
+ block_id: snippet.block_id,
60024
+ line_range: snippet.line_range,
60025
+ raw_list_items: markdownListItemCount(snippet.quote)
60026
+ }));
60027
+ if (affected.length === 0)
60028
+ return;
60029
+ input.state.warnings.push({
60030
+ code: "compile-markdown-list-format-collapsed",
60031
+ severity: "warning",
60032
+ message: `${input.label}.content may have collapsed a cited multi-line Markdown list into one line.`,
60033
+ next_action: "If this was not an intentional prose summary, rerun the listed request_full_text command(s) and patch content to preserve the source list line breaks. The CLI will not rewrite content automatically.",
60034
+ path: `${input.label}.content`,
60035
+ diagnostics: {
60036
+ affected_source_refs: affected,
60037
+ request_full_text_commands: affected.map((item) => typeof item.block_id === "string" ? `context compile context ${input.context.node.slug} --request-full-text ${item.block_id} --view text --format json` : undefined).filter((command) => command !== undefined)
60038
+ }
60039
+ });
60040
+ }
60041
+ function collectDraftMarkdownFormatWarnings(output, context, state) {
60042
+ for (const [index2, action] of output.actions.entries()) {
60043
+ if (action.op === "add") {
60044
+ pushMarkdownListFormatWarning({ state, context, content: action.content, sourceRefs: sourceRefsForAction(action), label: `actions[${index2}]` });
60045
+ } else if (action.op === "update") {
60046
+ pushMarkdownListFormatWarning({ state, context, content: action.content, sourceRefs: sourceRefsForAction(action), label: `actions[${index2}]` });
60047
+ } else if (action.op === "supersede") {
60048
+ pushMarkdownListFormatWarning({ state, context, content: action.new.content, sourceRefs: sourceRefsForAction(action), label: `actions[${index2}].new` });
60049
+ }
60050
+ }
60051
+ }
59965
60052
  function collectCompileDraftWarnings(output, context) {
59966
60053
  const state = { warnings: [] };
59967
60054
  collectDraftSummaryWarnings(output, state);
59968
60055
  collectDraftLanguageWarnings(output, context, state);
59969
60056
  collectDraftPlannedSectionWarnings(output, context, state);
60057
+ collectDraftMarkdownFormatWarnings(output, context, state);
59970
60058
  return state.warnings;
59971
60059
  }
59972
- var SUMMARY_RECOMMENDED_CONTENT_CHARS = 500, SUMMARY_MAX_CHARS = 280, SUMMARY_HINT_SEVERITY = "info", CJK_RE3, ENGLISH_WORD_RE;
60060
+ var SUMMARY_RECOMMENDED_CONTENT_CHARS = 500, SUMMARY_MAX_CHARS = 280, SUMMARY_HINT_SEVERITY = "info", CJK_RE3, ENGLISH_WORD_RE, PLACEHOLDER_SUMMARY_RE;
59973
60061
  var init_compileDraftWarningHints = __esm(() => {
59974
60062
  init_generationPolicy();
60063
+ init_markdownFormatSignals();
59975
60064
  CJK_RE3 = /[\u3400-\u9fff]/gu;
59976
60065
  ENGLISH_WORD_RE = /\b[A-Za-z][A-Za-z-]{2,}\b/gu;
60066
+ PLACEHOLDER_SUMMARY_RE = /^(?:description|spec|warning|principle|decision|incident|example|changelog|comparison|faq)?\s*section\s+covering\s+\d+\s+evidence\s+blocks?\s*(?:\(s\))?\.?$/iu;
59977
60067
  });
59978
60068
 
59979
60069
  // src/workflow/compileDraftValidation.ts
@@ -60851,12 +60941,12 @@ var init_agentHintRegistry = __esm(() => {
60851
60941
  "align-candidate-ledger-invalid-op",
60852
60942
  "align-candidate-ops-input-invalid",
60853
60943
  "align-candidate-ops-segment-mismatch",
60854
- "align-action-downgraded-to-entity",
60944
+ "align-action-gate-invalid",
60855
60945
  "align-blocks-read-incomplete",
60856
60946
  "align-coarse-read-required",
60857
60947
  "align-coarse-read-segment-mismatch",
60858
60948
  "align-decision-ledger-invalid",
60859
- "align-domain-downgraded-to-entity",
60949
+ "align-domain-gate-invalid",
60860
60950
  "align-entity-tag-term-mixed-with-a-b",
60861
60951
  "align-finalize-node-without-citation-evidence",
60862
60952
  "align-finalize-unplanned-evidence-blocks",
@@ -60866,10 +60956,12 @@ var init_agentHintRegistry = __esm(() => {
60866
60956
  "align-ownership-default-cli-demoted",
60867
60957
  "align-pending-relation-refs",
60868
60958
  "align-read-plan-ready",
60959
+ "align-section-plan-crosses-headings",
60869
60960
  "align-section-plans-auto-split-contiguous-runs",
60870
60961
  "align-section-non-citable-blocks-ignored",
60871
60962
  "align-source-bundle-budget-fallback",
60872
60963
  "align-source-bundle-raw-c4a-sentinel-escaped",
60964
+ "align-source-bundle-use-read-plan",
60873
60965
  "align-finalize-patch-invalid",
60874
60966
  "align-ownership-patch-base-digest-stale",
60875
60967
  "align-ownership-patch-invalid",
@@ -60923,6 +61015,7 @@ var init_agentHintRegistry = __esm(() => {
60923
61015
  "compile-cycle-input-required",
60924
61016
  "compile-draft-invalid",
60925
61017
  "compile-draft-input-required",
61018
+ "compile-draft-patch-cycle-required",
60926
61019
  "compile-draft-patch-invalid",
60927
61020
  "compile-draft-patch-retired-field",
60928
61021
  "compile-draft-patch-ready",
@@ -60931,9 +61024,11 @@ var init_agentHintRegistry = __esm(() => {
60931
61024
  "compile-extract-normalized-match",
60932
61025
  "compile-lead-in-guidance",
60933
61026
  "compile-lead-in-skipped",
61027
+ "compile-markdown-list-format-collapsed",
60934
61028
  "compile-missing-refers-to-node",
60935
61029
  "compile-mode-required",
60936
61030
  "compile-modes-conflict",
61031
+ "compile-planned-section-fragment-review",
60937
61032
  "compile-node-type-guidance",
60938
61033
  "compile-node-no-citation-evidence",
60939
61034
  "compile-node-no-write-placeholder",
@@ -60950,6 +61045,7 @@ var init_agentHintRegistry = __esm(() => {
60950
61045
  "compile-section-kind-outside-plan",
60951
61046
  "compile-section-summary-format",
60952
61047
  "compile-section-summary-language",
61048
+ "compile-section-summary-placeholder",
60953
61049
  "compile-section-summary-recommended",
60954
61050
  "compile-section-summary-too-long",
60955
61051
  "compile-source-refs-draft-scaffold-available",
@@ -61007,6 +61103,8 @@ var init_agentHintRegistry = __esm(() => {
61007
61103
  "raw-snapshot-pending-compile",
61008
61104
  "ready-no-op-review",
61009
61105
  "ready-review-output",
61106
+ "prepare-candidates-index",
61107
+ "reconcile-apply-consumes-ready-review",
61010
61108
  "reconcile-prepare-draft-mode-invalid",
61011
61109
  "reconcile-validate-compile-mode-required",
61012
61110
  "reconcile-validate-decisions-required",
@@ -61115,17 +61213,17 @@ var init_agentHintRegistry = __esm(() => {
61115
61213
  command: "context schema align-structure-intent --view minimal --format json"
61116
61214
  },
61117
61215
  {
61118
- code: "align-domain-downgraded-to-entity",
61119
- severity: "warning",
61120
- description: "A submitted Domain node was finalized as an Entity because its Domain gate was missing or referenced unresolved children.",
61121
- trigger: "Align validation/finalize normalizes a node_type=domain proposal through domain_downgrade.",
61216
+ code: "align-domain-gate-invalid",
61217
+ severity: "error",
61218
+ description: "A submitted Domain node is missing a valid domain_gate with resolvable child refs.",
61219
+ trigger: "Align validation/finalize rejects node_type=domain when domain_gate.scope_blocks, child_refs, grouping_reason, or resolvable children are missing.",
61122
61220
  command: "context schema align-structure-intent --view minimal --format json"
61123
61221
  },
61124
61222
  {
61125
- code: "align-action-downgraded-to-entity",
61126
- severity: "warning",
61127
- description: "A submitted Action node was finalized as an Entity because action probe/gate evidence was insufficient.",
61128
- trigger: "Align validation/finalize normalizes a node_type=action proposal through action_downgrade.",
61223
+ code: "align-action-gate-invalid",
61224
+ severity: "error",
61225
+ description: "A submitted Action node is missing action_probe or structured action_gate evidence.",
61226
+ trigger: "Align validation/finalize rejects node_type=action when action_probe.has_steps_or_phases or action_gate.inference_sources is missing.",
61129
61227
  command: "context schema align-structure-intent --view minimal --format json"
61130
61228
  },
61131
61229
  {
@@ -61135,6 +61233,13 @@ var init_agentHintRegistry = __esm(() => {
61135
61233
  trigger: "Agent submits canonical align-structure-decision to validate/finalize instead of align-structure-intent.",
61136
61234
  command: "context schema align-structure-intent --view minimal --format json"
61137
61235
  },
61236
+ {
61237
+ code: "align-section-plan-crosses-headings",
61238
+ severity: "warning",
61239
+ description: "A planned Section spans multiple source heading paths; the CLI reports the risky shape without rewriting the agent's grouping.",
61240
+ trigger: "Align validate/finalize sees one section plan whose block_ids cross source heading boundaries.",
61241
+ command: "context schema align-structure-intent --view minimal --format json"
61242
+ },
61138
61243
  {
61139
61244
  code: "section-plan-non-contiguous",
61140
61245
  severity: "error",
@@ -61156,6 +61261,13 @@ var init_agentHintRegistry = __esm(() => {
61156
61261
  trigger: "The legacy flag form selected multiple compile modes together.",
61157
61262
  command: "context compile scan --format json"
61158
61263
  },
61264
+ {
61265
+ code: "compile-planned-section-fragment-review",
61266
+ severity: "info",
61267
+ description: "Adjacent planned Sections under the same source heading may be over-fragmented.",
61268
+ trigger: "The source-refs view sees a single-block planned group next to a larger or list-like planned group with the same owner, source, and heading path.",
61269
+ command: "context compile context <slug> --view source-refs --format json"
61270
+ },
61159
61271
  {
61160
61272
  code: "compile-section-kind-outside-plan",
61161
61273
  severity: "warning",
@@ -61282,6 +61394,20 @@ var init_agentHintRegistry = __esm(() => {
61282
61394
  trigger: "accept-safe-defaults sees items with duplicate, supersede, conflict, unknown-input, or confirmation blockers.",
61283
61395
  command: "context reconcile review"
61284
61396
  },
61397
+ {
61398
+ code: "prepare-candidates-index",
61399
+ severity: "info",
61400
+ description: "The default prepare candidates view is an index and requires item-level drilldown before judging relation.",
61401
+ trigger: "context workflow show --payload prepare --view candidates is called without --item-id or --candidate-id.",
61402
+ command: "context workflow show --payload prepare --view candidates --item-id <item-id> --unwrap --format json"
61403
+ },
61404
+ {
61405
+ code: "reconcile-apply-consumes-ready-review",
61406
+ severity: "error",
61407
+ description: "reconcile apply was called with decisions input even though apply consumes the current ready review artifact.",
61408
+ trigger: "context reconcile apply receives --decisions.",
61409
+ command: "context reconcile apply --format json"
61410
+ },
61285
61411
  {
61286
61412
  code: "example-code-prose-summary",
61287
61413
  severity: "warning",
@@ -61308,7 +61434,7 @@ var init_agentHintRegistry = __esm(() => {
61308
61434
  severity: "error",
61309
61435
  description: "A proposed write combines facts that should be split across separate evidence blocks.",
61310
61436
  trigger: "source_support candidates indicate multiple evidence blocks are needed for independently supported claims.",
61311
- command: "context compile draft-patch <slug> --input -"
61437
+ command: "context compile cycle <slug> --input - --format json"
61312
61438
  }
61313
61439
  ];
61314
61440
  DETAILED_AGENT_HINT_BY_CODE = new Map(DETAILED_AGENT_HINTS.map((entry) => [entry.code, entry]));
@@ -62415,6 +62541,9 @@ function draftSessionError(message, hint = {}) {
62415
62541
  }]
62416
62542
  });
62417
62543
  }
62544
+ function compileDraftPatchSubmitCommand(options = {}) {
62545
+ return options.submitCommand ?? "context compile cycle <slug> --input - --format json";
62546
+ }
62418
62547
  function cloneAction(action) {
62419
62548
  if (action.op === "supersede")
62420
62549
  return { ...action, new: { ...action.new } };
@@ -62502,9 +62631,79 @@ function compileDraftPatchCorrectShape() {
62502
62631
  }]
62503
62632
  }, null, 2);
62504
62633
  }
62634
+ function isCompileDraftPatchLikeInput(value) {
62635
+ if (!isRecord29(value))
62636
+ return false;
62637
+ if (Array.isArray(value.operations))
62638
+ return true;
62639
+ if (typeof value.schema_version === "string" && value.schema_version.startsWith("compile.draft-patch."))
62640
+ return true;
62641
+ if (Array.isArray(value.patches))
62642
+ return true;
62643
+ return false;
62644
+ }
62645
+ function compileDraftPatchShapeIssues(value) {
62646
+ const issues = [];
62647
+ if (!isRecord29(value)) {
62648
+ return [{
62649
+ path: "$",
62650
+ message: "compile draft patch payload must be an object",
62651
+ expected: { operations: "non-empty array" },
62652
+ current_value: value
62653
+ }];
62654
+ }
62655
+ if (value.schema_version !== undefined && value.schema_version !== COMPILE_DRAFT_PATCH_SCHEMA_VERSION) {
62656
+ issues.push({
62657
+ path: "schema_version",
62658
+ message: `schema_version may be omitted; when present it must be ${COMPILE_DRAFT_PATCH_SCHEMA_VERSION}`,
62659
+ expected: COMPILE_DRAFT_PATCH_SCHEMA_VERSION,
62660
+ current_value: value.schema_version
62661
+ });
62662
+ }
62663
+ if (value.actions !== undefined) {
62664
+ issues.push({
62665
+ path: "actions",
62666
+ message: "compile draft patch payload uses operations[]",
62667
+ expected: "operations[]",
62668
+ current_value: value.actions
62669
+ });
62670
+ }
62671
+ if (value.patches !== undefined) {
62672
+ issues.push({
62673
+ path: "patches",
62674
+ message: "compile draft patch payload uses operations[]",
62675
+ expected: "operations[]",
62676
+ current_value: value.patches
62677
+ });
62678
+ }
62679
+ if (!Array.isArray(value.operations) || value.operations.length === 0) {
62680
+ issues.push({
62681
+ path: "operations",
62682
+ message: "operations[] is required and must contain at least one patch operation",
62683
+ expected: [{ op: "replace_action", action_id: "act_001", action: {} }],
62684
+ current_value: value.operations
62685
+ });
62686
+ }
62687
+ return issues;
62688
+ }
62689
+ function throwCompileDraftPatchShapeError(issues, options = {}) {
62690
+ const first = issues[0];
62691
+ const message = first?.message ?? "compile draft patch payload must use operations[]";
62692
+ const command = compileDraftPatchSubmitCommand(options);
62693
+ throw draftSessionError(message, {
62694
+ command,
62695
+ next_action: "Submit a compile-draft-patch payload with operations[] to the compile cycle command.",
62696
+ correct_shape: compileDraftPatchCorrectShape(),
62697
+ diagnostics: {
62698
+ current_schema_version: COMPILE_DRAFT_PATCH_SCHEMA_VERSION,
62699
+ command,
62700
+ issues
62701
+ }
62702
+ });
62703
+ }
62505
62704
  function parsePatchOp(operation, path13) {
62506
62705
  if (operation.op === "replace") {
62507
- throw draftSessionError(`${path13}.op "replace" is JSON Patch style; use replace_action with action_id, not path`, {
62706
+ throw draftSessionError(`${path13}.op must be replace_action|remove_action|add_action`, {
62508
62707
  next_action: "Run context compile draft-status <slug> --format json, copy the action_id for the action to revise, then submit replace_action with action.",
62509
62708
  command: "context schema compile-draft-patch",
62510
62709
  path: `${path13}.op`,
@@ -62542,19 +62741,16 @@ function assertPatchActionId(value, path13) {
62542
62741
  }
62543
62742
  });
62544
62743
  }
62545
- function parseCompileDraftPatch(value) {
62744
+ function parseCompileDraftPatch(value, options = {}) {
62745
+ const shapeIssues = compileDraftPatchShapeIssues(value);
62746
+ if (shapeIssues.length > 0)
62747
+ throwCompileDraftPatchShapeError(shapeIssues, options);
62546
62748
  if (!isRecord29(value))
62547
62749
  throw draftSessionError("compile draft patch must be an object");
62548
- if (value.patches !== undefined) {
62549
- throw draftSessionError("compile draft patch field patches is not supported; use operations[]");
62550
- }
62551
- if (value.schema_version !== undefined && value.schema_version !== COMPILE_DRAFT_PATCH_SCHEMA_VERSION) {
62552
- throw draftSessionError(`schema_version must be ${COMPILE_DRAFT_PATCH_SCHEMA_VERSION}`);
62553
- }
62554
- if (!Array.isArray(value.operations) || value.operations.length === 0) {
62555
- throw draftSessionError("compile draft patch must contain non-empty operations[]");
62556
- }
62557
- const operations = value.operations.map((operation, index2) => {
62750
+ const operationsInput = value.operations;
62751
+ if (!Array.isArray(operationsInput))
62752
+ throwCompileDraftPatchShapeError(compileDraftPatchShapeIssues(value), options);
62753
+ const operations = operationsInput.map((operation, index2) => {
62558
62754
  const path13 = `operations[${index2}]`;
62559
62755
  if (!isRecord29(operation))
62560
62756
  throw draftSessionError(`${path13} must be an object`);
@@ -63734,6 +63930,24 @@ function filterCurrentDraftCandidates(input) {
63734
63930
  }));
63735
63931
  return { candidates, filtered: input.candidates.length - candidates.length };
63736
63932
  }
63933
+ function sameCycleAppliedSectionIds(input) {
63934
+ if (input.since === undefined)
63935
+ return new Set;
63936
+ return new Set(input.records.flatMap((record) => {
63937
+ const node3 = record.node ?? record.target?.node;
63938
+ const sectionId = record.target?.section_id;
63939
+ if (record.mode !== "compile" || node3 !== input.node || typeof sectionId !== "string" || compareTemporal(record.applied_at, input.since) !== 1) {
63940
+ return [];
63941
+ }
63942
+ return [sectionId];
63943
+ }));
63944
+ }
63945
+ function filterSameCycleAppliedCandidates(input) {
63946
+ if (input.sectionIds.size === 0)
63947
+ return { candidates: [...input.candidates], filtered: 0 };
63948
+ const candidates = input.candidates.filter((candidate) => !input.sectionIds.has(candidate.section_id));
63949
+ return { candidates, filtered: input.candidates.length - candidates.length };
63950
+ }
63737
63951
  function sectionOutputSnapshot(nodeSlug, section) {
63738
63952
  return {
63739
63953
  node: nodeSlug,
@@ -63963,6 +64177,11 @@ async function prepareCompileReconcileContext(input) {
63963
64177
  const challengeReceipt = recordedChallenges(challengePayloads);
63964
64178
  const { index: index2 } = await prepareRetrieval(input);
63965
64179
  const ledger = await readSemanticLedger(input.ctxDir);
64180
+ const sameCycleAppliedSections = sameCycleAppliedSectionIds({
64181
+ records: ledger.document.decisions,
64182
+ node: node3,
64183
+ ...input.workflowStartedAt !== undefined ? { since: input.workflowStartedAt } : {}
64184
+ });
63966
64185
  const restoredArchiveCandidates = await restoredArchiveCandidatesForNode(input.ctxDir, node3);
63967
64186
  const sources = await loadSources(input.ctxDir);
63968
64187
  const sourceById = new Map(sources.sources.map((source2) => [source2.id, source2]));
@@ -64031,6 +64250,10 @@ async function prepareCompileReconcileContext(input) {
64031
64250
  activeSectionIds,
64032
64251
  proposed: temporal.proposed
64033
64252
  });
64253
+ const sameCycleFiltered = filterSameCycleAppliedCandidates({
64254
+ candidates: draftFiltered.candidates,
64255
+ sectionIds: sameCycleAppliedSections
64256
+ });
64034
64257
  resolvedItems.push({
64035
64258
  item_id: itemId,
64036
64259
  ...typeof action.action_id === "string" ? { action_id: action.action_id, draft_action_id: action.action_id } : {},
@@ -64040,11 +64263,16 @@ async function prepareCompileReconcileContext(input) {
64040
64263
  proposed: temporal.proposed,
64041
64264
  ...defaultDecision !== undefined ? { default_decision: defaultDecision } : {},
64042
64265
  ...target !== undefined ? { target } : {},
64043
- candidates: stripCompileRelationHints(draftFiltered.candidates),
64266
+ candidates: stripCompileRelationHints(sameCycleFiltered.candidates),
64044
64267
  retrieval: draftFiltered.filtered > 0 ? {
64045
64268
  ...recalled.retrieval,
64046
- returned_candidates: Math.max(0, recalled.retrieval.returned_candidates - draftFiltered.filtered),
64047
- self_draft_candidates_filtered: draftFiltered.filtered
64269
+ returned_candidates: Math.max(0, recalled.retrieval.returned_candidates - draftFiltered.filtered - sameCycleFiltered.filtered),
64270
+ self_draft_candidates_filtered: draftFiltered.filtered,
64271
+ ...sameCycleFiltered.filtered > 0 ? { same_cycle_candidates_filtered: sameCycleFiltered.filtered } : {}
64272
+ } : sameCycleFiltered.filtered > 0 ? {
64273
+ ...recalled.retrieval,
64274
+ returned_candidates: Math.max(0, recalled.retrieval.returned_candidates - sameCycleFiltered.filtered),
64275
+ same_cycle_candidates_filtered: sameCycleFiltered.filtered
64048
64276
  } : recalled.retrieval,
64049
64277
  previous_decisions: recentSemanticLedgerRecords(ledger.document.decisions, (record) => record.mode === "compile" && (record.node === node3 || record.target?.node === node3)),
64050
64278
  ...evidence !== undefined ? { evidence } : {},
@@ -64108,6 +64336,7 @@ var init_prepareCompile = __esm(() => {
64108
64336
  init_compileDraftReferenceHints();
64109
64337
  init_compileNode();
64110
64338
  init_sectionFingerprints();
64339
+ init_temporal();
64111
64340
  init_sources();
64112
64341
  init_shared();
64113
64342
  init_evidence();
@@ -64512,7 +64741,8 @@ async function prepareReconcileContext(input) {
64512
64741
  ...input.node !== undefined ? { node: input.node } : {},
64513
64742
  ...input.draftPath !== undefined ? { draftPath: input.draftPath } : {},
64514
64743
  ...input.draft !== undefined ? { draft: input.draft } : {},
64515
- ...input.draftDigest !== undefined ? { draftDigest: input.draftDigest } : {}
64744
+ ...input.draftDigest !== undefined ? { draftDigest: input.draftDigest } : {},
64745
+ ...input.workflowStartedAt !== undefined ? { workflowStartedAt: input.workflowStartedAt } : {}
64516
64746
  });
64517
64747
  }
64518
64748
  case "drop": {
@@ -66193,6 +66423,44 @@ var defaultRunner = (args2) => new Promise((resolve6, reject) => {
66193
66423
  resolve6({ stdout, stderr, exitCode: code3 });
66194
66424
  });
66195
66425
  });
66426
+ var docsFetchCapabilitiesCache = new WeakMap;
66427
+ async function detectDocsFetchCapabilities(runner) {
66428
+ const result = await runner(["docs", "+fetch", "--help"]).catch(() => ({
66429
+ stdout: "",
66430
+ stderr: "",
66431
+ exitCode: 1
66432
+ }));
66433
+ const help = `${result.stdout}
66434
+ ${result.stderr}`;
66435
+ const supportsApiVersion = result.exitCode === 0 && /\s--api-version\b/u.test(help);
66436
+ return {
66437
+ apiVersion: supportsApiVersion ? "v2" : "v1",
66438
+ supportsDocFormatMarkdown: result.exitCode === 0 && /\s--doc-format\b/u.test(help)
66439
+ };
66440
+ }
66441
+ function resolveDocsFetchPlan(requested, runner) {
66442
+ if (requested === "v1" || requested === "v2")
66443
+ return Promise.resolve({ apiVersion: requested });
66444
+ let capabilitiesPromise = docsFetchCapabilitiesCache.get(runner);
66445
+ if (capabilitiesPromise === undefined) {
66446
+ capabilitiesPromise = detectDocsFetchCapabilities(runner);
66447
+ docsFetchCapabilitiesCache.set(runner, capabilitiesPromise);
66448
+ }
66449
+ return capabilitiesPromise.then((capabilities) => ({
66450
+ apiVersion: capabilities.apiVersion,
66451
+ ...capabilities.apiVersion === "v2" && capabilities.supportsDocFormatMarkdown ? { docFormat: "markdown" } : {}
66452
+ }));
66453
+ }
66454
+ function docsFetchFailureMessage(stderr, apiVersion) {
66455
+ const trimmed = stderr.trim();
66456
+ const base = `${LARK_BIN} docs +fetch failed (auth / permission / unsupported doc type): ${trimmed}`;
66457
+ const mentionsV2 = /api-version|--api-version|v2|deprecated|lark-cli update/iu.test(stderr);
66458
+ if (apiVersion === "v1" && mentionsV2) {
66459
+ return `${base}
66460
+ Detected docs API v2 guidance from lark-cli. Upgrade @larksuite/cli and run \`lark-cli update\`; newer docs +fetch supports \`--api-version v2\`.`;
66461
+ }
66462
+ return base;
66463
+ }
66196
66464
  function parseDocsFetchPayload(stdout) {
66197
66465
  const trimmed = stdout.trim();
66198
66466
  if (trimmed.length === 0) {
@@ -66213,25 +66481,144 @@ function parseDocsFetchPayload(stdout) {
66213
66481
  }
66214
66482
  return envelope;
66215
66483
  }
66484
+ function stringValue(value) {
66485
+ return typeof value === "string" && value.length > 0 ? value : undefined;
66486
+ }
66487
+ function decodeXmlEntities(value) {
66488
+ return value.replace(/&lt;/gu, "<").replace(/&gt;/gu, ">").replace(/&quot;/gu, '"').replace(/&#39;/gu, "'").replace(/&apos;/gu, "'").replace(/&amp;/gu, "&");
66489
+ }
66490
+ function xmlInlineText(xml) {
66491
+ const withLinks = xml.replace(/<a\b[^>]*\bhref=(["'])(.*?)\1[^>]*>([\s\S]*?)<\/a>/giu, (_match, _quote, href, label) => {
66492
+ const text5 = xmlInlineText(label);
66493
+ return text5.length > 0 ? `[${text5}](${decodeXmlEntities(href)})` : decodeXmlEntities(href);
66494
+ });
66495
+ return decodeXmlEntities(withLinks.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/gu, "$1").replace(/<br\s*\/?>/giu, `
66496
+ `).replace(/<[^>]+>/gu, "").replace(/[ \t\r\n]+/gu, " ").trim());
66497
+ }
66498
+ function renderXmlTable(tableXml) {
66499
+ const rows = [...tableXml.matchAll(/<(?:tr|table_row|table-row)\b[^>]*>([\s\S]*?)<\/(?:tr|table_row|table-row)>/giu)].map((row) => {
66500
+ const rowXml = row[1] ?? "";
66501
+ return [...rowXml.matchAll(/<(?:th|td|table_cell|table-cell)\b[^>]*>([\s\S]*?)<\/(?:th|td|table_cell|table-cell)>/giu)].map((cell) => xmlInlineText(cell[1] ?? "").replace(/\|/gu, "\\|"));
66502
+ }).filter((cells) => cells.length > 0);
66503
+ if (rows.length === 0)
66504
+ return xmlInlineText(tableXml);
66505
+ const width = Math.max(...rows.map((row) => row.length));
66506
+ const normalized = rows.map((row) => [...row, ...Array.from({ length: width - row.length }, () => "")]);
66507
+ const header = normalized[0] ?? [];
66508
+ const separator = header.map(() => "---");
66509
+ const bodyRows = normalized.slice(1);
66510
+ return [header, separator, ...bodyRows].map((row) => `| ${row.join(" | ")} |`).join(`
66511
+ `);
66512
+ }
66513
+ function renderDocxXmlToMarkdown(xml) {
66514
+ const tableBlocks = [];
66515
+ const withoutTables = xml.replace(/<table\b[^>]*>[\s\S]*?<\/table>/giu, (tableXml) => {
66516
+ const marker = `
66517
+
66518
+ @@C4A_DOCX_TABLE_${tableBlocks.length}@@
66519
+
66520
+ `;
66521
+ tableBlocks.push(renderXmlTable(tableXml));
66522
+ return marker;
66523
+ });
66524
+ const titleMatch = /<title\b[^>]*>([\s\S]*?)<\/title>/iu.exec(withoutTables);
66525
+ const title = titleMatch ? xmlInlineText(titleMatch[1] ?? "") : undefined;
66526
+ let body2 = withoutTables.replace(/<\?xml[\s\S]*?\?>/giu, "").replace(/<title\b[^>]*>[\s\S]*?<\/title>/giu, "").replace(/<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1>/giu, (_match, level, content3) => {
66527
+ const text5 = xmlInlineText(content3);
66528
+ return text5.length > 0 ? `
66529
+
66530
+ ${"#".repeat(Number(level))} ${text5}
66531
+
66532
+ ` : `
66533
+
66534
+ `;
66535
+ }).replace(/<heading\b[^>]*\blevel=(["'])([1-6])\1[^>]*>([\s\S]*?)<\/heading>/giu, (_match, _quote, level, content3) => {
66536
+ const text5 = xmlInlineText(content3);
66537
+ return text5.length > 0 ? `
66538
+
66539
+ ${"#".repeat(Number(level))} ${text5}
66540
+
66541
+ ` : `
66542
+
66543
+ `;
66544
+ }).replace(/<(?:p|paragraph|div|section)\b[^>]*>/giu, `
66545
+
66546
+ `).replace(/<\/(?:p|paragraph|div|section)>/giu, `
66547
+
66548
+ `).replace(/<li\b[^>]*>/giu, `
66549
+ - `).replace(/<\/li>/giu, `
66550
+ `).replace(/<br\s*\/?>/giu, `
66551
+ `).replace(/<a\b[^>]*\bhref=(["'])(.*?)\1[^>]*>([\s\S]*?)<\/a>/giu, (_match, _quote, href, label) => {
66552
+ const text5 = xmlInlineText(label);
66553
+ return text5.length > 0 ? `[${text5}](${decodeXmlEntities(href)})` : decodeXmlEntities(href);
66554
+ }).replace(/<[^>]+>/gu, "").replace(/@@C4A_DOCX_TABLE_(\d+)@@/gu, (_match, index2) => `
66555
+
66556
+ ${tableBlocks[Number(index2)] ?? ""}
66557
+
66558
+ `);
66559
+ body2 = decodeXmlEntities(body2).split(/\n/gu).map((line) => line.trimEnd()).join(`
66560
+ `).replace(/\n{3,}/gu, `
66561
+
66562
+ `).trim();
66563
+ return [title !== undefined && title.length > 0 ? `# ${title}` : "", body2].filter((part) => part.length > 0).join(`
66564
+
66565
+ `);
66566
+ }
66567
+ function payloadShapeSummary(payload) {
66568
+ const keys = Object.keys(payload).sort().join(", ") || "(none)";
66569
+ const document4 = payload.document;
66570
+ if (document4 && typeof document4 === "object") {
66571
+ const documentKeys = Object.keys(document4).sort().join(", ") || "(none)";
66572
+ return `top-level keys: ${keys}; document keys: ${documentKeys}`;
66573
+ }
66574
+ return `top-level keys: ${keys}`;
66575
+ }
66576
+ function extractDocsFetchContent(payload) {
66577
+ const document4 = payload.document && typeof payload.document === "object" ? payload.document : undefined;
66578
+ const title = stringValue(payload.title) ?? stringValue(document4?.title);
66579
+ const markdown = stringValue(payload.markdown) ?? stringValue(document4?.markdown);
66580
+ const withTitle = (result) => title === undefined ? result : { ...result, title };
66581
+ if (markdown !== undefined)
66582
+ return withTitle({ body: markdown, recognizedShape: true });
66583
+ const documentContent = stringValue(document4?.content);
66584
+ if (documentContent !== undefined) {
66585
+ const body2 = /^\s*</u.test(documentContent) ? renderDocxXmlToMarkdown(documentContent) : documentContent;
66586
+ return withTitle({ body: body2, recognizedShape: true });
66587
+ }
66588
+ return withTitle({
66589
+ recognizedShape: payload.title !== undefined || payload.markdown !== undefined || document4?.title !== undefined || document4?.markdown !== undefined || document4?.content !== undefined
66590
+ });
66591
+ }
66216
66592
  async function fetchFeishuDoc(input, runner = defaultRunner) {
66217
66593
  const chunks = [];
66218
66594
  let title;
66595
+ let unsupportedShape;
66596
+ const docsFetchPlan = await resolveDocsFetchPlan(input.docsApiVersion ?? "auto", runner);
66219
66597
  let nextOffset;
66220
66598
  for (let page = 0;page < MAX_FETCH_PAGES; page++) {
66221
66599
  const args2 = ["docs", "+fetch", "--doc", input.url, "--format", "json"];
66600
+ if (docsFetchPlan.apiVersion === "v2") {
66601
+ args2.push("--api-version", "v2");
66602
+ }
66603
+ if (docsFetchPlan.docFormat === "markdown") {
66604
+ args2.push("--doc-format", "markdown");
66605
+ }
66222
66606
  if (nextOffset !== undefined) {
66223
66607
  args2.push("--offset", String(nextOffset));
66224
66608
  }
66225
66609
  const result = await runner(args2);
66226
66610
  if (result.exitCode !== 0) {
66227
- throw new LarkCliError(`${LARK_BIN} docs +fetch failed (auth / permission / unsupported doc type): ${result.stderr.trim()}`, result.exitCode, result.stderr);
66611
+ throw new LarkCliError(docsFetchFailureMessage(result.stderr, docsFetchPlan.apiVersion), result.exitCode, result.stderr);
66228
66612
  }
66229
66613
  const payload = parseDocsFetchPayload(result.stdout);
66230
- if (page === 0 && typeof payload.title === "string") {
66231
- title = payload.title;
66614
+ const extracted = extractDocsFetchContent(payload);
66615
+ if (page === 0 && extracted.title !== undefined) {
66616
+ title = extracted.title;
66232
66617
  }
66233
- if (typeof payload.markdown === "string" && payload.markdown.length > 0) {
66234
- chunks.push(payload.markdown);
66618
+ if (extracted.body !== undefined && extracted.body.length > 0) {
66619
+ chunks.push(extracted.body);
66620
+ } else if (!extracted.recognizedShape && unsupportedShape === undefined) {
66621
+ unsupportedShape = payloadShapeSummary(payload);
66235
66622
  }
66236
66623
  if (payload.has_more !== true)
66237
66624
  break;
@@ -66247,6 +66634,9 @@ async function fetchFeishuDoc(input, runner = defaultRunner) {
66247
66634
 
66248
66635
  `);
66249
66636
  if (body2.trim().length === 0 && (title === undefined || title.length === 0)) {
66637
+ if (unsupportedShape !== undefined) {
66638
+ throw new LarkCliError(`${LARK_BIN} docs +fetch returned an unsupported payload shape (${unsupportedShape}). Expected data.markdown or data.document.content; this is a format adapter issue, not a permission error.`, 0, "");
66639
+ }
66250
66640
  throw new LarkCliError("document is empty — it may not exist or you lack permission", 0, "");
66251
66641
  }
66252
66642
  if (title !== undefined && title.length > 0 && !/^#\s/.test(body2)) {
@@ -68516,7 +68906,15 @@ function projectedWorkspaceFileFromInput(ctxDir, filePath, input) {
68516
68906
  }
68517
68907
  return { filePath, relativePath, root: root2 };
68518
68908
  }
68519
- function attachProjectedContainsLists(ctxDir, rendered) {
68909
+ function isOwnedOnlyByCurrentCodeSource(node3, sourceIds) {
68910
+ if (node3 === undefined || node3.node.sources.length === 0)
68911
+ return false;
68912
+ return node3.node.sources.every((source2) => sourceIds.has(sourceIdWithoutVersion(source2)));
68913
+ }
68914
+ async function attachProjectedContainsLists(ctxDir, rendered, sourceIds) {
68915
+ const existingFiles = await readWorkspaceNodeFiles(ctxDir);
68916
+ const existingNodesBySlug = new Map(flattenWorkspaceNodes(existingFiles).map((node3) => [node3.parsed.node.id, node3.parsed]));
68917
+ const existingContainsByParent = new Map(existingFiles.map((file) => [file.root.node.id, file.root.containsList]));
68520
68918
  const containsByParent = new Map;
68521
68919
  for (const [slug, item] of rendered) {
68522
68920
  if (!slug.includes("/"))
@@ -68537,13 +68935,23 @@ function attachProjectedContainsLists(ctxDir, rendered) {
68537
68935
  ]);
68538
68936
  }
68539
68937
  return new Map([...rendered.entries()].map(([slug, item]) => {
68540
- const entries = containsByParent.get(slug);
68541
- if (entries === undefined || entries.length === 0)
68938
+ const generatedEntries = containsByParent.get(slug) ?? [];
68939
+ const existingEntries = existingContainsByParent.get(slug) ?? item.input.containsList ?? [];
68940
+ if (existingEntries.length === 0 && generatedEntries.length === 0)
68542
68941
  return [slug, item];
68942
+ const merged = new Map;
68943
+ for (const entry of existingEntries) {
68944
+ const existingNode = existingNodesBySlug.get(entry.slug);
68945
+ if (isOwnedOnlyByCurrentCodeSource(existingNode, sourceIds))
68946
+ continue;
68947
+ merged.set(entry.slug, entry);
68948
+ }
68949
+ for (const entry of generatedEntries)
68950
+ merged.set(entry.slug, entry);
68543
68951
  return [slug, {
68544
68952
  input: {
68545
68953
  ...item.input,
68546
- containsList: [...entries].sort((left, right) => left.slug.localeCompare(right.slug))
68954
+ containsList: sortContainsEntries([...merged.values()])
68547
68955
  }
68548
68956
  }];
68549
68957
  }));
@@ -68557,7 +68965,7 @@ async function projectedWorkspaceFiles(ctxDir, rendered) {
68557
68965
  return [...byPath.values()];
68558
68966
  }
68559
68967
  async function projectedRenderContext(plan) {
68560
- const renderedWithContains = attachProjectedContainsLists(plan.state.ctxDir, plan.rendered);
68968
+ const renderedWithContains = await attachProjectedContainsLists(plan.state.ctxDir, plan.rendered, new Set(plan.sources));
68561
68969
  const [files, currentEdges, currentExternals, renderConfig] = await Promise.all([
68562
68970
  projectedWorkspaceFiles(plan.state.ctxDir, renderedWithContains),
68563
68971
  loadKnowledgeGraphEdges(plan.state.ctxDir),
@@ -68622,7 +69030,7 @@ async function renderCodeProjectionPlanFromState(state) {
68622
69030
  state
68623
69031
  };
68624
69032
  const renderContext = await projectedRenderContext(initialPlan);
68625
- const renderedWithContains = attachProjectedContainsLists(state.ctxDir, rendered);
69033
+ const renderedWithContains = await attachProjectedContainsLists(state.ctxDir, rendered, new Set(initialPlan.sources));
68626
69034
  const nodes = [];
68627
69035
  for (const item of pending) {
68628
69036
  const input = renderedWithContains.get(item.slug)?.input ?? item.input;
@@ -80329,8 +80737,8 @@ function reviewAgentHints(input) {
80329
80737
  code: "split-by-evidence-blocks",
80330
80738
  severity: "error",
80331
80739
  message: `${splitByEvidenceBlockCount} unsupported decision(s) appear to combine facts from multiple evidence blocks.`,
80332
- next_action: "Split the proposed content into one draft action per source_support.evidence_block_candidates[] entry, then rerun prepare/review. If the draft session is available, patch only the affected action with context compile draft-patch <slug> --input -.",
80333
- command: "context compile draft-patch <slug> --input -"
80740
+ next_action: "Split the proposed content into one draft action per source_support.evidence_block_candidates[] entry, then rerun prepare/review. If the draft session is available, submit a compile-draft-patch payload through context compile cycle <slug> --input - --format json.",
80741
+ command: "context compile cycle <slug> --input - --format json"
80334
80742
  });
80335
80743
  }
80336
80744
  const contentShapeIssueCount = input.issues.filter((issue2) => issue2.severity === "error" && issue2.path.includes(".proposed") && issue2.path.endsWith(".content") && issue2.message.startsWith("content must")).length;
@@ -80824,7 +81232,7 @@ function assertDelegatedDecisionsAllowed(input) {
80824
81232
 
80825
81233
  // src/reconcile/reviewSourceSupport.ts
80826
81234
  init_sourceSupport();
80827
- var FENCED_CODE_RE = /(^|\n)\s*(```|~~~)/u;
81235
+ var FENCED_CODE_RE2 = /(^|\n)\s*(```|~~~)/u;
80828
81236
  function preparedSupportContentMatches(input) {
80829
81237
  return typeof input.item?.proposed?.content === "string" && input.item.proposed.content === input.content || typeof input.item?.default_decision?.proposed?.content === "string" && input.item.default_decision.proposed.content === input.content;
80830
81238
  }
@@ -81040,9 +81448,9 @@ function needsExampleDetailPreservationWarning(input) {
81040
81448
  return false;
81041
81449
  if (supportKind(input.decision, input.item) !== "example")
81042
81450
  return false;
81043
- if (!FENCED_CODE_RE.test(citedTextForDecision2(input.decision, input.item)))
81451
+ if (!FENCED_CODE_RE2.test(citedTextForDecision2(input.decision, input.item)))
81044
81452
  return false;
81045
- return !FENCED_CODE_RE.test(input.decision.proposed?.content ?? "");
81453
+ return !FENCED_CODE_RE2.test(input.decision.proposed?.content ?? "");
81046
81454
  }
81047
81455
  function exampleDetailPreservationWarning(input) {
81048
81456
  return {
@@ -83391,6 +83799,26 @@ function prepareCandidateRows(context, options = {}) {
83391
83799
  }
83392
83800
  return rows;
83393
83801
  }
83802
+ function candidateIndexRows(context) {
83803
+ return context.items.map((item) => ({
83804
+ item_id: item.item_id,
83805
+ ...item.action_id !== undefined ? { action_id: item.action_id } : {},
83806
+ ...item.action_op_index !== undefined ? { action_op_index: item.action_op_index } : {},
83807
+ ...item.action_selector !== undefined ? { action_selector: item.action_selector } : {},
83808
+ status: item.status ?? "pending",
83809
+ target: item.target,
83810
+ candidates: item.candidates.length,
83811
+ candidate_count: item.candidates.length,
83812
+ ...item.source_support !== undefined ? {
83813
+ source_support: {
83814
+ verdict: item.source_support.verdict,
83815
+ missing_hard_terms_count: item.source_support.missing_hard_terms.length,
83816
+ missing_content_terms_count: item.source_support.missing_content_terms.length
83817
+ }
83818
+ } : {},
83819
+ ...item.candidates.length > 0 ? { candidate_detail_command: prepareCandidateDetailCommand(item.item_id) } : {}
83820
+ }));
83821
+ }
83394
83822
  function candidateViewHowToExplore(options, tokenBudget) {
83395
83823
  const baseCommand = [
83396
83824
  "context workflow show --payload prepare --view candidates",
@@ -83409,6 +83837,35 @@ function candidateViewHowToExplore(options, tokenBudget) {
83409
83837
  ];
83410
83838
  }
83411
83839
  function projectPrepareCandidates(context, options = {}) {
83840
+ if (options.itemId === undefined && options.candidateId === undefined) {
83841
+ const rows2 = candidateIndexRows(context);
83842
+ const page = paginate(rows2, options);
83843
+ return {
83844
+ schema_version: context.schema_version,
83845
+ mode: context.mode,
83846
+ workspace: context.workspace,
83847
+ target: context.target,
83848
+ view: "candidates",
83849
+ mode_hint: "index",
83850
+ filters: {},
83851
+ counts: {
83852
+ items: context.items.length,
83853
+ candidates: context.items.reduce((sum, item) => sum + item.candidates.length, 0),
83854
+ items_with_candidates: context.items.filter((item) => item.candidates.length > 0).length,
83855
+ shown: page.items.length
83856
+ },
83857
+ item_id_field: "item_id",
83858
+ items: page.items,
83859
+ ...page.page !== undefined ? { page: page.page } : {},
83860
+ agent_hints: [{
83861
+ code: "prepare-candidates-index",
83862
+ severity: "info",
83863
+ message: "Default candidates view lists prepare items and candidate counts only.",
83864
+ next_action: "Use candidate_detail_command or --item-id <item-id> to inspect one item's candidate Section content before judging relation.",
83865
+ command: "context workflow show --payload prepare --view candidates --item-id <item-id> --unwrap --format json"
83866
+ }]
83867
+ };
83868
+ }
83412
83869
  const tokenBudget = parseTokenBudgetOption(options.tokenBudget);
83413
83870
  const rows = prepareCandidateRows(context, options);
83414
83871
  return {
@@ -83499,6 +83956,40 @@ function sourceSupportMissingTerms2(support) {
83499
83956
  }))
83500
83957
  };
83501
83958
  }
83959
+ function sourceSupportSummary(support) {
83960
+ return {
83961
+ verdict: support.verdict,
83962
+ ...support.reason_code !== undefined ? { reason_code: support.reason_code } : {},
83963
+ matched: support.matched_term_count,
83964
+ total: support.content_term_count,
83965
+ required: support.required_term_count,
83966
+ missing_hard_terms_count: support.missing_hard_terms.length,
83967
+ missing_content_terms_count: support.missing_content_terms.length,
83968
+ ...support.missing_terms !== undefined ? { missing_terms_count: support.missing_terms.length } : {},
83969
+ ...support.evidence_block_candidates !== undefined ? { evidence_block_candidates: support.evidence_block_candidates.length } : {},
83970
+ ...support.evidence_block_source_ref !== undefined ? { evidence_block_source_ref: support.evidence_block_source_ref } : {},
83971
+ ...support.evidence_block_line_range !== undefined ? { evidence_block_line_range: support.evidence_block_line_range } : {},
83972
+ ...support.merged_from_source_refs !== undefined ? { merged_source_ref_count: support.merged_from_source_refs.length } : {},
83973
+ ...support.merge_kind !== undefined ? { merge_kind: support.merge_kind } : {}
83974
+ };
83975
+ }
83976
+ function sourceSupportDetail(support, projection) {
83977
+ if (projection === "summary")
83978
+ return sourceSupportSummary(support);
83979
+ return {
83980
+ verdict: support.verdict,
83981
+ ...support.reason_code !== undefined ? { reason_code: support.reason_code } : {},
83982
+ matched: support.matched_term_count,
83983
+ total: support.content_term_count,
83984
+ required: support.required_term_count,
83985
+ ...sourceSupportFailureTerms(support),
83986
+ ...sourceSupportMissingTerms2(support),
83987
+ ...support.evidence_block_source_ref !== undefined ? { evidence_block_source_ref: support.evidence_block_source_ref } : {},
83988
+ ...support.evidence_block_line_range !== undefined ? { evidence_block_line_range: support.evidence_block_line_range } : {},
83989
+ ...support.merged_from_source_refs !== undefined ? { merged_from_source_refs: support.merged_from_source_refs } : {},
83990
+ ...support.merge_kind !== undefined ? { merge_kind: support.merge_kind } : {}
83991
+ };
83992
+ }
83502
83993
  function nextDecisionsTemplate(context) {
83503
83994
  return context.next_decisions_template ?? {
83504
83995
  schema_version: context.schema_version,
@@ -83630,6 +84121,8 @@ function requirePrepareIssueStatus(value) {
83630
84121
  function compactPrepareItem(item, input = {}) {
83631
84122
  const proposed = isRecord35(item.proposed) ? item.proposed : {};
83632
84123
  const safeDefaultBlockers = computeSafeDefaultBlockers(item, input.mode ?? "compile");
84124
+ const candidates = item.candidates.length;
84125
+ const sourceSupportProjection = input.sourceSupportProjection ?? "summary";
83633
84126
  return {
83634
84127
  item_id: item.item_id,
83635
84128
  ...item.action_id !== undefined ? { action_id: item.action_id } : {},
@@ -83647,21 +84140,13 @@ function compactPrepareItem(item, input = {}) {
83647
84140
  ...item.default_decision !== undefined ? { default_decision: { relation: item.default_decision.relation, action: item.default_decision.action } } : {},
83648
84141
  ...safeDefaultBlockers.length > 0 ? { safe_default_blockers: safeDefaultBlockers } : {},
83649
84142
  ...item.source_support !== undefined ? {
83650
- source_support: {
83651
- verdict: item.source_support.verdict,
83652
- matched: item.source_support.matched_term_count,
83653
- total: item.source_support.content_term_count,
83654
- required: item.source_support.required_term_count,
83655
- ...sourceSupportFailureTerms(item.source_support),
83656
- ...sourceSupportMissingTerms2(item.source_support),
83657
- ...item.source_support.evidence_block_source_ref !== undefined ? { evidence_block_source_ref: item.source_support.evidence_block_source_ref } : {},
83658
- ...item.source_support.merged_from_source_refs !== undefined ? { merged_from_source_refs: item.source_support.merged_from_source_refs } : {},
83659
- ...item.source_support.merge_kind !== undefined ? { merge_kind: item.source_support.merge_kind } : {}
83660
- }
84143
+ source_support: sourceSupportDetail(item.source_support, sourceSupportProjection)
83661
84144
  } : {},
83662
84145
  ...item.temporal_prior !== undefined ? { temporal_prior: item.temporal_prior } : {},
83663
- candidates: item.candidates.length,
83664
- ...item.candidates.length > 0 ? {
84146
+ candidates,
84147
+ candidate_count: candidates,
84148
+ item_detail_command: `context workflow show --payload prepare --view issues --item-id ${item.item_id} --unwrap --format json`,
84149
+ ...candidates > 0 ? {
83665
84150
  candidate_detail_command: prepareCandidateDetailCommand(item.item_id)
83666
84151
  } : {},
83667
84152
  previous_decisions: item.previous_decisions.length,
@@ -83670,6 +84155,7 @@ function compactPrepareItem(item, input = {}) {
83670
84155
  profile: item.retrieval.profile,
83671
84156
  returned_candidates: item.retrieval.returned_candidates,
83672
84157
  ...item.retrieval.self_draft_candidates_filtered !== undefined ? { self_draft_candidates_filtered: item.retrieval.self_draft_candidates_filtered } : {},
84158
+ ...item.retrieval.same_cycle_candidates_filtered !== undefined ? { same_cycle_candidates_filtered: item.retrieval.same_cycle_candidates_filtered } : {},
83673
84159
  truncated: item.retrieval.truncated,
83674
84160
  ...item.retrieval.blocked !== undefined ? { blocked: item.retrieval.blocked } : {},
83675
84161
  ...item.retrieval.blocked_reason !== undefined ? { blocked_reason: item.retrieval.blocked_reason } : {}
@@ -83682,7 +84168,10 @@ function issuePrepareItem(item, input = {}) {
83682
84168
  const issueStatus = prepareIssueStatus(item);
83683
84169
  if (issueStatus === undefined)
83684
84170
  return null;
83685
- const compact2 = compactPrepareItem(item, input);
84171
+ const compact2 = compactPrepareItem(item, {
84172
+ ...input,
84173
+ sourceSupportProjection: "issue"
84174
+ });
83686
84175
  if (support === undefined)
83687
84176
  return { ...compact2, issue_status: issueStatus };
83688
84177
  return {
@@ -84747,7 +85236,7 @@ function registerReconcileCommand(program2) {
84747
85236
  }
84748
85237
  });
84749
85238
  });
84750
- reconcile.command("apply").description("Apply semantic decisions to active knowledge and record the ledger after verify").option("--format <format>", "json | yaml", "json").addHelpText("after", [
85239
+ reconcile.command("apply").description("Apply semantic decisions to active knowledge and record the ledger after verify").option("--format <format>", "json | yaml", "json").addOption(new Option("--decisions <path>", "invalid for apply; apply consumes the ready review artifact").hideHelp()).addHelpText("after", [
84751
85240
  "",
84752
85241
  "Apply consumes the current workflow scope's unique ready immutable review artifact.",
84753
85242
  "Do not pass hand-edited decisions or review-output files to apply.",
@@ -84760,6 +85249,18 @@ function registerReconcileCommand(program2) {
84760
85249
  stateRequirement: "state-required",
84761
85250
  flags: {},
84762
85251
  run: async (ctx) => {
85252
+ if (typeof options.decisions === "string") {
85253
+ throw new ContextError(ExitCode.UserError, "reconcile apply does not accept --decisions", {
85254
+ category: ErrorCategory.UserInputInvalid,
85255
+ agent_hints: [{
85256
+ code: "reconcile-apply-consumes-ready-review",
85257
+ severity: "error",
85258
+ message: "context reconcile apply reads the current workflow's ready immutable review artifact; it does not read semantic decisions from stdin.",
85259
+ next_action: "Run plain context reconcile apply for the current workflow scope.",
85260
+ command: "context reconcile apply --format json"
85261
+ }]
85262
+ });
85263
+ }
84763
85264
  const ctxDir = requireWorkspace2(ctx.ctxDir, "reconcile apply");
84764
85265
  const currentArtifact = await readUniqueReadyReviewArtifactForCurrent(ctxDir);
84765
85266
  const currentWorkflow = await readReadyCurrentWorkflow(ctxDir, "reconcile apply");
@@ -86757,6 +87258,14 @@ function activeContentSourceIds(value) {
86757
87258
  function sourcePlanById(value) {
86758
87259
  return new Map(sourcePlanRows(value).map((source2) => [source2.source_id, source2]));
86759
87260
  }
87261
+ function resolveSourceBundleSourceId(value, sourceIdOrAlias) {
87262
+ if (sourceIdOrAlias === undefined)
87263
+ return;
87264
+ const plans = sourcePlanRows(value);
87265
+ if (plans.some((source2) => source2.source_id === sourceIdOrAlias))
87266
+ return sourceIdOrAlias;
87267
+ return plans.find((source2) => source2.source_alias === sourceIdOrAlias)?.source_id ?? sourceIdOrAlias;
87268
+ }
86760
87269
  function sourceBundleCommand(record, options = {}, format = "text") {
86761
87270
  const parts = ["--view source-bundle"];
86762
87271
  if (options.sourceId !== undefined)
@@ -86771,19 +87280,16 @@ function sourceBundleCommand(record, options = {}, format = "text") {
86771
87280
  parts.push(`--page-size ${shellQuote(options.pageSize)}`);
86772
87281
  if (options.pageToken !== undefined)
86773
87282
  parts.push(`--page-token ${shellQuote(options.pageToken)}`);
86774
- if (options.tokenBudget !== undefined)
86775
- parts.push(`--token-budget ${shellQuote(options.tokenBudget)}`);
86776
- if (options.budget !== undefined)
86777
- parts.push(`--budget ${shellQuote(options.budget)}`);
86778
87283
  return workflowPayloadShowCommand(record, [parts.join(" "), "--unwrap", `--format ${format}`]);
86779
87284
  }
86780
87285
  function sourceBundleScopeBlocks(value, options) {
86781
87286
  const activeIds = activeAlignSourceIds(value);
87287
+ const selectedSourceId = resolveSourceBundleSourceId(value, options.sourceId);
86782
87288
  const windows = alignWindowRows(value);
86783
87289
  const selectedWindows = typeof options.windowId === "string" ? resolveWindowSelectors(windows, options.windowId) : [];
86784
87290
  const windowBlockIds = selectedWindows.length === 0 ? undefined : new Set(selectedWindows.flatMap((window2) => window2.block_ids));
86785
87291
  const range = parseOrdinalRange(options.range);
86786
- return alignBlockRows(value).filter((block) => typeof block.source_id === "string" && activeIds.has(block.source_id) && (options.sourceId === undefined || block.source_id === options.sourceId) && (windowBlockIds === undefined || typeof block.block_id === "string" && windowBlockIds.has(block.block_id)) && headingMatches(block.heading_path, options.heading) && (range === undefined || block.ordinal_in_source >= range.start && block.ordinal_in_source <= range.end));
87292
+ return alignBlockRows(value).filter((block) => typeof block.source_id === "string" && activeIds.has(block.source_id) && (selectedSourceId === undefined || block.source_id === selectedSourceId) && (windowBlockIds === undefined || typeof block.block_id === "string" && windowBlockIds.has(block.block_id)) && headingMatches(block.heading_path, options.heading) && (range === undefined || block.ordinal_in_source >= range.start && block.ordinal_in_source <= range.end));
86787
87293
  }
86788
87294
  function estimateSourceBundleBlocksBudget(blocks) {
86789
87295
  const sourceIds = new Set(blocks.map((block) => block.source_id).filter((sourceId) => typeof sourceId === "string"));
@@ -86836,6 +87342,25 @@ function withSourceBundleRecommendedPageSize(value, options) {
86836
87342
  const pageSize = sourceBundleRecommendedPageSize(value, options);
86837
87343
  return pageSize === undefined ? options : { ...options, pageSize };
86838
87344
  }
87345
+ function sourceBundleScopeFitsBudget(value, options) {
87346
+ const budget = estimateSourceBundleBlocksBudget(sourceBundleScopeBlocks(value, options));
87347
+ return budget.safe === true;
87348
+ }
87349
+ function firstSourceWindowId(value, sourceId) {
87350
+ if (sourceId === undefined)
87351
+ return;
87352
+ const first = alignWindowRows(value).filter((window2) => window2.source_id === sourceId && typeof window2.window_id === "string").sort((left, right) => (typeof right.token_estimate === "number" ? right.token_estimate : 0) - (typeof left.token_estimate === "number" ? left.token_estimate : 0))[0];
87353
+ return typeof first?.window_id === "string" ? first.window_id : undefined;
87354
+ }
87355
+ function sourceBundlePreferredScopeForSource(value, sourceId) {
87356
+ const sourceScope = { sourceId };
87357
+ if (sourceBundleScopeFitsBudget(value, sourceScope))
87358
+ return sourceScope;
87359
+ const windowId = firstSourceWindowId(value, sourceId);
87360
+ if (windowId !== undefined)
87361
+ return withSourceBundleRecommendedPageSize(value, { windowId });
87362
+ return withSourceBundleRecommendedPageSize(value, sourceScope);
87363
+ }
86839
87364
  function sourceBundleBudget(sourcePlans) {
86840
87365
  const tokenEstimate4 = sourcePlans.reduce((sum, source2) => sum + source2.bundle_token_estimate, 0);
86841
87366
  const blockCount = sourcePlans.reduce((sum, source2) => sum + source2.block_count, 0);
@@ -86865,17 +87390,13 @@ function routeKindForReadPlan(value, bundleSafe, firstSource) {
86865
87390
  if (routeMode === "batched_review_required") {
86866
87391
  if (firstSource === undefined)
86867
87392
  return "batched_route";
86868
- return firstSource.window_count > 1 ? "window_drilldown" : "source_drilldown";
87393
+ return sourceBundleScopeFitsBudget(value, { sourceId: firstSource.source_id }) ? "source_drilldown" : "window_drilldown";
86869
87394
  }
86870
87395
  if (bundleSafe)
86871
87396
  return "source_bundle";
86872
- return firstSource !== undefined && firstSource.window_count > 1 && firstSource.largest_window_tokens < firstSource.token_estimate ? "window_drilldown" : "source_drilldown";
86873
- }
86874
- function firstWindowId(value, sourceId) {
86875
- if (sourceId === undefined)
86876
- return;
86877
- const first = alignWindowRows(value).filter((window2) => window2.source_id === sourceId && typeof window2.window_id === "string").sort((left, right) => (typeof right.token_estimate === "number" ? right.token_estimate : 0) - (typeof left.token_estimate === "number" ? left.token_estimate : 0))[0];
86878
- return typeof first?.window_id === "string" ? first.window_id : undefined;
87397
+ if (firstSource === undefined)
87398
+ return "source_drilldown";
87399
+ return sourceBundleScopeFitsBudget(value, { sourceId: firstSource.source_id }) ? "source_drilldown" : "window_drilldown";
86879
87400
  }
86880
87401
  function readPlanNextAction(record, value, routeKind, firstSource) {
86881
87402
  if (routeKind === "no_align_needed") {
@@ -86894,11 +87415,10 @@ function readPlanNextAction(record, value, routeKind, firstSource) {
86894
87415
  };
86895
87416
  }
86896
87417
  if (routeKind === "window_drilldown") {
86897
- const windowId = firstWindowId(value, firstSource?.source_id);
86898
- if (windowId !== undefined) {
87418
+ if (firstSource !== undefined) {
86899
87419
  return {
86900
87420
  kind: "show_view",
86901
- command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { windowId })),
87421
+ command: sourceBundleCommand(record, sourceBundlePreferredScopeForSource(value, firstSource.source_id)),
86902
87422
  reason_code: "align-read-plan-window-drilldown",
86903
87423
  blocking: true
86904
87424
  };
@@ -86907,7 +87427,7 @@ function readPlanNextAction(record, value, routeKind, firstSource) {
86907
87427
  if (firstSource !== undefined) {
86908
87428
  return {
86909
87429
  kind: "show_view",
86910
- command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { sourceId: firstSource.source_id })),
87430
+ command: sourceBundleCommand(record, { sourceId: firstSource.source_id }),
86911
87431
  reason_code: "align-read-plan-source-drilldown",
86912
87432
  blocking: true
86913
87433
  };
@@ -87090,7 +87610,7 @@ function activeWindowQueue(value) {
87090
87610
  return String(left.window_id).localeCompare(String(right.window_id));
87091
87611
  });
87092
87612
  }
87093
- function nextWindowAfter(value, windowSelector) {
87613
+ function nextWindowReadAfter(value, windowSelector) {
87094
87614
  const selected = resolveWindowSelectors(alignWindowRows(value), windowSelector);
87095
87615
  const selectedIds = new Set(selected.map((window2) => window2.window_id));
87096
87616
  const queue = activeWindowQueue(value);
@@ -87100,9 +87620,18 @@ function nextWindowAfter(value, windowSelector) {
87100
87620
  lastIndex = index2;
87101
87621
  }
87102
87622
  if (lastIndex < 0)
87103
- return;
87623
+ return {};
87624
+ const currentSourceId = queue[lastIndex]?.source_id;
87625
+ if (typeof currentSourceId === "string") {
87626
+ const sameSourceNext = queue.slice(lastIndex + 1).find((window2) => window2.source_id === currentSourceId);
87627
+ if (typeof sameSourceNext?.window_id === "string")
87628
+ return { windowId: sameSourceNext.window_id };
87629
+ const nextSource = nextSourceAfter(value, currentSourceId);
87630
+ if (nextSource !== undefined)
87631
+ return { sourceId: nextSource };
87632
+ }
87104
87633
  const next = queue[lastIndex + 1];
87105
- return typeof next?.window_id === "string" ? next.window_id : undefined;
87634
+ return typeof next?.window_id === "string" ? { windowId: next.window_id } : {};
87106
87635
  }
87107
87636
  function firstSourceId(blocks) {
87108
87637
  const first = blocks.find((block) => typeof block.source_id === "string");
@@ -87172,7 +87701,7 @@ function sourceBundleNextAction(record, value, options, blocks, complete, pageNe
87172
87701
  if (nextSource !== undefined) {
87173
87702
  return {
87174
87703
  kind: "show_view",
87175
- command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { sourceId: nextSource })),
87704
+ command: sourceBundleCommand(record, sourceBundlePreferredScopeForSource(value, nextSource)),
87176
87705
  reason_code: "align-source-bundle-next-source",
87177
87706
  blocking: true
87178
87707
  };
@@ -87180,15 +87709,23 @@ function sourceBundleNextAction(record, value, options, blocks, complete, pageNe
87180
87709
  return partialScopeTerminalAction(record, routeMode, "align-source-bundle-last-source");
87181
87710
  }
87182
87711
  if (options.windowId !== undefined) {
87183
- const nextWindow = nextWindowAfter(value, options.windowId);
87184
- if (nextWindow !== undefined) {
87712
+ const nextRead = nextWindowReadAfter(value, options.windowId);
87713
+ if (nextRead.windowId !== undefined) {
87185
87714
  return {
87186
87715
  kind: "show_view",
87187
- command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { windowId: nextWindow })),
87716
+ command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { windowId: nextRead.windowId })),
87188
87717
  reason_code: "align-source-bundle-next-window",
87189
87718
  blocking: true
87190
87719
  };
87191
87720
  }
87721
+ if (nextRead.sourceId !== undefined) {
87722
+ return {
87723
+ kind: "show_view",
87724
+ command: sourceBundleCommand(record, sourceBundlePreferredScopeForSource(value, nextRead.sourceId)),
87725
+ reason_code: "align-source-bundle-next-source-after-window",
87726
+ blocking: true
87727
+ };
87728
+ }
87192
87729
  return partialScopeTerminalAction(record, routeMode, "align-source-bundle-last-window");
87193
87730
  }
87194
87731
  if (options.heading !== undefined || options.range !== undefined) {
@@ -87197,7 +87734,7 @@ function sourceBundleNextAction(record, value, options, blocks, complete, pageNe
87197
87734
  if (nextSource !== undefined) {
87198
87735
  return {
87199
87736
  kind: "show_view",
87200
- command: sourceBundleCommand(record, withSourceBundleRecommendedPageSize(value, { sourceId: nextSource })),
87737
+ command: sourceBundleCommand(record, sourceBundlePreferredScopeForSource(value, nextSource)),
87201
87738
  reason_code: "align-source-bundle-next-source-after-scope",
87202
87739
  blocking: true
87203
87740
  };
@@ -87227,6 +87764,8 @@ function estimateBundleTokens(blocks, renderedBytes) {
87227
87764
  return Math.max(sourceTokenEstimate + annotationTokenEstimate, Math.ceil(renderedBytes / 2));
87228
87765
  }
87229
87766
  function nextFallbackOptions(value, options) {
87767
+ if (!hasSemanticSourceBundleScope(options))
87768
+ return;
87230
87769
  const currentPageSize = parsePositiveIntegerOption(options.pageSize, "--page-size");
87231
87770
  if (currentPageSize === undefined) {
87232
87771
  const recommended = sourceBundleRecommendedPageSize(value, options);
@@ -87237,6 +87776,28 @@ function nextFallbackOptions(value, options) {
87237
87776
  return { ...options, pageSize: String(Math.max(1, Math.floor(currentPageSize / 2))) };
87238
87777
  return;
87239
87778
  }
87779
+ function hasSemanticSourceBundleScope(options) {
87780
+ return options.sourceId !== undefined || options.windowId !== undefined || options.heading !== undefined || options.range !== undefined;
87781
+ }
87782
+ function normalizeSourceBundleOptions(value, options) {
87783
+ const sourceId = resolveSourceBundleSourceId(value, options.sourceId);
87784
+ if (sourceId === undefined)
87785
+ return options;
87786
+ return sourceId === options.sourceId ? options : { ...options, sourceId };
87787
+ }
87788
+ function safeSourceBundleBudgets(options) {
87789
+ const requestedByteBudget = parsePositiveIntegerOption(options.budget, "--budget");
87790
+ const requestedTokenBudget = options.tokenBudget !== undefined ? parseTokenBudgetOption(options.tokenBudget) : undefined;
87791
+ const byteBudget = Math.min(requestedByteBudget ?? SOURCE_BUNDLE_DEFAULT_BYTE_BUDGET, SOURCE_BUNDLE_DEFAULT_BYTE_BUDGET);
87792
+ const tokenBudget = Math.min(requestedTokenBudget ?? AGENT_VIEW_SIZE_POLICY.acceptable.maxTokens, AGENT_VIEW_SIZE_POLICY.acceptable.maxTokens);
87793
+ return {
87794
+ byteBudget,
87795
+ tokenBudget,
87796
+ ...requestedByteBudget !== undefined ? { requestedByteBudget } : {},
87797
+ ...requestedTokenBudget !== undefined ? { requestedTokenBudget } : {},
87798
+ clamped: requestedByteBudget !== undefined && requestedByteBudget > SOURCE_BUNDLE_DEFAULT_BYTE_BUDGET || requestedTokenBudget !== undefined && requestedTokenBudget > AGENT_VIEW_SIZE_POLICY.acceptable.maxTokens
87799
+ };
87800
+ }
87240
87801
  function bundleOmittedText(input) {
87241
87802
  const full = [
87242
87803
  renderC4aTextAnnotation("bundle-omitted", {
@@ -87245,7 +87806,10 @@ function bundleOmittedText(input) {
87245
87806
  ...input.estimatedBytes !== undefined ? { estimated_bytes: input.estimatedBytes } : {},
87246
87807
  ...input.byteBudget !== undefined ? { byte_budget: input.byteBudget } : {},
87247
87808
  ...input.estimatedTokens !== undefined ? { estimated_tokens: input.estimatedTokens } : {},
87248
- ...input.tokenBudget !== undefined ? { token_budget: input.tokenBudget } : {}
87809
+ ...input.tokenBudget !== undefined ? { token_budget: input.tokenBudget } : {},
87810
+ ...input.budgetClamped === true ? { budget_clamped: true } : {},
87811
+ ...input.requestedByteBudget !== undefined ? { requested_byte_budget: input.requestedByteBudget } : {},
87812
+ ...input.requestedTokenBudget !== undefined ? { requested_token_budget: input.requestedTokenBudget } : {}
87249
87813
  }),
87250
87814
  renderC4aTextAnnotation("next-action", input.nextAction),
87251
87815
  ""
@@ -87341,6 +87905,7 @@ function renderSourceBundleText(input) {
87341
87905
  }
87342
87906
  function compactAlignSegmentSourceBundle(record, value, options) {
87343
87907
  validateSourceBundleScope(record, options);
87908
+ const normalizedOptions = normalizeSourceBundleOptions(value, options);
87344
87909
  if (activeAlignSourceIds(value).size === 0) {
87345
87910
  const nextAction2 = { kind: "start_compile_scan", command: COMPILE_SCAN_COMMAND, reason_code: "align-source-bundle-no-active-source" };
87346
87911
  return {
@@ -87353,8 +87918,33 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87353
87918
  read_scope_complete: false
87354
87919
  };
87355
87920
  }
87356
- const allBlocks = sourceBundleScopeBlocks(value, options);
87357
- if ((options.sourceId !== undefined || options.windowId !== undefined || options.heading !== undefined || options.range !== undefined) && allBlocks.length === 0) {
87921
+ if (!hasSemanticSourceBundleScope(normalizedOptions) && (normalizedOptions.pageSize !== undefined || normalizedOptions.pageToken !== undefined)) {
87922
+ const nextAction2 = {
87923
+ kind: "show_view",
87924
+ command: workflowPayloadShowCommand(record, ["--view read-plan", "--unwrap", "--format json"]),
87925
+ reason_code: "align-source-bundle-unscoped-pagination-disabled",
87926
+ blocking: true
87927
+ };
87928
+ return {
87929
+ view_schema_version: ALIGN_SOURCE_BUNDLE_VIEW_SCHEMA_VERSION,
87930
+ mode: "source-bundle",
87931
+ text: bundleOmittedText({ reasonCode: "source_bundle_unscoped_pagination_disabled", nextAction: nextAction2 }),
87932
+ bundle_omitted: true,
87933
+ reason_code: "source_bundle_unscoped_pagination_disabled",
87934
+ next_action: nextAction2,
87935
+ read_scope_complete: false,
87936
+ filters: compactFilters(normalizedOptions),
87937
+ agent_hints: [{
87938
+ code: "align-source-bundle-use-read-plan",
87939
+ severity: "warning",
87940
+ message: "Unscoped source-bundle pagination is disabled because it encourages reconstructing a large batch outside the workflow plan.",
87941
+ next_action: "Run next_action.command and follow the scoped source-bundle command chosen by read-plan.",
87942
+ command: nextAction2.command
87943
+ }]
87944
+ };
87945
+ }
87946
+ const allBlocks = sourceBundleScopeBlocks(value, normalizedOptions);
87947
+ if (hasSemanticSourceBundleScope(normalizedOptions) && allBlocks.length === 0) {
87358
87948
  const nextAction2 = {
87359
87949
  kind: "show_view",
87360
87950
  command: workflowPayloadShowCommand(record, ["--view read-plan", "--unwrap", "--format json"]),
@@ -87369,13 +87959,13 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87369
87959
  reason_code: "source_bundle_scope_empty",
87370
87960
  next_action: nextAction2,
87371
87961
  read_scope_complete: false,
87372
- filters: compactFilters(options)
87962
+ filters: compactFilters(normalizedOptions)
87373
87963
  };
87374
87964
  }
87375
- const page = paginate(allBlocks, options);
87965
+ const page = paginate(allBlocks, normalizedOptions);
87376
87966
  const pageNextToken = typeof page.page?.next_token === "string" ? page.page.next_token : undefined;
87377
- const complete = sourceBundleScopeComplete(value, page.items, options, pageNextToken !== undefined);
87378
- const nextAction = sourceBundleNextAction(record, value, options, page.items, complete, pageNextToken);
87967
+ const complete = sourceBundleScopeComplete(value, page.items, normalizedOptions, pageNextToken !== undefined);
87968
+ const nextAction = sourceBundleNextAction(record, value, normalizedOptions, page.items, complete, pageNextToken);
87379
87969
  const rendered = renderSourceBundleText({
87380
87970
  value,
87381
87971
  blocks: page.items,
@@ -87383,17 +87973,22 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87383
87973
  readScopeComplete: complete,
87384
87974
  ...page.page !== undefined ? { page: page.page } : {}
87385
87975
  });
87386
- const byteBudget = parsePositiveIntegerOption(options.budget, "--budget") ?? SOURCE_BUNDLE_DEFAULT_BYTE_BUDGET;
87387
- const tokenBudget = options.tokenBudget !== undefined ? parseTokenBudgetOption(options.tokenBudget) : AGENT_VIEW_SIZE_POLICY.acceptable.maxTokens;
87976
+ const budget = safeSourceBundleBudgets(normalizedOptions);
87977
+ const { byteBudget, tokenBudget } = budget;
87388
87978
  const estimatedBytes = Buffer.byteLength(rendered.text, "utf8");
87389
87979
  const estimatedTokens = estimateBundleTokens(page.items, estimatedBytes);
87390
87980
  if (estimatedBytes > byteBudget || estimatedTokens > tokenBudget) {
87391
- const fallbackOptions = nextFallbackOptions(value, options);
87392
- const fallbackAction = fallbackOptions === undefined ? {
87981
+ const fallbackOptions = nextFallbackOptions(value, normalizedOptions);
87982
+ const fallbackAction = !hasSemanticSourceBundleScope(normalizedOptions) ? {
87983
+ kind: "show_view",
87984
+ command: workflowPayloadShowCommand(record, ["--view read-plan", "--unwrap", "--format json"]),
87985
+ reason_code: "align-source-bundle-return-read-plan",
87986
+ blocking: true
87987
+ } : fallbackOptions === undefined ? {
87393
87988
  kind: "show_view",
87394
87989
  command: workflowPayloadShowCommand(record, [
87395
87990
  "--view block-index",
87396
- ...options.sourceId !== undefined ? [`--source ${shellQuote(options.sourceId)}`] : [],
87991
+ ...normalizedOptions.sourceId !== undefined ? [`--source ${shellQuote(normalizedOptions.sourceId)}`] : [],
87397
87992
  "--unwrap",
87398
87993
  "--format json"
87399
87994
  ]),
@@ -87414,6 +88009,9 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87414
88009
  byteBudget,
87415
88010
  estimatedTokens,
87416
88011
  tokenBudget,
88012
+ budgetClamped: budget.clamped,
88013
+ ...budget.requestedByteBudget !== undefined ? { requestedByteBudget: budget.requestedByteBudget } : {},
88014
+ ...budget.requestedTokenBudget !== undefined ? { requestedTokenBudget: budget.requestedTokenBudget } : {},
87417
88015
  nextAction: fallbackAction
87418
88016
  }),
87419
88017
  bundle_omitted: true,
@@ -87421,6 +88019,11 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87421
88019
  byte_budget: byteBudget,
87422
88020
  estimated_tokens: estimatedTokens,
87423
88021
  token_budget: tokenBudget,
88022
+ ...budget.clamped ? {
88023
+ budget_clamped: true,
88024
+ ...budget.requestedByteBudget !== undefined ? { requested_byte_budget: budget.requestedByteBudget } : {},
88025
+ ...budget.requestedTokenBudget !== undefined ? { requested_token_budget: budget.requestedTokenBudget } : {}
88026
+ } : {},
87424
88027
  next_action: fallbackAction,
87425
88028
  read_scope_complete: false,
87426
88029
  agent_hints: [{
@@ -87434,12 +88037,12 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87434
88037
  byte_budget: byteBudget,
87435
88038
  estimated_tokens: estimatedTokens,
87436
88039
  token_budget: tokenBudget,
87437
- feedback: "If this fallback seems too conservative during testing, report estimated_tokens/token_budget, estimated_bytes/byte_budget, and any override values you tried.",
87438
- override_flags: {
87439
- byte_budget: "--budget <bytes>",
87440
- token_budget: "--token-budget <tokens>"
87441
- },
87442
- override_policy: "Only raise these budgets when the user is explicitly testing bundle size behavior; report the estimates and requested override values."
88040
+ ...budget.clamped ? {
88041
+ budget_clamped: true,
88042
+ requested_byte_budget: budget.requestedByteBudget,
88043
+ requested_token_budget: budget.requestedTokenBudget
88044
+ } : {},
88045
+ feedback: "If this fallback seems too conservative during testing, report estimated_tokens/token_budget and estimated_bytes/byte_budget. Source-bundle keeps generated commands inside the agent-safe budget policy."
87443
88046
  }
87444
88047
  }]
87445
88048
  };
@@ -87448,10 +88051,15 @@ function compactAlignSegmentSourceBundle(record, value, options) {
87448
88051
  view_schema_version: ALIGN_SOURCE_BUNDLE_VIEW_SCHEMA_VERSION,
87449
88052
  mode: "source-bundle",
87450
88053
  format: "c4a-annotated-text",
87451
- filters: compactFilters(options),
88054
+ filters: compactFilters(normalizedOptions),
87452
88055
  text: rendered.text,
87453
88056
  text_bytes: estimatedBytes,
87454
88057
  estimated_tokens: estimatedTokens,
88058
+ ...budget.clamped ? {
88059
+ budget_clamped: true,
88060
+ ...budget.requestedByteBudget !== undefined ? { requested_byte_budget: budget.requestedByteBudget } : {},
88061
+ ...budget.requestedTokenBudget !== undefined ? { requested_token_budget: budget.requestedTokenBudget } : {}
88062
+ } : {},
87455
88063
  read_scope_complete: complete,
87456
88064
  raw_c4a_sentinel_escaped: rendered.collisionEscaped,
87457
88065
  ...rendered.collisionEscapedBlockIds.length > 0 ? {
@@ -88116,7 +88724,7 @@ function coverageRows(value) {
88116
88724
  const row = {
88117
88725
  candidate_id: candidateId2,
88118
88726
  issue_type: issueType,
88119
- node_slug: stringValue3(candidate.node_slug, "unknown"),
88727
+ node_slug: stringValue4(candidate.node_slug, "unknown"),
88120
88728
  signal: coverageSignal(candidate),
88121
88729
  why_flagged: whyFlagged(candidate),
88122
88730
  source_ref_count: sourceRefs2.length,
@@ -88232,7 +88840,7 @@ function compareCoverageGroups(a, b) {
88232
88840
  return signalRank(b.signal) - signalRank(a.signal) || a.issue_type.localeCompare(b.issue_type) || b.count - a.count;
88233
88841
  }
88234
88842
  function coverageSignal(candidate) {
88235
- return stringValue3(candidate.signal, "unknown");
88843
+ return stringValue4(candidate.signal, "unknown");
88236
88844
  }
88237
88845
  function whyFlagged(candidate) {
88238
88846
  const direct = strings(candidate.why_flagged);
@@ -88277,7 +88885,7 @@ function strings(value) {
88277
88885
  function isRecord37(value) {
88278
88886
  return typeof value === "object" && value !== null && !Array.isArray(value);
88279
88887
  }
88280
- function stringValue3(value, fallback) {
88888
+ function stringValue4(value, fallback) {
88281
88889
  return typeof value === "string" && value.length > 0 ? value : fallback;
88282
88890
  }
88283
88891
  function setString(target, key, value) {
@@ -88302,6 +88910,7 @@ function headingMatches2(path13, input) {
88302
88910
 
88303
88911
  // src/commands/workflowNodeContextPayloadViews.ts
88304
88912
  init_workflowPayloadStore();
88913
+ init_markdownFormatSignals();
88305
88914
  var SOURCE_REFS_SELECTION_POLICY = {
88306
88915
  id: "source-refs-v2",
88307
88916
  order: [
@@ -88358,6 +88967,7 @@ function nodeContextSourceRefRows(value) {
88358
88967
  const quotePreview = previewText(snippet.quote);
88359
88968
  const quoteText = normalizedPreviewBasis(snippet.quote);
88360
88969
  const quoteCharCount = quoteText?.length;
88970
+ const formatSignals = markdownFormatSignals(snippet.quote);
88361
88971
  const blockId = typeof snippet.block_id === "string" ? snippet.block_id : undefined;
88362
88972
  const sourceId = typeof snippet.source_id === "string" ? snippet.source_id : undefined;
88363
88973
  const finalizedOwnershipRole = typeof snippet.finalized_ownership_role === "string" ? snippet.finalized_ownership_role : undefined;
@@ -88380,6 +88990,10 @@ function nodeContextSourceRefRows(value) {
88380
88990
  ...quoteCharCount !== undefined ? { quote_char_count: quoteCharCount } : {},
88381
88991
  ...quotePreview !== undefined ? { preview_char_count: quotePreview.length } : {},
88382
88992
  ...quotePreview !== undefined && quoteCharCount !== undefined ? { preview_is_complete: quotePreview.length >= quoteCharCount } : {},
88993
+ ...formatSignals.format_sensitive ? {
88994
+ ...formatSignals,
88995
+ quote_preview_preserves_line_breaks: false
88996
+ } : {},
88383
88997
  ...node3 !== undefined && blockId !== undefined && canRequestFullTextForSnippet(snippet) ? { request_full_text_command: `context compile context ${shellQuote(node3)} --request-full-text ${shellQuote(blockId)} --view text --format json` } : {}
88384
88998
  };
88385
88999
  });
@@ -88635,26 +89249,28 @@ function sanitizeNodeContextValue(value) {
88635
89249
  };
88636
89250
  }
88637
89251
  function compactPreparePayload(value, view, options = {}) {
88638
- const wantsIssueDetail = view === "issues" && (options.status !== undefined || options.itemId !== undefined || options.pageSize !== undefined || options.pageToken !== undefined);
89252
+ const wantsIssueDetail = view === "issues" && options.itemId !== undefined;
89253
+ const shouldDefaultPage = view === "summary" || view === "issues" || view === "candidates" && options.itemId === undefined && options.candidateId === undefined;
89254
+ const pagedOptions = shouldDefaultPage && options.pageSize === undefined ? { ...options, pageSize: "20" } : options;
88639
89255
  const projected = projectPrepareContext(value, view, {
88640
- ...options.status !== undefined ? { status: options.status } : {},
88641
- ...options.itemId !== undefined ? { itemId: options.itemId } : {},
88642
- ...options.candidateId !== undefined ? { candidateId: options.candidateId } : {},
88643
- ...options.pageSize !== undefined ? { pageSize: options.pageSize } : {},
88644
- ...options.pageToken !== undefined ? { pageToken: options.pageToken } : {},
88645
- ...options.tokenBudget !== undefined ? { tokenBudget: options.tokenBudget } : {},
89256
+ ...pagedOptions.status !== undefined ? { status: pagedOptions.status } : {},
89257
+ ...pagedOptions.itemId !== undefined ? { itemId: pagedOptions.itemId } : {},
89258
+ ...pagedOptions.candidateId !== undefined ? { candidateId: pagedOptions.candidateId } : {},
89259
+ ...pagedOptions.pageSize !== undefined ? { pageSize: pagedOptions.pageSize } : {},
89260
+ ...pagedOptions.pageToken !== undefined ? { pageToken: pagedOptions.pageToken } : {},
89261
+ ...pagedOptions.tokenBudget !== undefined ? { tokenBudget: pagedOptions.tokenBudget } : {},
88646
89262
  ...wantsIssueDetail ? { detail: true } : {}
88647
89263
  });
88648
89264
  if (!isRecord36(projected))
88649
89265
  return { value: projected };
88650
- if (view !== "issues")
89266
+ if (view === "candidates")
88651
89267
  return projected;
88652
- const issueItems = asRecords(projected.items);
88653
- const page = paginate(issueItems, options);
89268
+ const projectedItems = asRecords(projected.items);
89269
+ const page = paginate(projectedItems, pagedOptions);
88654
89270
  const existingFilters = isRecord36(projected.filters) ? projected.filters : {};
88655
89271
  const filters = {
88656
89272
  ...existingFilters,
88657
- ...compactFilters(options)
89273
+ ...compactFilters(pagedOptions)
88658
89274
  };
88659
89275
  return {
88660
89276
  ...projected,
@@ -89491,7 +90107,13 @@ function writeWorkflowShowOutput(input) {
89491
90107
  return;
89492
90108
  }
89493
90109
  const metadata2 = workflowPayloadMetadata(input.record);
89494
- const compactValue = input.view === undefined ? undefined : compactWorkflowPayloadView(input.record, input.view, input.viewOptions);
90110
+ const rawCompactValue = input.view === undefined ? undefined : compactWorkflowPayloadView(input.record, input.view, input.viewOptions);
90111
+ const compactValue = input.view !== undefined && rawCompactValue !== undefined ? withPagedNextCommand({
90112
+ record: input.record,
90113
+ view: input.view,
90114
+ viewOptions: input.viewOptions,
90115
+ value: rawCompactValue
90116
+ }) : rawCompactValue;
89495
90117
  const availableViews = workflowPayloadAvailableViews(input.record.payload);
89496
90118
  const viewGuide = input.view === undefined && !input.metadataOnly && !input.unwrap ? workflowPayloadViewGuide(input.record) : {};
89497
90119
  const shouldOmitFullValue = input.view === undefined && !input.metadataOnly && !input.unwrap && availableViews.length > 0;
@@ -90096,7 +90718,7 @@ init_alignBlockStructuralRole();
90096
90718
  function isRecord39(value) {
90097
90719
  return typeof value === "object" && value !== null && !Array.isArray(value);
90098
90720
  }
90099
- function stringValue4(value) {
90721
+ function stringValue5(value) {
90100
90722
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
90101
90723
  }
90102
90724
  function assertKnownEvidenceBlocks(input) {
@@ -90259,7 +90881,7 @@ function normalizeUnresolved(value) {
90259
90881
  return Array.isArray(value) ? value.filter(isRecord39) : [];
90260
90882
  }
90261
90883
  function validateUnresolvedQuestions(input) {
90262
- const questionIds = new Set(input.unresolved.map((item) => stringValue4(item.question_id)).filter((item) => item !== undefined));
90884
+ const questionIds = new Set(input.unresolved.map((item) => stringValue5(item.question_id)).filter((item) => item !== undefined));
90263
90885
  input.blockOwnership.forEach((item, index2) => {
90264
90886
  if (item.ownership_role !== "unresolved")
90265
90887
  return;
@@ -90814,9 +91436,9 @@ function parseNodes(value) {
90814
91436
  return value.map((raw, index2) => {
90815
91437
  if (!isRecord18(raw))
90816
91438
  reject(`nodes[${index2}]`, "node must be an object");
90817
- const rawSlug = stringValue(raw.slug);
90818
- const rawHint = stringValue(raw.llm_slug_hint);
90819
- const slugBase = rawSlug ?? (rawHint !== undefined ? slugBaseFromHint(rawHint) : undefined) ?? stringValue(raw.title);
91439
+ const rawSlug = stringValue2(raw.slug);
91440
+ const rawHint = stringValue2(raw.llm_slug_hint);
91441
+ const slugBase = rawSlug ?? (rawHint !== undefined ? slugBaseFromHint(rawHint) : undefined) ?? stringValue2(raw.title);
90820
91442
  if (!slugBase)
90821
91443
  reject(`nodes[${index2}].slug`, "slug, llm_slug_hint, or title is required");
90822
91444
  const slug = rawSlug !== undefined ? rawSlug.split("/").map((part) => slugify(part)).filter(Boolean).join("/") : slugify(slugBase);
@@ -90836,16 +91458,16 @@ function parseNodes(value) {
90836
91458
  } : {}
90837
91459
  });
90838
91460
  }
90839
- const llmSlugHint = stringValue(raw.llm_slug_hint);
90840
- const containsParent = stringValue(raw.contains_parent);
90841
- const containsParentRef = stringValue(raw.contains_parent_ref);
90842
- const summary3 = stringValue(raw.summary);
91461
+ const llmSlugHint = stringValue2(raw.llm_slug_hint);
91462
+ const containsParent = stringValue2(raw.contains_parent);
91463
+ const containsParentRef = stringValue2(raw.contains_parent_ref);
91464
+ const summary3 = stringValue2(raw.summary);
90843
91465
  return {
90844
91466
  slug,
90845
91467
  ...llmSlugHint !== undefined ? { llm_slug_hint: llmSlugHint } : {},
90846
91468
  node_type: nodeType,
90847
91469
  tags,
90848
- title: stringValue(raw.title) ?? slug,
91470
+ title: stringValue2(raw.title) ?? slug,
90849
91471
  ...raw.contains_parent === null ? { contains_parent: null } : {},
90850
91472
  ...containsParent !== undefined ? { contains_parent: containsParent } : {},
90851
91473
  ...containsParentRef !== undefined ? { contains_parent_ref: containsParentRef } : {},
@@ -90895,33 +91517,6 @@ function validateInferenceSources(gate, path13) {
90895
91517
  }
90896
91518
  }
90897
91519
  }
90898
- function downgradeReason(node3) {
90899
- if (node3.action_probe?.has_steps_or_phases !== true)
90900
- return "action_probe lacks explicit steps or phases";
90901
- if (node3.action_gate === undefined)
90902
- return "action gate lacks structured inference sources";
90903
- return null;
90904
- }
90905
- function downgradeNode(node3, warningKind, reason) {
90906
- return {
90907
- node: {
90908
- ...node3,
90909
- node_type: "entity",
90910
- tags: node3.tags.length > 0 && !node3.tags.some((tag) => ACTION_KIND_VALUES.includes(tag)) ? node3.tags : ["term"]
90911
- },
90912
- warning: {
90913
- kind: warningKind,
90914
- node_slug: node3.slug,
90915
- reason,
90916
- original_proposal: {
90917
- node_type: node3.node_type,
90918
- title: node3.title,
90919
- rationale: node3.summary ?? ""
90920
- },
90921
- evidence_blocks: node3.evidence_blocks
90922
- }
90923
- };
90924
- }
90925
91520
  function scopeNameEntityWarning(node3) {
90926
91521
  if (node3.node_type !== "entity")
90927
91522
  return null;
@@ -90940,6 +91535,92 @@ function scopeNameEntityWarning(node3) {
90940
91535
  evidence_blocks: node3.evidence_blocks
90941
91536
  };
90942
91537
  }
91538
+ function gateRepairOptions(type) {
91539
+ return type === "domain" ? [
91540
+ "If this is a Domain, add domain_gate.scope_blocks, domain_gate.child_refs, and domain_gate.grouping_reason with resolvable child_refs.",
91541
+ "If this is not a Domain, resubmit it as node_type=entity and choose the concrete Entity tag yourself; CLI will not auto-pick tags."
91542
+ ] : [
91543
+ "If this is an Action, add action_probe plus action_gate.inference_sources with actor, outcome_or_goal, repeatability_or_plan, and answerability evidence.",
91544
+ "If this is not an Action, resubmit it as node_type=entity or move the process wording into a Section under the owning Node; CLI will not auto-pick tags."
91545
+ ];
91546
+ }
91547
+ function normalizeDomainGate(input) {
91548
+ const gate = input.node.domain_gate;
91549
+ const rawChildRefs = Array.isArray(gate?.child_refs) ? gate.child_refs : undefined;
91550
+ const childRefs = rawChildRefs?.map((ref) => typeof ref === "string" ? ref.trim() : "") ?? [];
91551
+ const unresolvedChildRefs = childRefs.filter((ref) => ref.length === 0 || !input.refs.has(ref) && !input.allSlugs.has(ref));
91552
+ const validGate = gate !== undefined && Array.isArray(gate.scope_blocks) && rawChildRefs !== undefined && typeof gate.grouping_reason === "string" && childRefs.length === rawChildRefs.length && unresolvedChildRefs.length === 0;
91553
+ if (!validGate) {
91554
+ const missing = [
91555
+ gate === undefined ? "domain_gate" : undefined,
91556
+ gate !== undefined && !Array.isArray(gate.scope_blocks) ? "domain_gate.scope_blocks" : undefined,
91557
+ rawChildRefs === undefined ? "domain_gate.child_refs" : undefined,
91558
+ gate !== undefined && typeof gate.grouping_reason !== "string" ? "domain_gate.grouping_reason" : undefined,
91559
+ unresolvedChildRefs.length > 0 ? "domain_gate.child_refs.resolvable" : undefined
91560
+ ].filter((item) => item !== undefined);
91561
+ reject(rawChildRefs === undefined || unresolvedChildRefs.length > 0 ? `nodes[${input.nodeIndex}].domain_gate.child_refs` : `nodes[${input.nodeIndex}].domain_gate`, "node_type=domain requires a valid domain_gate; CLI does not auto-downgrade invalid Domain nodes to entity", {
91562
+ hintCode: "align-domain-gate-invalid",
91563
+ reasonCode: "align-domain-gate-invalid",
91564
+ schemaLookup: "context schema align-structure-intent --view minimal --format json",
91565
+ repairOptions: gateRepairOptions("domain"),
91566
+ availableNodeRefs: nodeRefsForHint(input.refs),
91567
+ availableNodeSlugs: [...input.allSlugs],
91568
+ diagnostics: {
91569
+ missing_or_invalid: missing,
91570
+ unresolved_child_refs: unresolvedChildRefs,
91571
+ submitted_node_type: "domain",
91572
+ auto_downgrade: false
91573
+ }
91574
+ });
91575
+ }
91576
+ const canonicalChildRefs = childRefs.map((ref) => input.refs.get(ref) ?? ref);
91577
+ const duplicateChildRef = canonicalChildRefs.find((ref, refIndex) => canonicalChildRefs.indexOf(ref) !== refIndex);
91578
+ if (duplicateChildRef !== undefined) {
91579
+ reject(`nodes[${input.nodeIndex}].domain_gate.child_refs`, `domain_gate.child_refs contains duplicate child "${duplicateChildRef}"`, {
91580
+ reasonCode: "duplicate-domain-child-ref",
91581
+ failedRef: duplicateChildRef,
91582
+ availableNodeRefs: nodeRefsForHint(input.refs),
91583
+ availableNodeSlugs: [...input.allSlugs]
91584
+ });
91585
+ }
91586
+ return {
91587
+ ...input.node,
91588
+ domain_gate: {
91589
+ ...gate,
91590
+ child_refs: canonicalChildRefs
91591
+ }
91592
+ };
91593
+ }
91594
+ function validateActionGate(node3, nodeIndex) {
91595
+ if (node3.action_probe?.has_steps_or_phases !== true) {
91596
+ reject(`nodes[${nodeIndex}].action_probe.has_steps_or_phases`, "node_type=action requires action_probe.has_steps_or_phases=true; CLI does not auto-downgrade invalid Action nodes to entity", {
91597
+ hintCode: "align-action-gate-invalid",
91598
+ reasonCode: "align-action-gate-invalid",
91599
+ schemaLookup: "context schema align-structure-intent --view minimal --format json",
91600
+ repairOptions: gateRepairOptions("action"),
91601
+ diagnostics: {
91602
+ missing_or_invalid: ["action_probe.has_steps_or_phases"],
91603
+ submitted_node_type: "action",
91604
+ auto_downgrade: false
91605
+ }
91606
+ });
91607
+ }
91608
+ const gate = node3.action_gate;
91609
+ if (gate === undefined) {
91610
+ reject(`nodes[${nodeIndex}].action_gate`, "node_type=action requires action_gate.inference_sources; CLI does not auto-downgrade invalid Action nodes to entity", {
91611
+ hintCode: "align-action-gate-invalid",
91612
+ reasonCode: "align-action-gate-invalid",
91613
+ schemaLookup: "context schema align-structure-intent --view minimal --format json",
91614
+ repairOptions: gateRepairOptions("action"),
91615
+ diagnostics: {
91616
+ missing_or_invalid: ["action_gate.inference_sources"],
91617
+ submitted_node_type: "action",
91618
+ auto_downgrade: false
91619
+ }
91620
+ });
91621
+ }
91622
+ validateInferenceSources(gate, `nodes[${nodeIndex}].action_gate`);
91623
+ }
90943
91624
  function normalizeNodes(nodes, refs, allSlugs, previousTypes) {
90944
91625
  const warnings = [];
90945
91626
  const normalized = nodes.map((node3, index2) => {
@@ -90956,46 +91637,10 @@ function normalizeNodes(nodes, refs, allSlugs, previousTypes) {
90956
91637
  });
90957
91638
  }
90958
91639
  if (next.node_type === "domain") {
90959
- const gate = next.domain_gate;
90960
- const rawChildRefs = Array.isArray(gate?.child_refs) ? gate.child_refs : undefined;
90961
- const childRefs = rawChildRefs?.map((ref) => typeof ref === "string" ? ref.trim() : "") ?? [];
90962
- const validGate = gate !== undefined && Array.isArray(gate.scope_blocks) && rawChildRefs !== undefined && typeof gate.grouping_reason === "string" && childRefs.length === rawChildRefs.length && childRefs.every((ref) => ref.length > 0 && (refs.has(ref) || allSlugs.has(ref)));
90963
- if (!validGate) {
90964
- const downgraded = downgradeNode(next, "domain_downgrade", "domain_gate is missing or references unresolved child refs");
90965
- next = downgraded.node;
90966
- warnings.push(downgraded.warning);
90967
- } else {
90968
- const canonicalChildRefs = childRefs.map((ref) => refs.get(ref) ?? ref);
90969
- const duplicateChildRef = canonicalChildRefs.find((ref, refIndex) => canonicalChildRefs.indexOf(ref) !== refIndex);
90970
- if (duplicateChildRef !== undefined) {
90971
- reject(`nodes[${index2}].domain_gate.child_refs`, `domain_gate.child_refs contains duplicate child "${duplicateChildRef}"`, {
90972
- reasonCode: "duplicate-domain-child-ref",
90973
- failedRef: duplicateChildRef,
90974
- availableNodeRefs: nodeRefsForHint(refs),
90975
- availableNodeSlugs: [...allSlugs]
90976
- });
90977
- }
90978
- next = {
90979
- ...next,
90980
- domain_gate: {
90981
- ...gate,
90982
- child_refs: canonicalChildRefs
90983
- }
90984
- };
90985
- }
91640
+ next = normalizeDomainGate({ node: next, nodeIndex: index2, refs, allSlugs });
90986
91641
  }
90987
91642
  if (next.node_type === "action") {
90988
- const reason = downgradeReason(next);
90989
- if (reason !== null) {
90990
- const downgraded = downgradeNode(next, "action_downgrade", reason);
90991
- next = downgraded.node;
90992
- warnings.push(downgraded.warning);
90993
- } else {
90994
- const gate = next.action_gate;
90995
- if (gate === undefined)
90996
- reject(`nodes[${index2}].action_gate`, "action_gate is required");
90997
- validateInferenceSources(gate, `nodes[${index2}].action_gate`);
90998
- }
91643
+ validateActionGate(next, index2);
90999
91644
  }
91000
91645
  const previousType = previousTypes.get(next.slug);
91001
91646
  if (previousType !== undefined && previousType !== next.node_type) {
@@ -91075,7 +91720,7 @@ function normalizeSections(value, refs, currentSlugs) {
91075
91720
  return value.map((raw, index2) => {
91076
91721
  if (!isRecord18(raw))
91077
91722
  reject(`sections[${index2}]`, "section must be an object");
91078
- const rawOwner = stringValue(raw.owner);
91723
+ const rawOwner = stringValue2(raw.owner);
91079
91724
  if (rawOwner === undefined)
91080
91725
  reject(`sections[${index2}].owner`, `sections[${index2}].owner is required`);
91081
91726
  const owner = refs.get(rawOwner);
@@ -91094,9 +91739,9 @@ function normalizeSections(value, refs, currentSlugs) {
91094
91739
  availableNodeSlugs: [...currentSlugs]
91095
91740
  });
91096
91741
  }
91097
- const rationale = stringValue(raw.rationale);
91742
+ const rationale = stringValue2(raw.rationale);
91098
91743
  return {
91099
- section_id: stringValue(raw.section_id) ?? `planned_section_${index2 + 1}`,
91744
+ section_id: stringValue2(raw.section_id) ?? `planned_section_${index2 + 1}`,
91100
91745
  owner,
91101
91746
  section_kind: raw.section_kind,
91102
91747
  block_ids: stringArray2(raw.block_ids),
@@ -91114,8 +91759,8 @@ function normalizeEdges(value, refs, slugs) {
91114
91759
  if (raw.edge_type !== "depends_on" && raw.type !== "depends_on") {
91115
91760
  rejectLegacy(`edges[${index2}].edge_type`, `document edge type must be depends_on; allowed runtime EdgeType values are ${EDGE_TYPES.join("|")}`);
91116
91761
  }
91117
- const from = resolveRef2(refs, stringValue(raw.from_ref) ?? stringValue(raw.from), `edges[${index2}].from_ref`);
91118
- const to = resolveRef2(refs, stringValue(raw.to_ref) ?? stringValue(raw.to), `edges[${index2}].to_ref`);
91762
+ const from = resolveRef2(refs, stringValue2(raw.from_ref) ?? stringValue2(raw.from), `edges[${index2}].from_ref`);
91763
+ const to = resolveRef2(refs, stringValue2(raw.to_ref) ?? stringValue2(raw.to), `edges[${index2}].to_ref`);
91119
91764
  if (!from || !to || !slugs.has(from) || !slugs.has(to)) {
91120
91765
  reject(`edges[${index2}]`, "edge endpoints must reference finalized nodes", {
91121
91766
  reasonCode: "unknown-edge-endpoint",
@@ -91123,10 +91768,10 @@ function normalizeEdges(value, refs, slugs) {
91123
91768
  availableNodeSlugs: [...slugs]
91124
91769
  });
91125
91770
  }
91126
- const fromRef = stringValue(raw.from_ref);
91127
- const toRef = stringValue(raw.to_ref);
91128
- const confidence = stringValue(raw.confidence);
91129
- const rationale = stringValue(raw.rationale);
91771
+ const fromRef = stringValue2(raw.from_ref);
91772
+ const toRef = stringValue2(raw.to_ref);
91773
+ const confidence = stringValue2(raw.confidence);
91774
+ const rationale = stringValue2(raw.rationale);
91130
91775
  return {
91131
91776
  edge_type: "depends_on",
91132
91777
  from,
@@ -91225,7 +91870,7 @@ function normalizeAlignStructureDecision(input) {
91225
91870
  });
91226
91871
  const unresolved = normalizeUnresolved(input.payload.unresolved);
91227
91872
  validateUnresolvedQuestions({ blockOwnership, unresolved, reject });
91228
- const artifactKind = stringValue(input.payload.artifact_kind);
91873
+ const artifactKind = stringValue2(input.payload.artifact_kind);
91229
91874
  const auditWarnings = Array.isArray(input.payload.audit_warnings) ? input.payload.audit_warnings.filter((warning) => isRecord18(warning) && typeof warning.kind === "string" && typeof warning.reason === "string") : [];
91230
91875
  return {
91231
91876
  schema_version: ALIGN_STRUCTURE_DECISION_SCHEMA_VERSION,
@@ -91258,16 +91903,16 @@ var CITABLE_OWNERSHIP_ROLES = new Set(["owned", "shared"]);
91258
91903
  function isRecord40(value) {
91259
91904
  return typeof value === "object" && value !== null && !Array.isArray(value);
91260
91905
  }
91261
- function stringValue5(value) {
91906
+ function stringValue6(value) {
91262
91907
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
91263
91908
  }
91264
91909
  function stringArray6(value) {
91265
91910
  return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim()) : [];
91266
91911
  }
91267
91912
  function normalizedNodeSlug(rawNode) {
91268
- const rawSlug = stringValue5(rawNode.slug);
91269
- const rawHint = stringValue5(rawNode.llm_slug_hint);
91270
- const slugBase = rawSlug ?? (rawHint !== undefined ? rawHint.replace(/^local:/u, "") : undefined) ?? stringValue5(rawNode.title);
91913
+ const rawSlug = stringValue6(rawNode.slug);
91914
+ const rawHint = stringValue6(rawNode.llm_slug_hint);
91915
+ const slugBase = rawSlug ?? (rawHint !== undefined ? rawHint.replace(/^local:/u, "") : undefined) ?? stringValue6(rawNode.title);
91271
91916
  if (slugBase === undefined)
91272
91917
  return;
91273
91918
  const slug = rawSlug !== undefined ? rawSlug.split("/").map((part) => slugify(part)).filter(Boolean).join("/") : slugify(slugBase);
@@ -91296,7 +91941,7 @@ function nodeReferenceIndex(rawDecision, context) {
91296
91941
  continue;
91297
91942
  slugs.add(slug);
91298
91943
  setRef2(slug, slug);
91299
- setRef2(stringValue5(rawNode.llm_slug_hint), slug);
91944
+ setRef2(stringValue6(rawNode.llm_slug_hint), slug);
91300
91945
  }
91301
91946
  return { refs, slugs };
91302
91947
  }
@@ -91371,8 +92016,8 @@ function ownershipRolesByBlock(rawDecision, context) {
91371
92016
  for (const raw of ownershipInput) {
91372
92017
  if (!isRecord40(raw))
91373
92018
  continue;
91374
- const blockId = stringValue5(raw.block_id);
91375
- const role = stringValue5(raw.ownership_role);
92019
+ const blockId = stringValue6(raw.block_id);
92020
+ const role = stringValue6(raw.ownership_role);
91376
92021
  if (blockId !== undefined && role !== undefined && ["owned", "shared", "context_only", "ignored", "unresolved"].includes(role)) {
91377
92022
  roles.set(blockId, role);
91378
92023
  }
@@ -91404,7 +92049,7 @@ function collectSectionIssues(rawDecision, context, issues, ownershipRoles) {
91404
92049
  issues.push({
91405
92050
  path: `sections[${index2}].block_ids`,
91406
92051
  reason_code: "non-coverable-block",
91407
- message: `section "${stringValue5(rawSection.section_id) ?? index2}" includes non-coverable block_ids`,
92052
+ message: `section "${stringValue6(rawSection.section_id) ?? index2}" includes non-coverable block_ids`,
91408
92053
  diagnostics: citationEligibilityDiagnostics(blockIds, context.segments, citationEligible)
91409
92054
  });
91410
92055
  return;
@@ -91413,7 +92058,7 @@ function collectSectionIssues(rawDecision, context, issues, ownershipRoles) {
91413
92058
  issues.push({
91414
92059
  path: `sections[${index2}].block_ids`,
91415
92060
  reason_code: nonCitable.length === blockIds.length ? "section-plan-no-citable-blocks" : "section-plan-non-citable-blocks",
91416
- message: nonCitable.length === blockIds.length ? `section "${stringValue5(rawSection.section_id) ?? index2}" has no citation-eligible block_ids after excluding supporting context` : `section "${stringValue5(rawSection.section_id) ?? index2}" includes supporting-context block_ids that cannot support citations`,
92061
+ message: nonCitable.length === blockIds.length ? `section "${stringValue6(rawSection.section_id) ?? index2}" has no citation-eligible block_ids after excluding supporting context` : `section "${stringValue6(rawSection.section_id) ?? index2}" includes supporting-context block_ids that cannot support citations`,
91417
92062
  diagnostics: citationEligibilityDiagnostics(blockIds, context.segments, citationEligible)
91418
92063
  });
91419
92064
  return;
@@ -91426,8 +92071,8 @@ function collectOwnershipIssues(rawDecision, context, issues, nodeRefs) {
91426
92071
  ownership.forEach((raw, index2) => {
91427
92072
  if (!isRecord40(raw))
91428
92073
  return;
91429
- const blockId = stringValue5(raw.block_id);
91430
- const role = stringValue5(raw.ownership_role);
92074
+ const blockId = stringValue6(raw.block_id);
92075
+ const role = stringValue6(raw.ownership_role);
91431
92076
  if (blockId !== undefined && !coverable.has(blockId)) {
91432
92077
  issues.push({
91433
92078
  path: `block_ownership[${index2}].block_id`,
@@ -91465,7 +92110,7 @@ function collectSupplementalIssues(rawDecision, context) {
91465
92110
  for (const [index2, rawNode] of (Array.isArray(rawDecision.nodes) ? rawDecision.nodes : []).entries()) {
91466
92111
  if (!isRecord40(rawNode))
91467
92112
  continue;
91468
- const nodeType = stringValue5(rawNode.node_type);
92113
+ const nodeType = stringValue6(rawNode.node_type);
91469
92114
  if (nodeType !== undefined && NODE_TYPES.includes(nodeType) && Array.isArray(rawNode.planned_sections)) {
91470
92115
  for (const kind of stringArray6(rawNode.planned_sections)) {
91471
92116
  if (!isSectionKindMountable(nodeType, kind)) {
@@ -91497,17 +92142,17 @@ function isAlignStructureIntentPayload(value) {
91497
92142
  return isRecord18(value) && value.schema_version === ALIGN_STRUCTURE_INTENT_SCHEMA_VERSION;
91498
92143
  }
91499
92144
  function stableNodeSlug(raw) {
91500
- const rawSlug = stringValue(raw.slug);
92145
+ const rawSlug = stringValue2(raw.slug);
91501
92146
  if (rawSlug !== undefined)
91502
92147
  return rawSlug.split("/").map((part) => slugify(part)).filter(Boolean).join("/");
91503
- const hint = stringValue(raw.llm_slug_hint);
92148
+ const hint = stringValue2(raw.llm_slug_hint);
91504
92149
  if (hint !== undefined)
91505
92150
  return slugify(hint.replace(/^local:/u, ""));
91506
- const title = stringValue(raw.title);
92151
+ const title = stringValue2(raw.title);
91507
92152
  return title !== undefined ? slugify(title) : undefined;
91508
92153
  }
91509
92154
  function nodeRefs(raw) {
91510
- return [stableNodeSlug(raw), stringValue(raw.slug), stringValue(raw.llm_slug_hint)].filter((value) => value !== undefined && value.length > 0);
92155
+ return [stableNodeSlug(raw), stringValue2(raw.slug), stringValue2(raw.llm_slug_hint)].filter((value) => value !== undefined && value.length > 0);
91511
92156
  }
91512
92157
  function distinctStrings(values2) {
91513
92158
  const seen = new Set;
@@ -91584,8 +92229,8 @@ function compileSections(input) {
91584
92229
  });
91585
92230
  }
91586
92231
  }
91587
- const owner = stringValue(group.owner);
91588
- const kind = stringValue(group.section_kind);
92232
+ const owner = stringValue2(group.owner);
92233
+ const kind = stringValue2(group.section_kind);
91589
92234
  if (owner !== undefined && kind !== undefined) {
91590
92235
  const existing = sectionsByOwner.get(owner) ?? [];
91591
92236
  existing.push(kind);
@@ -91610,7 +92255,7 @@ function compileSections(input) {
91610
92255
  section_kind: kind,
91611
92256
  block_ids: blockIds,
91612
92257
  ...Array.isArray(group.refers_to_nodes) ? { refers_to_nodes: distinctStrings(stringArray2(group.refers_to_nodes)) } : {},
91613
- ...stringValue(group.rationale) !== undefined ? { rationale: stringValue(group.rationale) } : {}
92258
+ ...stringValue2(group.rationale) !== undefined ? { rationale: stringValue2(group.rationale) } : {}
91614
92259
  };
91615
92260
  });
91616
92261
  const nodes = rawNodes.map((node3, index2) => {
@@ -91672,7 +92317,7 @@ function throwIntentIssues(issues) {
91672
92317
  throwStructureIssues(issues.map(withIntentIssueContext));
91673
92318
  }
91674
92319
  function roleOf(record, block, applyDefaultDemotion = false) {
91675
- const role = stringValue(record?.ownership_role);
92320
+ const role = stringValue2(record?.ownership_role);
91676
92321
  if (applyDefaultDemotion && (role === "owned" || role === "shared") && block !== undefined) {
91677
92322
  return defaultOwnershipRoleForStructuralRole(block.structural_role) ?? role;
91678
92323
  }
@@ -91695,6 +92340,7 @@ function compileOwnership(input) {
91695
92340
  }
91696
92341
  const sourceDefaults = new Map;
91697
92342
  const groupExplicit = new Map;
92343
+ const ownershipNoopGroups = [];
91698
92344
  groups.forEach((group, index2) => {
91699
92345
  const scope = isRecord18(group.scope) ? group.scope : undefined;
91700
92346
  if (scope === undefined) {
@@ -91706,8 +92352,8 @@ function compileOwnership(input) {
91706
92352
  return;
91707
92353
  }
91708
92354
  const blockIds = stringArray2(scope.block_ids);
91709
- const sourceId = stringValue(scope.source_id);
91710
- const structuralRole = stringValue(scope.structural_role);
92355
+ const sourceId = stringValue2(scope.source_id);
92356
+ const structuralRole = stringValue2(scope.structural_role);
91711
92357
  const hasBlockIds = blockIds.length > 0;
91712
92358
  const sourceOnly = sourceId !== undefined && structuralRole === undefined && !hasBlockIds;
91713
92359
  const sourceRole = sourceId !== undefined && structuralRole !== undefined && !hasBlockIds;
@@ -91746,6 +92392,17 @@ function compileOwnership(input) {
91746
92392
  }
91747
92393
  const selected = explicitBlocks ? blockIds.map((blockId) => blockById2.get(blockId)).filter((block) => block !== undefined) : (blocksBySource.get(sourceId) ?? []).filter((block) => block.structural_role === structuralRole);
91748
92394
  if (selected.length === 0) {
92395
+ if (sourceRole && defaultOwnershipRoleForStructuralRole(structuralRole) !== undefined) {
92396
+ ownershipNoopGroups.push({
92397
+ index: index2,
92398
+ source_id: sourceId,
92399
+ structural_role: structuralRole,
92400
+ reason_code: "align-intent-ownership-scope-redundant",
92401
+ message: "No matching coverable blocks remain for this structural role; the source-wide default/automatic ownership policy already handles this non-content role when present.",
92402
+ next_action: "Remove this ownership_groups[] entry unless you need an explicit block_ownership[] override for a specific block."
92403
+ });
92404
+ return;
92405
+ }
91749
92406
  input.issues.push({
91750
92407
  path: `ownership_groups[${index2}].scope`,
91751
92408
  message: "ownership group scope matched no coverable blocks",
@@ -91794,7 +92451,7 @@ function compileOwnership(input) {
91794
92451
  finalRoles.set(blockId, roleOf(entry.record, block));
91795
92452
  }
91796
92453
  for (const patch of explicitPatches) {
91797
- const blockId = stringValue(patch.block_id);
92454
+ const blockId = stringValue2(patch.block_id);
91798
92455
  if (blockId !== undefined)
91799
92456
  finalRoles.set(blockId, roleOf(patch, blockById2.get(blockId)));
91800
92457
  }
@@ -91802,6 +92459,7 @@ function compileOwnership(input) {
91802
92459
  blockOwnershipDefaults: defaults,
91803
92460
  blockOwnership: [...groupExplicitRows, ...explicitPatches],
91804
92461
  ownershipGroupCount: groups.length,
92462
+ ownershipNoopGroups,
91805
92463
  finalRoles
91806
92464
  };
91807
92465
  }
@@ -91916,8 +92574,327 @@ function compileAlignStructureIntent(input) {
91916
92574
  section_groups: sections.sectionGroupCount,
91917
92575
  ownership_groups: ownership.ownershipGroupCount,
91918
92576
  ownership_defaults: ownership.blockOwnershipDefaults.length,
91919
- ownership_exceptions: ownership.blockOwnership.length
92577
+ ownership_exceptions: ownership.blockOwnership.length,
92578
+ ...ownership.ownershipNoopGroups.length > 0 ? { ownership_noop_groups: ownership.ownershipNoopGroups } : {}
92579
+ }
92580
+ };
92581
+ }
92582
+ // src/commands/workflowAlignEnvelope.ts
92583
+ init_currentWorkflow();
92584
+ init_nextActionEnvelope();
92585
+ var ALIGN_FINALIZE_COMMAND = "context align finalize --input - --format json";
92586
+ var ALIGN_VALIDATE_COMMAND2 = "context align validate --input - --format json";
92587
+ var ALIGN_COARSE_READ_COMMAND2 = "context align coarse-read --input - --format json";
92588
+ var ALIGN_CANDIDATE_OPS_COMMAND = "context align ops --input - --format json";
92589
+ var ALIGN_RESCAN_COMMAND = "context align scan --format json";
92590
+ var COMPILE_SCAN_COMMAND2 = "context compile scan --format json";
92591
+ var ALIGN_READ_PLAN_COMMAND = "context workflow show --payload align-segments --view read-plan --unwrap --format json";
92592
+ var ALIGN_SOURCE_BUNDLE_COMMAND = "context workflow show --payload align-segments --view source-bundle --unwrap --format text";
92593
+ function alignWorkflowEnvelopeContext(state, digest2) {
92594
+ return {
92595
+ id: state.workflow_id,
92596
+ workflow_id: state.workflow_id,
92597
+ family: state.family,
92598
+ stage: state.stage,
92599
+ terminal: state.stage === "finalized" || state.stage === "closed" || state.stage === "abandoned",
92600
+ scope_id: workflowScope(state),
92601
+ ...digest2 !== undefined ? { digest: digest2 } : {}
92602
+ };
92603
+ }
92604
+ function alignRouteId(route) {
92605
+ return route.mode;
92606
+ }
92607
+ function routeReasonBreach(threshold) {
92608
+ if (threshold.value > threshold.recommended_max)
92609
+ return "recommended_max";
92610
+ if (threshold.value > threshold.direct_max)
92611
+ return "direct_max";
92612
+ return;
92613
+ }
92614
+ function routeReason(indicator, threshold) {
92615
+ const breach = routeReasonBreach(threshold);
92616
+ if (breach === undefined)
92617
+ return;
92618
+ return {
92619
+ indicator,
92620
+ value: threshold.value,
92621
+ direct_max: threshold.direct_max,
92622
+ recommended_max: threshold.recommended_max,
92623
+ breach
92624
+ };
92625
+ }
92626
+ function alignRouteSummary(route) {
92627
+ return {
92628
+ id: alignRouteId(route),
92629
+ hard_gate: route.hard_gate,
92630
+ reasons: Object.entries(route.thresholds).map(([indicator, threshold]) => routeReason(indicator, threshold)).filter((reason) => reason !== undefined)
92631
+ };
92632
+ }
92633
+ function alignSegmentsViews() {
92634
+ return [
92635
+ {
92636
+ id: "read-plan",
92637
+ purpose: "Read the compact align reading plan and follow its single next_action command.",
92638
+ evidence_role: "primary",
92639
+ expected: true,
92640
+ budget_safety: "compact",
92641
+ command: ALIGN_READ_PLAN_COMMAND
92642
+ },
92643
+ {
92644
+ id: "source-bundle",
92645
+ purpose: "Read the near-source text bundle only when read-plan recommends it.",
92646
+ evidence_role: "primary",
92647
+ expected: false,
92648
+ budget_safety: "paged",
92649
+ command: ALIGN_SOURCE_BUNDLE_COMMAND
92650
+ },
92651
+ {
92652
+ id: "blocks",
92653
+ purpose: "Drill into paged align block JSON only when read-plan or source-bundle asks for a scoped fallback.",
92654
+ evidence_role: "primary",
92655
+ expected: false,
92656
+ budget_safety: "paged",
92657
+ command: "context workflow show --payload align-segments --view blocks --page-size 10 --token-budget 8000 --unwrap --format json"
92658
+ },
92659
+ {
92660
+ id: "block-index",
92661
+ purpose: "List block ids, ordinals, structural roles, and heading paths without text.",
92662
+ evidence_role: "supporting",
92663
+ expected: false,
92664
+ budget_safety: "compact",
92665
+ command: "context workflow show --payload align-segments --view block-index --unwrap --format json"
92666
+ },
92667
+ {
92668
+ id: "source-mapping",
92669
+ purpose: "Inspect source to block mapping without full block text.",
92670
+ evidence_role: "supporting",
92671
+ expected: false,
92672
+ budget_safety: "compact",
92673
+ command: "context workflow show --payload align-segments --view source-mapping --unwrap --format json"
92674
+ },
92675
+ {
92676
+ id: "pending-relation-refs",
92677
+ purpose: "Inspect explicit Parent/Children/Related markdown relation refs before deciding contains_parent or domain child refs.",
92678
+ evidence_role: "supporting",
92679
+ expected: false,
92680
+ budget_safety: "compact",
92681
+ command: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92682
+ },
92683
+ {
92684
+ id: "windows",
92685
+ purpose: "Page source windows to choose narrower block reads for large sources.",
92686
+ evidence_role: "supporting",
92687
+ expected: false,
92688
+ budget_safety: "paged",
92689
+ command: "context workflow show --payload align-segments --view windows --page-size 10 --compact-hints --unwrap --format json"
92690
+ },
92691
+ {
92692
+ id: "segment",
92693
+ purpose: "Read compact align segment summary and route metadata.",
92694
+ evidence_role: "diagnostic",
92695
+ expected: false,
92696
+ budget_safety: "compact",
92697
+ command: "context workflow show --payload align-segments --view segment --unwrap --format json"
91920
92698
  }
92699
+ ];
92700
+ }
92701
+ function alignInspectCommands() {
92702
+ return {
92703
+ read_plan: ALIGN_READ_PLAN_COMMAND,
92704
+ summary: "context workflow show --payload align-segments --view segment --unwrap --format json",
92705
+ pending_relation_refs: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92706
+ };
92707
+ }
92708
+ function alignInspectCommandTemplates() {
92709
+ return {
92710
+ source_bundle: ALIGN_SOURCE_BUNDLE_COMMAND,
92711
+ source_pending_relation_refs: "context workflow show --payload align-segments --view pending-relation-refs --source <source-id> --unwrap --format json",
92712
+ source_block_index: "context workflow show --payload align-segments --view block-index --source <source-id> --unwrap --format json",
92713
+ heading_block_index: "context workflow show --payload align-segments --view block-index --heading <heading-prefix> --unwrap --format json",
92714
+ source_blocks: "context workflow show --payload align-segments --view blocks --source <source-id> --page-size 10 --token-budget 8000 --unwrap --format json",
92715
+ heading_blocks: "context workflow show --payload align-segments --view blocks --heading <heading-prefix> --page-size 10 --token-budget 8000 --unwrap --format json",
92716
+ block_detail: "context workflow show --payload align-segments --view blocks --window <window-id|src-N:M[,selector...]> --page-size 10 --token-budget 8000 --unwrap --format json"
92717
+ };
92718
+ }
92719
+ function classifyAlignWindow(input) {
92720
+ if (input.tokenEstimate > 8000 || input.blockCount > 30 || input.multiSubsection)
92721
+ return "complex";
92722
+ if (input.tokenEstimate > 3000 || input.blockCount > 12)
92723
+ return "moderate";
92724
+ return "simple";
92725
+ }
92726
+ function readStrategyForComplexity(complexity) {
92727
+ if (complexity === "complex")
92728
+ return "drill_by_window_or_heading_before_deciding_structure";
92729
+ if (complexity === "moderate")
92730
+ return "read_budgeted_blocks_then_expand_selected_windows";
92731
+ return "read_budgeted_blocks_directly";
92732
+ }
92733
+ function alignSourceComplexitySummaries(segments) {
92734
+ const coverableBlockIds = new Set(segments.coverage.coverable_block_ids);
92735
+ return segments.sources.map((source2) => {
92736
+ const coverableBlocks2 = source2.blocks.filter((block) => coverableBlockIds.has(block.block_id));
92737
+ const largestWindowTokens = source2.windows.reduce((max, window2) => Math.max(max, window2.token_estimate), 0);
92738
+ const sourceComplexity = source2.windows.some((window2) => classifyAlignWindow({
92739
+ tokenEstimate: window2.token_estimate,
92740
+ blockCount: window2.block_ids.length,
92741
+ multiSubsection: window2.multi_subsection === true
92742
+ }) === "complex") || source2.windows.length > 6 || coverableBlocks2.length > 50 ? "complex" : source2.windows.some((window2) => classifyAlignWindow({
92743
+ tokenEstimate: window2.token_estimate,
92744
+ blockCount: window2.block_ids.length,
92745
+ multiSubsection: window2.multi_subsection === true
92746
+ }) === "moderate") || source2.windows.length > 3 || coverableBlocks2.length > 20 ? "moderate" : "simple";
92747
+ return {
92748
+ source_id: source2.source_id,
92749
+ block_count: source2.blocks.length,
92750
+ coverable_block_count: coverableBlocks2.length,
92751
+ window_count: source2.windows.length,
92752
+ total_tokens: source2.total_tokens,
92753
+ largest_window_tokens: largestWindowTokens,
92754
+ complexity_class: sourceComplexity,
92755
+ suggested_read_strategy: readStrategyForComplexity(sourceComplexity),
92756
+ windows: source2.windows.map((window2) => {
92757
+ const complexity = classifyAlignWindow({
92758
+ tokenEstimate: window2.token_estimate,
92759
+ blockCount: window2.block_ids.length,
92760
+ multiSubsection: window2.multi_subsection === true
92761
+ });
92762
+ return {
92763
+ window_id: window2.window_id,
92764
+ block_count: window2.block_ids.length,
92765
+ token_estimate: window2.token_estimate,
92766
+ line_start: window2.line_start,
92767
+ line_end: window2.line_end,
92768
+ heading_path: window2.heading_path,
92769
+ complexity_class: complexity,
92770
+ suggested_read_strategy: readStrategyForComplexity(complexity)
92771
+ };
92772
+ })
92773
+ };
92774
+ });
92775
+ }
92776
+ function pendingRelationRefsCount2(segments) {
92777
+ return segments.sources.reduce((sum, source2) => sum + (source2.pending_relation_refs?.length ?? 0), 0);
92778
+ }
92779
+ function alignComplexityDiagnostics(input) {
92780
+ const automaticOwnershipAdjustments = automaticOwnershipAdjustmentCandidates(input.segments);
92781
+ const relationRefsCount = pendingRelationRefsCount2(input.segments);
92782
+ return {
92783
+ summary: {
92784
+ route_mode: input.route.mode,
92785
+ complexity: input.route.complexity,
92786
+ source_count: input.route.thresholds.source_count.value,
92787
+ coverable_block_count: input.route.thresholds.coverable_block_count.value,
92788
+ estimated_coverable_tokens: input.route.thresholds.estimated_coverable_tokens.value,
92789
+ largest_window_tokens: input.route.thresholds.largest_window_tokens.value,
92790
+ estimated_response_chars: input.route.thresholds.estimated_response_chars.value,
92791
+ windows: input.segments.sources.reduce((sum, source2) => sum + source2.windows.length, 0),
92792
+ structural_changes: input.structuralChanges,
92793
+ content_only_changes: input.contentOnlyChanges,
92794
+ ...relationRefsCount > 0 ? { pending_relation_refs: relationRefsCount } : {}
92795
+ },
92796
+ ...relationRefsCount > 0 ? {
92797
+ warnings: [{
92798
+ code: "align-pending-relation-refs",
92799
+ severity: "info",
92800
+ message: `${relationRefsCount} explicit Parent/Children/Related markdown relation ref(s) were detected.`,
92801
+ detail_view_command: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92802
+ }]
92803
+ } : {},
92804
+ automatic_ownership_adjustments: compactAutomaticOwnershipAdjustments(automaticOwnershipAdjustments, {
92805
+ ...input.automaticOwnershipDetailCommand !== undefined ? { detailCommand: input.automaticOwnershipDetailCommand } : {}
92806
+ })
92807
+ };
92808
+ }
92809
+ function alignNextActionForRoute(input) {
92810
+ if (input.hasWork) {
92811
+ return {
92812
+ kind: "show_view",
92813
+ command: ALIGN_READ_PLAN_COMMAND,
92814
+ reason_code: `${input.route.mode}-read-plan`,
92815
+ blocking: true
92816
+ };
92817
+ }
92818
+ if (input.contentOnlyChanges > 0) {
92819
+ return {
92820
+ kind: "start_compile_scan",
92821
+ command: COMPILE_SCAN_COMMAND2,
92822
+ reason_code: "align-content-only-changes"
92823
+ };
92824
+ }
92825
+ return {
92826
+ kind: "stop_noop",
92827
+ reason_code: "align-no-structural-work"
92828
+ };
92829
+ }
92830
+ function alignAllowedActionsForNextAction(nextAction) {
92831
+ if (nextAction.kind === "show_view")
92832
+ return ["show_view"];
92833
+ if (nextAction.kind === "submit_structure_decision")
92834
+ return ["show_view", "submit_structure_decision"];
92835
+ if (nextAction.kind === "validate_align_decision")
92836
+ return ["show_view", "validate_align_decision"];
92837
+ if (nextAction.kind === "submit_coarse_read")
92838
+ return ["show_view", "submit_coarse_read"];
92839
+ if (nextAction.kind === "submit_candidate_ops")
92840
+ return ["show_view", "submit_candidate_ops"];
92841
+ if (nextAction.kind === "abandon_or_rescan")
92842
+ return ["show_view", "abandon", "rescan"];
92843
+ if (nextAction.kind === "start_compile_scan")
92844
+ return ["show_view"];
92845
+ return;
92846
+ }
92847
+ function createAlignRouteEnvelope(input) {
92848
+ const allowedActions = alignAllowedActionsForNextAction(input.nextAction);
92849
+ const views = input.nextAction.kind === "stop_noop" || input.nextAction.kind === "start_compile_scan" ? undefined : alignSegmentsViews();
92850
+ return createNextActionEnvelope({
92851
+ workflow: alignWorkflowEnvelopeContext(input.workflowState),
92852
+ route: alignRouteSummary(input.route),
92853
+ ...allowedActions !== undefined ? { allowed_actions: allowedActions } : {},
92854
+ next_action: input.nextAction,
92855
+ ...views !== undefined ? { views } : {},
92856
+ ...input.diagnostics !== undefined ? { diagnostics: input.diagnostics } : {}
92857
+ });
92858
+ }
92859
+ function alignDirectFinalizeNextAction(reasonCode = "align-route-direct-finalize", inputSchema = "align-structure-intent") {
92860
+ return {
92861
+ kind: "submit_structure_decision",
92862
+ command: ALIGN_FINALIZE_COMMAND,
92863
+ input_schema: inputSchema,
92864
+ reason_code: reasonCode,
92865
+ blocking: true
92866
+ };
92867
+ }
92868
+ function alignValidateNextAction(reasonCode = "align-validate-repair-required", inputSchema = "align-structure-intent") {
92869
+ return {
92870
+ kind: "validate_align_decision",
92871
+ command: ALIGN_VALIDATE_COMMAND2,
92872
+ input_schema: inputSchema,
92873
+ reason_code: reasonCode,
92874
+ blocking: true
92875
+ };
92876
+ }
92877
+ function alignBatchedNextAction(kind) {
92878
+ return kind === "submit_candidate_ops" ? {
92879
+ kind,
92880
+ command: ALIGN_CANDIDATE_OPS_COMMAND,
92881
+ input_schema: "align-candidate-ops",
92882
+ reason_code: "align-route-batched-review-required",
92883
+ blocking: true
92884
+ } : {
92885
+ kind,
92886
+ command: ALIGN_COARSE_READ_COMMAND2,
92887
+ input_schema: "align-coarse-read",
92888
+ reason_code: "align-route-batched-review-required",
92889
+ blocking: true
92890
+ };
92891
+ }
92892
+ function alignAbandonOrRescanNextAction(reasonCode) {
92893
+ return {
92894
+ kind: "abandon_or_rescan",
92895
+ command: ALIGN_RESCAN_COMMAND,
92896
+ reason_code: reasonCode,
92897
+ blocking: true
91921
92898
  };
91922
92899
  }
91923
92900
 
@@ -91970,7 +92947,7 @@ function unplannedEvidenceIssues(input) {
91970
92947
  reason_code: input.inputSchema === "align-structure-intent" ? "align-intent-unplanned-evidence-blocks" : "align-finalize-unplanned-evidence-blocks",
91971
92948
  message: `${unplanned.length} owned/shared citation evidence block(s) are not included in any planned Section.`,
91972
92949
  diagnostics: {
91973
- target_path: path13,
92950
+ target_field: path13,
91974
92951
  unplanned_evidence_block_ids: blockIds,
91975
92952
  unplanned_evidence_blocks: unplanned.slice(0, 12).map(unplannedEvidenceBlockContext),
91976
92953
  unplanned_evidence_blocks_omitted: Math.max(0, unplanned.length - 12),
@@ -92014,6 +92991,132 @@ function unplannedEvidenceBlockContext(block) {
92014
92991
  ...block.text_preview !== undefined ? { text_preview: block.text_preview } : {}
92015
92992
  };
92016
92993
  }
92994
+ function sameHeadingPath2(left, right) {
92995
+ return left.length === right.length && left.every((item, index2) => item === right[index2]);
92996
+ }
92997
+ function commonHeadingPrefix(groups) {
92998
+ if (groups.length === 0)
92999
+ return [];
93000
+ const first = groups[0].heading_path;
93001
+ const prefix = [];
93002
+ for (let index2 = 0;index2 < first.length; index2 += 1) {
93003
+ const value = first[index2];
93004
+ if (value === undefined || groups.some((group) => group.heading_path[index2] !== value))
93005
+ break;
93006
+ prefix.push(value);
93007
+ }
93008
+ return prefix;
93009
+ }
93010
+ function splitSectionPlanByHeadingPath(ownership, plan) {
93011
+ const blockById2 = new Map(ownership.sources.flatMap((source2) => source2.blocks.map((block) => [block.block_id, block])));
93012
+ const groups = [];
93013
+ for (const blockId of plan.block_ids) {
93014
+ const block = blockById2.get(blockId);
93015
+ if (block === undefined)
93016
+ continue;
93017
+ const previous3 = groups.at(-1);
93018
+ if (previous3 !== undefined && sameHeadingPath2(previous3.heading_path, block.heading_path)) {
93019
+ previous3.block_ids.push(blockId);
93020
+ if (previous3.line_range !== undefined)
93021
+ previous3.line_range[1] = block.line_end;
93022
+ continue;
93023
+ }
93024
+ groups.push({
93025
+ heading_path: [...block.heading_path],
93026
+ block_ids: [blockId],
93027
+ source_id: block.source_id,
93028
+ line_range: [block.line_start, block.line_end]
93029
+ });
93030
+ }
93031
+ return groups;
93032
+ }
93033
+ function sectionPlanCrossHeadingHints(input) {
93034
+ const spans = (input.ownership.section_plans ?? []).map((plan) => ({ plan, heading_groups: splitSectionPlanByHeadingPath(input.ownership, plan) })).filter((item) => item.heading_groups.length > 1);
93035
+ if (spans.length === 0)
93036
+ return [];
93037
+ const targetField = input.inputSchema === "align-structure-intent" ? "section_groups" : "sections";
93038
+ const classifiedSpans = spans.map((span) => ({
93039
+ ...span,
93040
+ shared_heading: commonHeadingPrefix(span.heading_groups)
93041
+ }));
93042
+ const examplesFor = (items, input2) => items.slice(0, 5).map(({ plan, heading_groups: headingGroups, shared_heading: sharedHeading }) => {
93043
+ return {
93044
+ section_id: plan.section_id,
93045
+ owner: plan.owner,
93046
+ section_kind: plan.section_kind,
93047
+ heading_group_count: headingGroups.length,
93048
+ ...sharedHeading.length > 0 ? { shared_heading: sharedHeading } : {},
93049
+ heading_groups: headingGroups.map((group) => ({
93050
+ heading_path: group.heading_path,
93051
+ block_ids: group.block_ids,
93052
+ ...group.source_id !== undefined ? { source_id: group.source_id } : {},
93053
+ ...group.line_range !== undefined ? { line_range: group.line_range } : {}
93054
+ })),
93055
+ ...input2.includeSplitPayload ? { suggested_split_payload: headingGroups.map((group) => ({
93056
+ owner: plan.owner,
93057
+ section_kind: plan.section_kind,
93058
+ block_ids: group.block_ids,
93059
+ rationale: `Evidence under ${group.heading_path.join(" > ") || "<root>"}.`
93060
+ })) } : {}
93061
+ };
93062
+ });
93063
+ const sharedParent = classifiedSpans.filter((item) => item.shared_heading.length > 0);
93064
+ const unrelated = classifiedSpans.filter((item) => item.shared_heading.length === 0);
93065
+ const hints = [];
93066
+ if (sharedParent.length > 0) {
93067
+ hints.push({
93068
+ code: "align-section-plan-crosses-headings",
93069
+ severity: "info",
93070
+ message: `${sharedParent.length} planned section(s) span sibling source headings under a shared parent heading. Semantic aggregation is allowed when the Section intentionally covers that parent topic.`,
93071
+ next_action: `Continue if each ${targetField} entry is one coherent semantic Section for the shared parent topic. Split only when the sibling headings should become independently drafted Sections.`,
93072
+ command: "context schema align-structure-intent --view minimal --format json",
93073
+ diagnostics: {
93074
+ section_count: sharedParent.length,
93075
+ target_field: targetField,
93076
+ heading_relationship: "shared_parent",
93077
+ examples: examplesFor(sharedParent, { includeSplitPayload: false }),
93078
+ examples_omitted: Math.max(0, sharedParent.length - 5)
93079
+ }
93080
+ });
93081
+ }
93082
+ if (unrelated.length > 0) {
93083
+ hints.push({
93084
+ code: "align-section-plan-crosses-headings",
93085
+ severity: "warning",
93086
+ message: `${unrelated.length} planned section(s) cross unrelated source heading boundaries. CLI will not rewrite the grouping; review whether this was intentional.`,
93087
+ next_action: `If accidental, split ${targetField} by the suggested heading groups and rerun align validate/finalize. If intentional, continue; compile source-refs will still expose separate draft templates for heading-boundary runs.`,
93088
+ command: "context schema align-structure-intent --view minimal --format json",
93089
+ diagnostics: {
93090
+ section_count: unrelated.length,
93091
+ target_field: targetField,
93092
+ heading_relationship: "unrelated_parent",
93093
+ examples: examplesFor(unrelated, { includeSplitPayload: true }),
93094
+ examples_omitted: Math.max(0, unrelated.length - 5)
93095
+ }
93096
+ });
93097
+ }
93098
+ return hints;
93099
+ }
93100
+ function sectionPlanAutoSplitAgentHints(ownership) {
93101
+ const splitPlans = (ownership.section_plans ?? []).filter((plan) => plan.split_reason !== undefined && typeof plan.origin_section_id === "string");
93102
+ if (splitPlans.length === 0)
93103
+ return [];
93104
+ const originSectionIds = [...new Set(splitPlans.map((plan) => plan.origin_section_id))].sort();
93105
+ const splitReasons = [...new Set(splitPlans.flatMap((plan) => plan.split_reason === undefined ? [] : [plan.split_reason]))].sort();
93106
+ return [{
93107
+ code: "align-section-plans-auto-split-contiguous-runs",
93108
+ severity: "info",
93109
+ message: `${originSectionIds.length} align planned section(s) will be split into ${splitPlans.length} draft-ready section plan(s) by citation continuity.`,
93110
+ next_action: "Continue. During compile, use the emitted section_plans/source-refs draft_action_templates as separate draft actions by default; origin_section_id preserves the original align grouping.",
93111
+ command: COMPILE_SCAN_COMMAND2,
93112
+ diagnostics: {
93113
+ origin_section_ids: originSectionIds,
93114
+ split_section_plan_count: originSectionIds.length,
93115
+ emitted_section_plan_count: splitPlans.length,
93116
+ split_reasons: splitReasons
93117
+ }
93118
+ }];
93119
+ }
92017
93120
  function agentHintsForCitationAdvisories(issues) {
92018
93121
  return issues.map((issue2) => ({
92019
93122
  code: issue2.code,
@@ -92027,40 +93130,6 @@ function agentHintsForCitationAdvisories(issues) {
92027
93130
  }
92028
93131
  function agentHintsForAuditWarnings(warnings) {
92029
93132
  return warnings.flatMap((warning) => {
92030
- if (warning.kind === "domain_downgrade") {
92031
- return [{
92032
- code: "align-domain-downgraded-to-entity",
92033
- severity: "warning",
92034
- message: `Node "${warning.node_slug ?? "<unknown>"}" was finalized as an entity because ${warning.reason}. context status counts finalized node types, not submitted proposals.`,
92035
- next_action: "Continue if an atomic placeholder/term is acceptable. If this should remain a Domain, revise domain_gate.child_refs to resolvable child Node slugs and rerun align validate/finalize.",
92036
- command: "context schema align-structure-intent --view minimal --format json",
92037
- ...warning.node_slug !== undefined ? { target_node: warning.node_slug } : {},
92038
- ...warning.evidence_blocks !== undefined ? { available_block_ids: warning.evidence_blocks } : {},
92039
- diagnostics: {
92040
- finalized_node_type: "entity",
92041
- status_count_source: "finalized_node_type",
92042
- reason: warning.reason,
92043
- ...warning.original_proposal !== undefined ? { original_proposal: warning.original_proposal } : {}
92044
- }
92045
- }];
92046
- }
92047
- if (warning.kind === "action_downgrade") {
92048
- return [{
92049
- code: "align-action-downgraded-to-entity",
92050
- severity: "warning",
92051
- message: `Node "${warning.node_slug ?? "<unknown>"}" was finalized as an entity because ${warning.reason}. context status counts finalized node types, not submitted proposals.`,
92052
- next_action: "Continue if the evidence describes a subject rather than a repeatable process. If this should remain an Action, add explicit action_probe/action_gate evidence and rerun align validate/finalize.",
92053
- command: "context schema align-structure-intent --view minimal --format json",
92054
- ...warning.node_slug !== undefined ? { target_node: warning.node_slug } : {},
92055
- ...warning.evidence_blocks !== undefined ? { available_block_ids: warning.evidence_blocks } : {},
92056
- diagnostics: {
92057
- finalized_node_type: "entity",
92058
- status_count_source: "finalized_node_type",
92059
- reason: warning.reason,
92060
- ...warning.original_proposal !== undefined ? { original_proposal: warning.original_proposal } : {}
92061
- }
92062
- }];
92063
- }
92064
93133
  if (warning.kind === "scope_name_entity_hint") {
92065
93134
  return [{
92066
93135
  code: "align-scope-name-entity-warning",
@@ -92335,6 +93404,8 @@ function validateAlignStructureDecisionWithContext(input) {
92335
93404
  const auditHints = built === undefined ? errorHints : [
92336
93405
  ...errorHints,
92337
93406
  ...canonicalDecisionDirectHint(input.rawDecision),
93407
+ ...sectionPlanAutoSplitAgentHints(built.ownership),
93408
+ ...sectionPlanCrossHeadingHints({ ownership: built.ownership, inputSchema: built.inputSchema }),
92338
93409
  ...agentHintsForAuditWarnings(built.decision.audit_warnings),
92339
93410
  ...agentHintsForCitationAdvisories(built.citationAdvisories),
92340
93411
  ...agentHintsForCliDemotions(cliDemotions)
@@ -92364,325 +93435,6 @@ function validateAlignStructureDecisionWithContext(input) {
92364
93435
  };
92365
93436
  }
92366
93437
 
92367
- // src/commands/workflowAlignEnvelope.ts
92368
- init_currentWorkflow();
92369
- init_nextActionEnvelope();
92370
- var ALIGN_FINALIZE_COMMAND = "context align finalize --input - --format json";
92371
- var ALIGN_VALIDATE_COMMAND2 = "context align validate --input - --format json";
92372
- var ALIGN_COARSE_READ_COMMAND2 = "context align coarse-read --input - --format json";
92373
- var ALIGN_CANDIDATE_OPS_COMMAND = "context align ops --input - --format json";
92374
- var ALIGN_RESCAN_COMMAND = "context align scan --format json";
92375
- var COMPILE_SCAN_COMMAND2 = "context compile scan --format json";
92376
- var ALIGN_READ_PLAN_COMMAND = "context workflow show --payload align-segments --view read-plan --unwrap --format json";
92377
- var ALIGN_SOURCE_BUNDLE_COMMAND = "context workflow show --payload align-segments --view source-bundle --unwrap --format text";
92378
- function alignWorkflowEnvelopeContext(state, digest2) {
92379
- return {
92380
- id: state.workflow_id,
92381
- workflow_id: state.workflow_id,
92382
- family: state.family,
92383
- stage: state.stage,
92384
- terminal: state.stage === "finalized" || state.stage === "closed" || state.stage === "abandoned",
92385
- scope_id: workflowScope(state),
92386
- ...digest2 !== undefined ? { digest: digest2 } : {}
92387
- };
92388
- }
92389
- function alignRouteId(route) {
92390
- return route.mode;
92391
- }
92392
- function routeReasonBreach(threshold) {
92393
- if (threshold.value > threshold.recommended_max)
92394
- return "recommended_max";
92395
- if (threshold.value > threshold.direct_max)
92396
- return "direct_max";
92397
- return;
92398
- }
92399
- function routeReason(indicator, threshold) {
92400
- const breach = routeReasonBreach(threshold);
92401
- if (breach === undefined)
92402
- return;
92403
- return {
92404
- indicator,
92405
- value: threshold.value,
92406
- direct_max: threshold.direct_max,
92407
- recommended_max: threshold.recommended_max,
92408
- breach
92409
- };
92410
- }
92411
- function alignRouteSummary(route) {
92412
- return {
92413
- id: alignRouteId(route),
92414
- hard_gate: route.hard_gate,
92415
- reasons: Object.entries(route.thresholds).map(([indicator, threshold]) => routeReason(indicator, threshold)).filter((reason) => reason !== undefined)
92416
- };
92417
- }
92418
- function alignSegmentsViews() {
92419
- return [
92420
- {
92421
- id: "read-plan",
92422
- purpose: "Read the compact align reading plan and follow its single next_action command.",
92423
- evidence_role: "primary",
92424
- expected: true,
92425
- budget_safety: "compact",
92426
- command: ALIGN_READ_PLAN_COMMAND
92427
- },
92428
- {
92429
- id: "source-bundle",
92430
- purpose: "Read the near-source text bundle only when read-plan recommends it.",
92431
- evidence_role: "primary",
92432
- expected: false,
92433
- budget_safety: "paged",
92434
- command: ALIGN_SOURCE_BUNDLE_COMMAND
92435
- },
92436
- {
92437
- id: "blocks",
92438
- purpose: "Drill into paged align block JSON only when read-plan or source-bundle asks for a scoped fallback.",
92439
- evidence_role: "primary",
92440
- expected: false,
92441
- budget_safety: "paged",
92442
- command: "context workflow show --payload align-segments --view blocks --page-size 10 --token-budget 8000 --unwrap --format json"
92443
- },
92444
- {
92445
- id: "block-index",
92446
- purpose: "List block ids, ordinals, structural roles, and heading paths without text.",
92447
- evidence_role: "supporting",
92448
- expected: false,
92449
- budget_safety: "compact",
92450
- command: "context workflow show --payload align-segments --view block-index --unwrap --format json"
92451
- },
92452
- {
92453
- id: "source-mapping",
92454
- purpose: "Inspect source to block mapping without full block text.",
92455
- evidence_role: "supporting",
92456
- expected: false,
92457
- budget_safety: "compact",
92458
- command: "context workflow show --payload align-segments --view source-mapping --unwrap --format json"
92459
- },
92460
- {
92461
- id: "pending-relation-refs",
92462
- purpose: "Inspect explicit Parent/Children/Related markdown relation refs before deciding contains_parent or domain child refs.",
92463
- evidence_role: "supporting",
92464
- expected: false,
92465
- budget_safety: "compact",
92466
- command: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92467
- },
92468
- {
92469
- id: "windows",
92470
- purpose: "Page source windows to choose narrower block reads for large sources.",
92471
- evidence_role: "supporting",
92472
- expected: false,
92473
- budget_safety: "paged",
92474
- command: "context workflow show --payload align-segments --view windows --page-size 10 --compact-hints --unwrap --format json"
92475
- },
92476
- {
92477
- id: "segment",
92478
- purpose: "Read compact align segment summary and route metadata.",
92479
- evidence_role: "diagnostic",
92480
- expected: false,
92481
- budget_safety: "compact",
92482
- command: "context workflow show --payload align-segments --view segment --unwrap --format json"
92483
- }
92484
- ];
92485
- }
92486
- function alignInspectCommands() {
92487
- return {
92488
- read_plan: ALIGN_READ_PLAN_COMMAND,
92489
- summary: "context workflow show --payload align-segments --view segment --unwrap --format json",
92490
- pending_relation_refs: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92491
- };
92492
- }
92493
- function alignInspectCommandTemplates() {
92494
- return {
92495
- source_bundle: ALIGN_SOURCE_BUNDLE_COMMAND,
92496
- source_pending_relation_refs: "context workflow show --payload align-segments --view pending-relation-refs --source <source-id> --unwrap --format json",
92497
- source_block_index: "context workflow show --payload align-segments --view block-index --source <source-id> --unwrap --format json",
92498
- heading_block_index: "context workflow show --payload align-segments --view block-index --heading <heading-prefix> --unwrap --format json",
92499
- source_blocks: "context workflow show --payload align-segments --view blocks --source <source-id> --page-size 10 --token-budget 8000 --unwrap --format json",
92500
- heading_blocks: "context workflow show --payload align-segments --view blocks --heading <heading-prefix> --page-size 10 --token-budget 8000 --unwrap --format json",
92501
- block_detail: "context workflow show --payload align-segments --view blocks --window <window-id|src-N:M[,selector...]> --page-size 10 --token-budget 8000 --unwrap --format json"
92502
- };
92503
- }
92504
- function classifyAlignWindow(input) {
92505
- if (input.tokenEstimate > 8000 || input.blockCount > 30 || input.multiSubsection)
92506
- return "complex";
92507
- if (input.tokenEstimate > 3000 || input.blockCount > 12)
92508
- return "moderate";
92509
- return "simple";
92510
- }
92511
- function readStrategyForComplexity(complexity) {
92512
- if (complexity === "complex")
92513
- return "drill_by_window_or_heading_before_deciding_structure";
92514
- if (complexity === "moderate")
92515
- return "read_budgeted_blocks_then_expand_selected_windows";
92516
- return "read_budgeted_blocks_directly";
92517
- }
92518
- function alignSourceComplexitySummaries(segments) {
92519
- const coverableBlockIds = new Set(segments.coverage.coverable_block_ids);
92520
- return segments.sources.map((source2) => {
92521
- const coverableBlocks2 = source2.blocks.filter((block) => coverableBlockIds.has(block.block_id));
92522
- const largestWindowTokens = source2.windows.reduce((max, window2) => Math.max(max, window2.token_estimate), 0);
92523
- const sourceComplexity = source2.windows.some((window2) => classifyAlignWindow({
92524
- tokenEstimate: window2.token_estimate,
92525
- blockCount: window2.block_ids.length,
92526
- multiSubsection: window2.multi_subsection === true
92527
- }) === "complex") || source2.windows.length > 6 || coverableBlocks2.length > 50 ? "complex" : source2.windows.some((window2) => classifyAlignWindow({
92528
- tokenEstimate: window2.token_estimate,
92529
- blockCount: window2.block_ids.length,
92530
- multiSubsection: window2.multi_subsection === true
92531
- }) === "moderate") || source2.windows.length > 3 || coverableBlocks2.length > 20 ? "moderate" : "simple";
92532
- return {
92533
- source_id: source2.source_id,
92534
- block_count: source2.blocks.length,
92535
- coverable_block_count: coverableBlocks2.length,
92536
- window_count: source2.windows.length,
92537
- total_tokens: source2.total_tokens,
92538
- largest_window_tokens: largestWindowTokens,
92539
- complexity_class: sourceComplexity,
92540
- suggested_read_strategy: readStrategyForComplexity(sourceComplexity),
92541
- windows: source2.windows.map((window2) => {
92542
- const complexity = classifyAlignWindow({
92543
- tokenEstimate: window2.token_estimate,
92544
- blockCount: window2.block_ids.length,
92545
- multiSubsection: window2.multi_subsection === true
92546
- });
92547
- return {
92548
- window_id: window2.window_id,
92549
- block_count: window2.block_ids.length,
92550
- token_estimate: window2.token_estimate,
92551
- line_start: window2.line_start,
92552
- line_end: window2.line_end,
92553
- heading_path: window2.heading_path,
92554
- complexity_class: complexity,
92555
- suggested_read_strategy: readStrategyForComplexity(complexity)
92556
- };
92557
- })
92558
- };
92559
- });
92560
- }
92561
- function pendingRelationRefsCount2(segments) {
92562
- return segments.sources.reduce((sum, source2) => sum + (source2.pending_relation_refs?.length ?? 0), 0);
92563
- }
92564
- function alignComplexityDiagnostics(input) {
92565
- const automaticOwnershipAdjustments = automaticOwnershipAdjustmentCandidates(input.segments);
92566
- const relationRefsCount = pendingRelationRefsCount2(input.segments);
92567
- return {
92568
- summary: {
92569
- route_mode: input.route.mode,
92570
- complexity: input.route.complexity,
92571
- source_count: input.route.thresholds.source_count.value,
92572
- coverable_block_count: input.route.thresholds.coverable_block_count.value,
92573
- estimated_coverable_tokens: input.route.thresholds.estimated_coverable_tokens.value,
92574
- largest_window_tokens: input.route.thresholds.largest_window_tokens.value,
92575
- estimated_response_chars: input.route.thresholds.estimated_response_chars.value,
92576
- windows: input.segments.sources.reduce((sum, source2) => sum + source2.windows.length, 0),
92577
- structural_changes: input.structuralChanges,
92578
- content_only_changes: input.contentOnlyChanges,
92579
- ...relationRefsCount > 0 ? { pending_relation_refs: relationRefsCount } : {}
92580
- },
92581
- ...relationRefsCount > 0 ? {
92582
- warnings: [{
92583
- code: "align-pending-relation-refs",
92584
- severity: "info",
92585
- message: `${relationRefsCount} explicit Parent/Children/Related markdown relation ref(s) were detected.`,
92586
- detail_view_command: "context workflow show --payload align-segments --view pending-relation-refs --unwrap --format json"
92587
- }]
92588
- } : {},
92589
- automatic_ownership_adjustments: compactAutomaticOwnershipAdjustments(automaticOwnershipAdjustments, {
92590
- ...input.automaticOwnershipDetailCommand !== undefined ? { detailCommand: input.automaticOwnershipDetailCommand } : {}
92591
- })
92592
- };
92593
- }
92594
- function alignNextActionForRoute(input) {
92595
- if (input.hasWork) {
92596
- return {
92597
- kind: "show_view",
92598
- command: ALIGN_READ_PLAN_COMMAND,
92599
- reason_code: `${input.route.mode}-read-plan`,
92600
- blocking: true
92601
- };
92602
- }
92603
- if (input.contentOnlyChanges > 0) {
92604
- return {
92605
- kind: "start_compile_scan",
92606
- command: COMPILE_SCAN_COMMAND2,
92607
- reason_code: "align-content-only-changes"
92608
- };
92609
- }
92610
- return {
92611
- kind: "stop_noop",
92612
- reason_code: "align-no-structural-work"
92613
- };
92614
- }
92615
- function alignAllowedActionsForNextAction(nextAction) {
92616
- if (nextAction.kind === "show_view")
92617
- return ["show_view"];
92618
- if (nextAction.kind === "submit_structure_decision")
92619
- return ["show_view", "submit_structure_decision"];
92620
- if (nextAction.kind === "validate_align_decision")
92621
- return ["show_view", "validate_align_decision"];
92622
- if (nextAction.kind === "submit_coarse_read")
92623
- return ["show_view", "submit_coarse_read"];
92624
- if (nextAction.kind === "submit_candidate_ops")
92625
- return ["show_view", "submit_candidate_ops"];
92626
- if (nextAction.kind === "abandon_or_rescan")
92627
- return ["show_view", "abandon", "rescan"];
92628
- if (nextAction.kind === "start_compile_scan")
92629
- return ["show_view"];
92630
- return;
92631
- }
92632
- function createAlignRouteEnvelope(input) {
92633
- const allowedActions = alignAllowedActionsForNextAction(input.nextAction);
92634
- const views = input.nextAction.kind === "stop_noop" || input.nextAction.kind === "start_compile_scan" ? undefined : alignSegmentsViews();
92635
- return createNextActionEnvelope({
92636
- workflow: alignWorkflowEnvelopeContext(input.workflowState),
92637
- route: alignRouteSummary(input.route),
92638
- ...allowedActions !== undefined ? { allowed_actions: allowedActions } : {},
92639
- next_action: input.nextAction,
92640
- ...views !== undefined ? { views } : {},
92641
- ...input.diagnostics !== undefined ? { diagnostics: input.diagnostics } : {}
92642
- });
92643
- }
92644
- function alignDirectFinalizeNextAction(reasonCode = "align-route-direct-finalize", inputSchema = "align-structure-intent") {
92645
- return {
92646
- kind: "submit_structure_decision",
92647
- command: ALIGN_FINALIZE_COMMAND,
92648
- input_schema: inputSchema,
92649
- reason_code: reasonCode,
92650
- blocking: true
92651
- };
92652
- }
92653
- function alignValidateNextAction(reasonCode = "align-validate-repair-required", inputSchema = "align-structure-intent") {
92654
- return {
92655
- kind: "validate_align_decision",
92656
- command: ALIGN_VALIDATE_COMMAND2,
92657
- input_schema: inputSchema,
92658
- reason_code: reasonCode,
92659
- blocking: true
92660
- };
92661
- }
92662
- function alignBatchedNextAction(kind) {
92663
- return kind === "submit_candidate_ops" ? {
92664
- kind,
92665
- command: ALIGN_CANDIDATE_OPS_COMMAND,
92666
- input_schema: "align-candidate-ops",
92667
- reason_code: "align-route-batched-review-required",
92668
- blocking: true
92669
- } : {
92670
- kind,
92671
- command: ALIGN_COARSE_READ_COMMAND2,
92672
- input_schema: "align-coarse-read",
92673
- reason_code: "align-route-batched-review-required",
92674
- blocking: true
92675
- };
92676
- }
92677
- function alignAbandonOrRescanNextAction(reasonCode) {
92678
- return {
92679
- kind: "abandon_or_rescan",
92680
- command: ALIGN_RESCAN_COMMAND,
92681
- reason_code: reasonCode,
92682
- blocking: true
92683
- };
92684
- }
92685
-
92686
93438
  // src/commands/workflowAlignValidationViews.ts
92687
93439
  init_cliFeedback();
92688
93440
  init_errors();
@@ -92987,24 +93739,6 @@ function agentHintsForFinalizeIssues(issues) {
92987
93739
  };
92988
93740
  });
92989
93741
  }
92990
- function sectionPlanAutoSplitAgentHints(ownership) {
92991
- const splitPlans = (ownership.section_plans ?? []).filter((plan) => plan.split_reason === "non_contiguous_citation_eligible_blocks" && typeof plan.origin_section_id === "string");
92992
- if (splitPlans.length === 0)
92993
- return [];
92994
- const originSectionIds = [...new Set(splitPlans.map((plan) => plan.origin_section_id))].sort();
92995
- return [{
92996
- code: "align-section-plans-auto-split-contiguous-runs",
92997
- severity: "info",
92998
- message: `${originSectionIds.length} align planned section(s) were split into ${splitPlans.length} contiguous draft-ready section plan(s).`,
92999
- next_action: "Continue to compile scan; use the emitted section_plans/source-refs draft_action_templates. origin_section_id preserves the original align grouping.",
93000
- command: COMPILE_SCAN_COMMAND2,
93001
- diagnostics: {
93002
- origin_section_ids: originSectionIds,
93003
- split_section_plan_count: originSectionIds.length,
93004
- emitted_section_plan_count: splitPlans.length
93005
- }
93006
- }];
93007
- }
93008
93742
  function alignFinalizeCompileHandoffHint() {
93009
93743
  return {
93010
93744
  code: "align-finished-next-compile",
@@ -93160,11 +93894,9 @@ async function finalizeAlignStructureDecisionCommand(input) {
93160
93894
  decision,
93161
93895
  segments: finalizeContext.segments
93162
93896
  });
93163
- const sectionPlanAutoSplitHints = sectionPlanAutoSplitAgentHints(ownership);
93164
- const sectionPlanAutoSplitCount = (ownership.section_plans ?? []).filter((plan) => plan.split_reason === "non_contiguous_citation_eligible_blocks").length;
93897
+ const sectionPlanAutoSplitCount = (ownership.section_plans ?? []).filter((plan) => plan.split_reason !== undefined).length;
93165
93898
  const auditHints = [
93166
93899
  ...validation.auditHints,
93167
- ...sectionPlanAutoSplitHints,
93168
93900
  alignFinalizeCompileHandoffHint()
93169
93901
  ];
93170
93902
  const automaticOwnershipAdjustments = automaticOwnershipAdjustmentsFromDemotions(cliDemotions);
@@ -94338,7 +95070,7 @@ function buildStructureProposalStarter(segments) {
94338
95070
  recommended_no_write_shape: {
94339
95071
  planned_sections: [],
94340
95072
  ownership: "context_only_or_ignored",
94341
- node_type_hint: "domain_if_children_resolve_else_entity_term",
95073
+ node_type_hint: "domain_if_children_resolve_else_agent_chosen_entity",
94342
95074
  ...titleHint !== undefined ? { title_hint: titleHint } : {},
94343
95075
  rationale: "This source only carries relation/navigation or explicit no-detail placeholder text. Keep a Node only when the graph/slug is useful; do not create owned citation evidence or an active Section from these blocks."
94344
95076
  }
@@ -95936,7 +96668,7 @@ async function nodeCycleCoverageGate(input) {
95936
96668
  coverage_ratio: ratio,
95937
96669
  high_signal_unresolved: highSignalUnresolved.length,
95938
96670
  candidate_samples: candidateSamples,
95939
- patch_draft_command: `context compile draft-patch ${shellQuote(input.slug)} --input - --format json`,
96671
+ patch_draft_command: `context compile cycle ${shellQuote(input.slug)} --input - --format json`,
95940
96672
  skip_unresolved_command: skipCommand
95941
96673
  }
95942
96674
  };
@@ -95980,7 +96712,7 @@ function isBlockingWeakSourceSupport(item) {
95980
96712
  return true;
95981
96713
  return support.reason_code !== undefined && support.reason_code !== "weak.soft_diff";
95982
96714
  }
95983
- function sourceSupportSummary(context) {
96715
+ function sourceSupportSummary2(context) {
95984
96716
  return {
95985
96717
  supported: context.items.filter((item) => item.source_support?.verdict === "supported").length,
95986
96718
  weak: context.items.filter((item) => item.source_support?.verdict === "weak").length,
@@ -96421,10 +97153,6 @@ function formatDraftPlanHeadline(result) {
96421
97153
  function shellQuote2(value) {
96422
97154
  return `'${value.replace(/'/g, "'\\''")}'`;
96423
97155
  }
96424
- function formatDraftPatchHeadline(result) {
96425
- const counts = actionCounts(result);
96426
- return `${counts.total} actions parsed; draft patched; continue cycle required`;
96427
- }
96428
97156
  function compileCycleContinueCommand(slug) {
96429
97157
  return `context compile cycle ${shellQuote2(slug)} --continue --format json`;
96430
97158
  }
@@ -96464,7 +97192,7 @@ function draftPlanBody(input) {
96464
97192
  lines.push("**Next options**:");
96465
97193
  lines.push("- continue: `/context:compile`");
96466
97194
  if (draftDigest !== undefined) {
96467
- lines.push(`- revise: \`context compile draft-patch ${shellQuote2(slug)} --input -\``);
97195
+ lines.push(`- revise: \`context compile cycle ${shellQuote2(slug)} --input - --format json\``);
96468
97196
  lines.push(`- continue patched draft: \`${compileCycleContinueCommand(slug)}\``);
96469
97197
  lines.push(`- primitive: \`context reconcile prepare --mode compile --node ${shellQuote2(slug)} --view summary --format json\``);
96470
97198
  } else if (saved) {
@@ -96788,7 +97516,7 @@ function throwCompileDraftRecoveredError(input) {
96788
97516
  delete detail.category;
96789
97517
  delete detail.summary;
96790
97518
  const draftStatusCommand = `context compile draft-status ${input.slug} --format json`;
96791
- const patchCommand = `context compile draft-patch ${input.slug} --input - --format json`;
97519
+ const patchCommand = `context compile cycle ${input.slug} --input - --format json`;
96792
97520
  const reasonCode = typeof input.error.detail?.reason_code === "string" ? input.error.detail.reason_code : "compile-draft-validation-failed";
96793
97521
  const envelope = createNextActionEnvelope({
96794
97522
  allowed_actions: ["show_view", "patch_payload"],
@@ -96944,7 +97672,8 @@ async function runCompileNodeCycle(input) {
96944
97672
  mode: "compile",
96945
97673
  node: input.slug,
96946
97674
  draft: normalizedDraft,
96947
- draftDigest: draftPayload.digest
97675
+ draftDigest: draftPayload.digest,
97676
+ workflowStartedAt: input.workflowState.created_at
96948
97677
  });
96949
97678
  const preparedWorkflow = await advanceCurrentWorkflow({
96950
97679
  ctxDir: input.ctxDir,
@@ -96994,7 +97723,7 @@ async function runCompileNodeCycle(input) {
96994
97723
  const narrowingSummary = sourceRefNarrowingOutput(narrowingHints, "advisory_no_action_required", input.slug);
96995
97724
  if (!review.ready_to_apply) {
96996
97725
  const cycleIssues = review.issues;
96997
- const supportSummary = sourceSupportSummary(context);
97726
+ const supportSummary = sourceSupportSummary2(context);
96998
97727
  const reconcileSummary = reconcileStatusSummary(context);
96999
97728
  const issueStatus = prepareIssueStatus2({
97000
97729
  sourceSupport: supportSummary,
@@ -97206,7 +97935,7 @@ async function runCompileNodeCycle(input) {
97206
97935
  },
97207
97936
  available_actions: [{
97208
97937
  action: "patch_draft",
97209
- command: `context compile draft-patch ${shellQuote(input.slug)} --input - --format json`
97938
+ command: `context compile cycle ${shellQuote(input.slug)} --input - --format json`
97210
97939
  }, {
97211
97940
  action: "inspect_coverage",
97212
97941
  command: coverageGate.detailCommand
@@ -97469,7 +98198,7 @@ function rejectRetiredDraftPatchFields(patchInput, slug) {
97469
98198
  if (issues.length === 0)
97470
98199
  return;
97471
98200
  const first = issues[0];
97472
- const command = `context compile draft-patch ${slug} --input - --format json`;
98201
+ const command = `context compile cycle ${slug} --input - --format json`;
97473
98202
  const envelope = createNextActionEnvelope({
97474
98203
  allowed_actions: ["show_view", "patch_payload"],
97475
98204
  next_action: {
@@ -97506,7 +98235,7 @@ function rejectRetiredDraftPatchFields(patchInput, slug) {
97506
98235
  code: "compile-draft-patch-retired-field",
97507
98236
  severity: "error",
97508
98237
  message: first.message,
97509
- next_action: "Patch actions must use content plus optional summary and source_refs[]; remove retired body/detail/raw and extractive fields.",
98238
+ next_action: "Patch actions must use content plus optional summary and source_refs[] or source_block_ids[]. Submit the corrected compile-draft-patch payload through context compile cycle.",
97510
98239
  command,
97511
98240
  node_slug: slug,
97512
98241
  path: first.path,
@@ -97516,12 +98245,6 @@ function rejectRetiredDraftPatchFields(patchInput, slug) {
97516
98245
  }
97517
98246
 
97518
98247
  // src/commands/compileNodeCycleInput.ts
97519
- function isRecord43(value) {
97520
- return typeof value === "object" && value !== null && !Array.isArray(value);
97521
- }
97522
- function isCompileDraftPatchInput(value) {
97523
- return isRecord43(value) && Array.isArray(value.operations);
97524
- }
97525
98248
  async function resolveNodeCycleInput(input) {
97526
98249
  if (input.continueSaved === true) {
97527
98250
  const payload2 = await readWorkflowPayloadByDigest({
@@ -97538,7 +98261,7 @@ async function resolveNodeCycleInput(input) {
97538
98261
  ...session2.agent_hints !== undefined ? { agentHints: session2.agent_hints } : {}
97539
98262
  };
97540
98263
  }
97541
- if (!isCompileDraftPatchInput(input.value)) {
98264
+ if (!isCompileDraftPatchLikeInput(input.value)) {
97542
98265
  return { draft: input.value };
97543
98266
  }
97544
98267
  const payload = await readWorkflowPayloadByDigest({
@@ -97550,7 +98273,9 @@ async function resolveNodeCycleInput(input) {
97550
98273
  });
97551
98274
  const session = parseCompileDraftSession(payload.value);
97552
98275
  assertCompileDraftSessionNode(session, input.slug);
97553
- const patch = parseCompileDraftPatch(input.value);
98276
+ const patch = parseCompileDraftPatch(input.value, {
98277
+ submitCommand: `context compile cycle ${shellQuote(input.slug)} --input - --format json`
98278
+ });
97554
98279
  rejectRetiredDraftPatchFields(input.value, input.slug);
97555
98280
  const patched = applyCompileDraftPatch({
97556
98281
  session,
@@ -97708,6 +98433,9 @@ function draftActionTemplate(kind, rows) {
97708
98433
  source_refs: rows.map((row) => row.source_ref)
97709
98434
  };
97710
98435
  }
98436
+ function uniqueStrings5(values2) {
98437
+ return [...new Set(values2)].sort();
98438
+ }
97711
98439
  function citationEligibleOrdinals(context) {
97712
98440
  const ordinalByBlock = new Map;
97713
98441
  const rowsBySource = new Map;
@@ -97722,26 +98450,39 @@ function citationEligibleOrdinals(context) {
97722
98450
  }
97723
98451
  return { ordinalByBlock, rowsBySource };
97724
98452
  }
97725
- function splitContiguousRuns(rows, ordinalByBlock) {
98453
+ function splitDraftRuns(rows, ordinalByBlock) {
97726
98454
  const runs = [];
98455
+ const splitReasons = new Set;
97727
98456
  let current = [];
97728
98457
  let previousSource;
97729
98458
  let previousOrdinal;
98459
+ let previousHeadingPath;
97730
98460
  for (const row of rows) {
97731
98461
  const key = sourceKey(row);
97732
98462
  const ordinal = blockKey(row) === null ? undefined : ordinalByBlock.get(blockKey(row));
97733
98463
  const contiguous = current.length > 0 && previousSource === key && previousOrdinal !== undefined && ordinal !== undefined && ordinal === previousOrdinal + 1;
97734
- if (current.length > 0 && !contiguous) {
98464
+ const sameHeading2 = previousHeadingPath !== undefined && sameHeadingPath3(previousHeadingPath, row.heading_path);
98465
+ if (current.length > 0 && (!contiguous || !sameHeading2)) {
98466
+ splitReasons.add(contiguous ? "heading_path_changed" : "non_contiguous_citation_eligible_blocks");
97735
98467
  runs.push(current);
97736
98468
  current = [];
97737
98469
  }
97738
98470
  current.push(row);
97739
98471
  previousSource = key;
97740
98472
  previousOrdinal = ordinal;
98473
+ previousHeadingPath = row.heading_path;
97741
98474
  }
97742
98475
  if (current.length > 0)
97743
98476
  runs.push(current);
97744
- return runs;
98477
+ return { runs, splitReasons: [...splitReasons].sort() };
98478
+ }
98479
+ function sameHeadingPath3(left, right) {
98480
+ return left.length === right.length && left.every((item, index2) => item === right[index2]);
98481
+ }
98482
+ function headingPathKey(value) {
98483
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string"))
98484
+ return;
98485
+ return value.join("\x00");
97745
98486
  }
97746
98487
  function interveningBlockIds(input) {
97747
98488
  const result = new Set;
@@ -97774,6 +98515,49 @@ function recordArray(value) {
97774
98515
  function splitRunCount(group) {
97775
98516
  return numberValue(group.contiguous_run_count) ?? recordArray(group.contiguous_runs).length;
97776
98517
  }
98518
+ function stringArray9(value) {
98519
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
98520
+ }
98521
+ function groupNumber(value, key) {
98522
+ return numberValue(value[key]) ?? 0;
98523
+ }
98524
+ function groupHasMarkdownList(value) {
98525
+ return value.contains_markdown_list === true || recordArray(value.contiguous_runs).some((run2) => run2.contains_markdown_list === true);
98526
+ }
98527
+ function groupFragmentReviewExamples(sectionGroups) {
98528
+ const examples = [];
98529
+ for (let index2 = 0;index2 < sectionGroups.length - 1; index2 += 1) {
98530
+ const current = sectionGroups[index2];
98531
+ const next = sectionGroups[index2 + 1];
98532
+ if (current.owner !== next.owner)
98533
+ continue;
98534
+ const currentHeading = headingPathKey(current.heading_path);
98535
+ const nextHeading = headingPathKey(next.heading_path);
98536
+ if (currentHeading === undefined || currentHeading !== nextHeading)
98537
+ continue;
98538
+ const currentSources = stringArray9(current.source_ids);
98539
+ const nextSources = stringArray9(next.source_ids);
98540
+ if (currentSources.length !== 1 || nextSources.length !== 1 || currentSources[0] !== nextSources[0])
98541
+ continue;
98542
+ const currentBlocks = stringArray9(current.block_ids);
98543
+ const nextBlocks = stringArray9(next.block_ids);
98544
+ const currentSmall = groupNumber(current, "citation_block_count") <= 1 && currentBlocks.length <= 1 && !groupHasMarkdownList(current);
98545
+ const nextLooksLarger = groupNumber(next, "citation_block_count") > 1 || groupHasMarkdownList(next);
98546
+ if (!currentSmall || !nextLooksLarger)
98547
+ continue;
98548
+ examples.push({
98549
+ section_id: current.section_id,
98550
+ next_section_id: next.section_id,
98551
+ owner: current.owner,
98552
+ heading_path: current.heading_path,
98553
+ source_ids: currentSources,
98554
+ block_ids: currentBlocks,
98555
+ next_block_ids: nextBlocks,
98556
+ reason: groupHasMarkdownList(next) ? "single-block section is adjacent to a list-like section under the same heading" : "single-block section is adjacent to a larger section under the same heading"
98557
+ });
98558
+ }
98559
+ return examples;
98560
+ }
97777
98561
  function plannedSectionSourceRefGroups(context, rows) {
97778
98562
  const plans = context.finalized_ownership?.groups.section_plans ?? [];
97779
98563
  if (plans.length === 0)
@@ -97787,9 +98571,12 @@ function plannedSectionSourceRefGroups(context, rows) {
97787
98571
  });
97788
98572
  const citationRows = resolvedRows.filter((row) => row.citation_eligible);
97789
98573
  const sourceRefs2 = citationRows.map((row) => row.source_ref);
98574
+ const headingPaths = uniqueStrings5(citationRows.map((row) => row.heading_path.join("\x00")));
98575
+ const sourceIds = uniqueStrings5(citationRows.flatMap((row) => typeof row.source_id === "string" ? [row.source_id] : []));
98576
+ const containsMarkdownList = citationRows.some((row) => row.contains_markdown_list === true);
97790
98577
  const missingBlockIds = plan.block_ids.filter((blockId) => !rowByBlockId.has(blockId));
97791
98578
  const nonCitationBlockIds = resolvedRows.filter((row) => !row.citation_eligible).flatMap((row) => typeof row.block_id === "string" ? [row.block_id] : []);
97792
- const runs = splitContiguousRuns(citationRows, ordinals.ordinalByBlock);
98579
+ const { runs, splitReasons } = splitDraftRuns(citationRows, ordinals.ordinalByBlock);
97793
98580
  const templates = runs.map((run2) => draftActionTemplate(plan.section_kind, run2));
97794
98581
  const status = missingBlockIds.length > 0 || nonCitationBlockIds.length > 0 || sourceRefs2.length === 0 ? "needs-attention" : runs.length > 1 ? "ready_with_splits" : "ready";
97795
98582
  const intervening = runs.length > 1 ? interveningBlockIds({
@@ -97804,14 +98591,27 @@ function plannedSectionSourceRefGroups(context, rows) {
97804
98591
  section_kind: plan.section_kind,
97805
98592
  status,
97806
98593
  block_ids: [...plan.block_ids],
98594
+ citation_block_count: citationRows.length,
98595
+ ...sourceIds.length > 0 ? { source_ids: sourceIds } : {},
98596
+ ...headingPaths.length === 1 ? { heading_path: headingPaths[0].split("\x00") } : headingPaths.length > 1 ? { heading_paths: headingPaths.map((path14) => path14.split("\x00")) } : {},
98597
+ ...containsMarkdownList ? { contains_markdown_list: true } : {},
97807
98598
  source_refs: sourceRefs2,
97808
98599
  ...plan.refers_to_nodes !== undefined ? { refers_to_nodes: [...plan.refers_to_nodes] } : {},
97809
98600
  ...missingBlockIds.length > 0 ? { missing_block_ids: missingBlockIds } : {},
97810
98601
  ...nonCitationBlockIds.length > 0 ? { non_citation_block_ids: nonCitationBlockIds } : {},
97811
98602
  ...runs.length > 1 ? {
97812
98603
  contiguous_run_count: runs.length,
98604
+ draft_run_count: runs.length,
97813
98605
  intervening_citation_eligible_block_ids: intervening,
97814
- split_reason: "non_contiguous_citation_eligible_blocks",
98606
+ split_reason: splitReasons.includes("non_contiguous_citation_eligible_blocks") ? "non_contiguous_citation_eligible_blocks" : "heading_path_changed",
98607
+ split_reasons: splitReasons,
98608
+ ...splitReasons.includes("heading_path_changed") ? {
98609
+ heading_path_runs: runs.map((run2, index2) => ({
98610
+ run_index: index2 + 1,
98611
+ heading_path: run2[0]?.heading_path ?? [],
98612
+ block_ids: run2.flatMap((row) => typeof row.block_id === "string" ? [row.block_id] : [])
98613
+ }))
98614
+ } : {},
97815
98615
  ...siblingCoveredIntervening.length > 0 ? {
97816
98616
  sibling_bridge_reason: "intervening_blocks_are_planned_by_sibling_sections",
97817
98617
  sibling_bridge_block_ids: siblingCoveredIntervening
@@ -97820,13 +98620,32 @@ function plannedSectionSourceRefGroups(context, rows) {
97820
98620
  contiguous_runs: runs.map((run2, index2) => ({
97821
98621
  run_index: index2 + 1,
97822
98622
  block_ids: run2.flatMap((row) => typeof row.block_id === "string" ? [row.block_id] : []),
97823
- source_refs: run2.map((row) => row.source_ref)
98623
+ source_refs: run2.map((row) => row.source_ref),
98624
+ ...run2[0]?.heading_path !== undefined ? { heading_path: run2[0].heading_path } : {},
98625
+ ...run2.some((row) => row.contains_markdown_list === true) ? { contains_markdown_list: true } : {}
97824
98626
  })),
97825
98627
  draft_action_templates: templates,
97826
98628
  ...status === "ready_with_splits" ? {} : { draft_action_template: templates[0] ?? draftActionTemplate(plan.section_kind, []) }
97827
98629
  };
97828
98630
  });
97829
98631
  }
98632
+ function plannedSectionFragmentReviewHint(input) {
98633
+ const examples = groupFragmentReviewExamples(input.sectionGroups);
98634
+ if (examples.length === 0)
98635
+ return;
98636
+ return {
98637
+ code: "compile-planned-section-fragment-review",
98638
+ severity: "info",
98639
+ message: `${examples.length} adjacent planned section pair(s) may be over-fragmented under the same source heading.`,
98640
+ next_action: "Review these pairs before drafting. If a small lead-in and the following section are one knowledge unit, intentionally combine them in the draft or revise align; otherwise keep the planned groups separate.",
98641
+ command: input.detailCommand,
98642
+ diagnostics: {
98643
+ pair_count: examples.length,
98644
+ examples: examples.slice(0, 8),
98645
+ examples_omitted: Math.max(0, examples.length - 8)
98646
+ }
98647
+ };
98648
+ }
97830
98649
  function plannedSectionSplitRequiredHint(input) {
97831
98650
  const sectionGroups = input.sectionGroups ?? plannedSectionSourceRefGroups(input.context, nodeContextSourceRefRows(input.context));
97832
98651
  const splitGroups = sectionGroups.filter((group) => group.status === "ready_with_splits");
@@ -97842,7 +98661,7 @@ function plannedSectionSplitRequiredHint(input) {
97842
98661
  code: "compile-planned-section-groups-require-split",
97843
98662
  severity: "info",
97844
98663
  message: `Node has ${sectionGroups.length} planned section group(s); ${splitGroups.length} must be split into separate draft actions${bridgeSuffix}.`,
97845
- next_action: "Read source-refs view before drafting; copy each planned_section_groups[].draft_action_templates entry as a separate draft action. Do not merge templates or contiguous runs.",
98664
+ next_action: "Read source-refs view before drafting; copy each planned_section_groups[].draft_action_templates entry as a separate draft action. Do not merge templates, citation-gap runs, or heading-boundary runs.",
97846
98665
  command: input.detailCommand,
97847
98666
  diagnostics: {
97848
98667
  planned_section_groups_count: sectionGroups.length,
@@ -98262,7 +99081,7 @@ var COMMON_DOTTED_IDENTIFIER_ROOTS = new Set([
98262
99081
  "Buffer"
98263
99082
  ]);
98264
99083
  var CODE_ROOT_SUFFIX_RE = /(?:API|Api|Service|Client|Controller|Repository|Manager|Handler|Factory|Provider|Module|Model|Config|Store|Router|Adapter|Component|Context|Runtime|Engine)$/u;
98265
- function stringValue6(value) {
99084
+ function stringValue7(value) {
98266
99085
  return typeof value === "string" && value.length > 0 ? value : undefined;
98267
99086
  }
98268
99087
  function numberValue2(value) {
@@ -98271,11 +99090,23 @@ function numberValue2(value) {
98271
99090
  function booleanValue(value) {
98272
99091
  return typeof value === "boolean" ? value : undefined;
98273
99092
  }
99093
+ function optionalBooleanField(key, value) {
99094
+ return typeof value === "boolean" ? { [key]: value } : {};
99095
+ }
99096
+ function formatFields(row) {
99097
+ return {
99098
+ ...optionalBooleanField("format_sensitive", row.format_sensitive),
99099
+ ...optionalBooleanField("contains_markdown_list", row.contains_markdown_list),
99100
+ ...optionalBooleanField("contains_markdown_table", row.contains_markdown_table),
99101
+ ...optionalBooleanField("contains_fenced_code", row.contains_fenced_code),
99102
+ ...optionalBooleanField("quote_preview_preserves_line_breaks", row.quote_preview_preserves_line_breaks)
99103
+ };
99104
+ }
98274
99105
  function quotePreview(row) {
98275
- return stringValue6(row.quote_preview) ?? stringValue6(row.quote);
99106
+ return stringValue7(row.quote_preview) ?? stringValue7(row.quote);
98276
99107
  }
98277
99108
  function quoteFullText(row) {
98278
- return stringValue6(row.quote_full_text);
99109
+ return stringValue7(row.quote_full_text);
98279
99110
  }
98280
99111
  function literalTexts(row) {
98281
99112
  const fullText = quoteFullText(row);
@@ -98305,9 +99136,9 @@ function contextRole(row) {
98305
99136
  return "framing";
98306
99137
  }
98307
99138
  function mapCitable(row) {
98308
- const sourceRef = stringValue6(row.source_ref);
98309
- const sourceId = stringValue6(row.source_id);
98310
- const blockId = stringValue6(row.block_id);
99139
+ const sourceRef = stringValue7(row.source_ref);
99140
+ const sourceId = stringValue7(row.source_id);
99141
+ const blockId = stringValue7(row.block_id);
98311
99142
  if (row.citation_eligible !== true || sourceRef === undefined || sourceId === undefined || blockId === undefined) {
98312
99143
  return;
98313
99144
  }
@@ -98327,19 +99158,20 @@ function mapCitable(row) {
98327
99158
  ...quoteCharCount !== undefined ? { quote_char_count: quoteCharCount } : {},
98328
99159
  ...previewCharCount !== undefined ? { preview_char_count: previewCharCount } : {},
98329
99160
  ...previewIsComplete !== undefined ? { preview_is_complete: previewIsComplete } : {},
99161
+ ...formatFields(row),
98330
99162
  ...selector !== undefined ? { selector } : {}
98331
99163
  };
98332
99164
  }
98333
99165
  function mapSupporting(row) {
98334
- const sourceRef = stringValue6(row.source_ref);
98335
- const sourceId = stringValue6(row.source_id);
98336
- const blockId = stringValue6(row.block_id);
99166
+ const sourceRef = stringValue7(row.source_ref);
99167
+ const sourceId = stringValue7(row.source_id);
99168
+ const blockId = stringValue7(row.block_id);
98337
99169
  if (row.citation_eligible === true || sourceRef === undefined || sourceId === undefined || blockId === undefined) {
98338
99170
  return;
98339
99171
  }
98340
99172
  const role = contextRole(row);
98341
99173
  const preview = quotePreview(row);
98342
- const structuralRole = stringValue6(row.structural_role);
99174
+ const structuralRole = stringValue7(row.structural_role);
98343
99175
  const quoteCharCount = numberValue2(row.quote_char_count);
98344
99176
  const previewCharCount = numberValue2(row.preview_char_count);
98345
99177
  const previewIsComplete = booleanValue(row.preview_is_complete);
@@ -98355,12 +99187,13 @@ function mapSupporting(row) {
98355
99187
  ...preview !== undefined ? { quote_preview: preview } : {},
98356
99188
  ...quoteCharCount !== undefined ? { quote_char_count: quoteCharCount } : {},
98357
99189
  ...previewCharCount !== undefined ? { preview_char_count: previewCharCount } : {},
98358
- ...previewIsComplete !== undefined ? { preview_is_complete: previewIsComplete } : {}
99190
+ ...previewIsComplete !== undefined ? { preview_is_complete: previewIsComplete } : {},
99191
+ ...formatFields(row)
98359
99192
  };
98360
99193
  }
98361
99194
  function literalBase(row) {
98362
- const sourceRef = stringValue6(row.source_ref);
98363
- const blockId = stringValue6(row.block_id);
99195
+ const sourceRef = stringValue7(row.source_ref);
99196
+ const blockId = stringValue7(row.block_id);
98364
99197
  return {
98365
99198
  ...sourceRef !== undefined ? { source_ref: sourceRef } : {},
98366
99199
  ...blockId !== undefined ? { block_id: blockId } : {}
@@ -98489,11 +99322,32 @@ function plannedTemplateActions(sectionGroups) {
98489
99322
  function scaffoldUsage() {
98490
99323
  return "Fill each action.content, adjust kind when needed, keep source_block_ids as the citation shorthand, and keep every scaffold action / planned_section_groups[].draft_action_templates entry as a separate draft action. Do not merge multiple planned groups, templates, or contiguous runs into one action; non-contiguous evidence will be rejected. Submit the actions with context compile cycle <node> --input - --format json, or context compile draft <node> --input - for manual review.";
98491
99324
  }
99325
+ function stringArray10(value) {
99326
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.length > 0) : [];
99327
+ }
99328
+ function formatSensitiveMetadata(action, rows) {
99329
+ const blockIds = new Set(stringArray10(action.source_block_ids));
99330
+ const sourceRefs2 = new Set(stringArray10(action.source_refs));
99331
+ const selected = rows.filter((row) => row.format_sensitive === true && (typeof row.block_id === "string" && blockIds.has(row.block_id) || typeof row.source_ref === "string" && sourceRefs2.has(row.source_ref)));
99332
+ if (selected.length === 0)
99333
+ return {};
99334
+ const sensitiveBlockIds = selected.map((row) => row.block_id).filter((blockId) => typeof blockId === "string" && blockId.length > 0);
99335
+ const commands = selected.map((row) => row.request_full_text_command).filter((command) => typeof command === "string" && command.length > 0);
99336
+ return {
99337
+ format_sensitive_block_ids: sensitiveBlockIds,
99338
+ request_full_text_commands: commands,
99339
+ content_source_hint: "Use request_full_text output for user-facing Markdown content from these block_ids; quote_preview is compact and does not preserve line breaks."
99340
+ };
99341
+ }
99342
+ function formatSensitiveBlockIds(rows) {
99343
+ return rows.filter((row) => row.format_sensitive === true).map((row) => row.block_id).filter((blockId) => typeof blockId === "string" && blockId.length > 0);
99344
+ }
98492
99345
  function sourceRefsDraftScaffold(input) {
98493
99346
  const requested = new Set(input.requestedBlockIds ?? []);
98494
99347
  const plannedActions = requested.size === 0 ? plannedTemplateActions(input.sectionGroups) : [];
98495
99348
  if (plannedActions.length > 0) {
98496
99349
  const evidence2 = input.compact === true ? undefined : compileEvidenceFields(input.rows);
99350
+ const formatSensitiveIds2 = formatSensitiveBlockIds(input.rows);
98497
99351
  return {
98498
99352
  schema_version: COMPILE_DRAFT_SCHEMA_VERSION,
98499
99353
  node_slug: input.context.node.slug,
@@ -98504,17 +99358,25 @@ function sourceRefsDraftScaffold(input) {
98504
99358
  planned_section_groups: input.sectionGroups.filter((group) => group.status === "ready" || group.status === "ready_with_splits").map((group) => group.section_id).filter((sectionId2) => typeof sectionId2 === "string")
98505
99359
  },
98506
99360
  usage: scaffoldUsage(),
99361
+ ...formatSensitiveIds2.length > 0 ? {
99362
+ format_sensitive_block_ids: formatSensitiveIds2,
99363
+ content_source_hint: "Format-sensitive block_ids contain Markdown lists, tables, or fenced code. Use request_full_text_commands before filling user-facing content from quote previews."
99364
+ } : {},
98507
99365
  ...evidence2 !== undefined ? {
98508
99366
  citable_source_refs: evidence2.citable_source_refs,
98509
99367
  supporting_context_refs: evidence2.supporting_context_refs,
98510
99368
  required_preserved_literals: evidence2.required_preserved_literals
98511
99369
  } : {},
98512
- actions: plannedActions.map((action) => ({ ...action }))
99370
+ actions: plannedActions.map((action) => ({
99371
+ ...action,
99372
+ ...formatSensitiveMetadata(action, input.rows)
99373
+ }))
98513
99374
  };
98514
99375
  }
98515
99376
  const selectedRows = input.rows.filter((row) => row.citation_eligible === true && typeof row.source_ref === "string" && (requested.size === 0 || typeof row.block_id === "string" && requested.has(row.block_id)));
98516
99377
  const kind = defaultScaffoldSectionKind(input.context);
98517
99378
  const evidence = input.compact === true ? undefined : compileEvidenceFields(selectedRows);
99379
+ const formatSensitiveIds = formatSensitiveBlockIds(selectedRows);
98518
99380
  return {
98519
99381
  schema_version: COMPILE_DRAFT_SCHEMA_VERSION,
98520
99382
  node_slug: input.context.node.slug,
@@ -98525,6 +99387,10 @@ function sourceRefsDraftScaffold(input) {
98525
99387
  ...requested.size > 0 ? { requested_block_ids: [...requested] } : {}
98526
99388
  },
98527
99389
  usage: scaffoldUsage(),
99390
+ ...formatSensitiveIds.length > 0 ? {
99391
+ format_sensitive_block_ids: formatSensitiveIds,
99392
+ content_source_hint: "Format-sensitive block_ids contain Markdown lists, tables, or fenced code. Use request_full_text_commands before filling user-facing content from quote previews."
99393
+ } : {},
98528
99394
  ...evidence !== undefined ? {
98529
99395
  citable_source_refs: evidence.citable_source_refs,
98530
99396
  supporting_context_refs: evidence.supporting_context_refs,
@@ -98534,7 +99400,8 @@ function sourceRefsDraftScaffold(input) {
98534
99400
  op: "add",
98535
99401
  kind,
98536
99402
  content: "",
98537
- source_block_ids: typeof row.block_id === "string" ? [row.block_id] : []
99403
+ source_block_ids: typeof row.block_id === "string" ? [row.block_id] : [],
99404
+ ...formatSensitiveMetadata({ source_block_ids: typeof row.block_id === "string" ? [row.block_id] : [] }, selectedRows)
98538
99405
  }))
98539
99406
  };
98540
99407
  }
@@ -98563,8 +99430,15 @@ function compactDraftScaffoldGroup(group) {
98563
99430
  "missing_block_ids",
98564
99431
  "non_citation_block_ids",
98565
99432
  "contiguous_run_count",
99433
+ "citation_block_count",
99434
+ "source_ids",
99435
+ "heading_path",
99436
+ "heading_paths",
99437
+ "contains_markdown_list",
98566
99438
  "intervening_citation_eligible_block_ids",
98567
99439
  "split_reason",
99440
+ "split_reasons",
99441
+ "heading_path_runs",
98568
99442
  "sibling_bridge_reason",
98569
99443
  "sibling_bridge_block_ids",
98570
99444
  "contiguous_runs",
@@ -98632,7 +99506,7 @@ function sourceRefsSectionGroupHint(sectionGroups) {
98632
99506
  code: "compile-source-refs-planned-section-groups",
98633
99507
  severity: "info",
98634
99508
  message: "planned_section_groups is the primary source-refs authoring path for finalized align section plans.",
98635
- next_action: splitCount > 0 ? "Copy each planned_section_groups[].draft_action_templates entry as a separate draft action; split groups already avoid non-contiguous citation-eligible blocks and may use source_block_ids shorthand. Do not merge templates or contiguous runs." : "Copy each planned_section_groups[].draft_action_templates entry as a separate draft action; fill content from the cited evidence and keep source_block_ids shorthand when present. Do not merge planned groups/templates.",
99509
+ next_action: splitCount > 0 ? "Copy each planned_section_groups[].draft_action_templates entry as a separate draft action; split groups already avoid non-contiguous citation-eligible blocks and may use source_block_ids shorthand. Do not merge by default; only intentionally combine adjacent templates when a fragment-review hint flags them and the evidence is one knowledge unit." : "Copy each planned_section_groups[].draft_action_templates entry as a separate draft action; fill content from the cited evidence and keep source_block_ids shorthand when present. Do not merge by default; only intentionally combine adjacent groups when a fragment-review hint flags them and the evidence is one knowledge unit.",
98636
99510
  diagnostics: {
98637
99511
  planned_section_groups: sectionGroups.length,
98638
99512
  split_planned_section_groups: splitCount
@@ -98643,7 +99517,7 @@ function sourceRefsDenseHintWithSectionGroups(hint, sectionGroups) {
98643
99517
  return {
98644
99518
  ...hint,
98645
99519
  message: `${hint.message} planned_section_groups are available for finalized align section plans.`,
98646
- next_action: "Use planned_section_groups[].draft_action_templates first, keeping each template as a separate draft action. Fallback may split finer only when a planned group is missing, needs attention, or you intentionally need finer-grained Sections; do not merge planned groups/templates.",
99520
+ next_action: "Use planned_section_groups[].draft_action_templates first, keeping each template as a separate draft action by default. Fallback may split finer only when a planned group is missing, needs attention, or you intentionally need finer-grained Sections; combine adjacent templates only when fragment-review evidence shows one knowledge unit.",
98647
99521
  diagnostics: {
98648
99522
  ...hint.diagnostics ?? {},
98649
99523
  planned_section_groups_available: true,
@@ -98653,6 +99527,11 @@ function sourceRefsDenseHintWithSectionGroups(hint, sectionGroups) {
98653
99527
  }
98654
99528
  function sourceRefsViewHints(input) {
98655
99529
  const sectionGroupHints = sourceRefsSectionGroupHint(input.sectionGroups);
99530
+ const fragmentReviewHint = plannedSectionFragmentReviewHint({
99531
+ sectionGroups: input.sectionGroups,
99532
+ detailCommand: input.detailCommand
99533
+ });
99534
+ const fragmentHints = fragmentReviewHint === undefined ? [] : [fragmentReviewHint];
98656
99535
  if (input.sectionGroups.length === 0) {
98657
99536
  return [...input.projectedHints, input.scaffoldHint];
98658
99537
  }
@@ -98665,7 +99544,7 @@ function sourceRefsViewHints(input) {
98665
99544
  nonDenseHints.push(hint);
98666
99545
  }
98667
99546
  }
98668
- return [...nonDenseHints, ...sectionGroupHints, ...denseHints, input.scaffoldHint];
99547
+ return [...nonDenseHints, ...sectionGroupHints, ...fragmentHints, ...denseHints, input.scaffoldHint];
98669
99548
  }
98670
99549
  function compileCycleCommand(slug) {
98671
99550
  return `context compile cycle ${shellQuote(slug)} --input - --format json`;
@@ -98761,7 +99640,12 @@ function writeCompileSourceRefs(context, format, options = {}) {
98761
99640
  command: sourceRefsIndex,
98762
99641
  detail_view_command: sourceRefsDetail
98763
99642
  };
98764
- const viewHints = sourceRefsViewHints({ projectedHints, sectionGroups, scaffoldHint });
99643
+ const viewHints = sourceRefsViewHints({
99644
+ projectedHints,
99645
+ sectionGroups,
99646
+ scaffoldHint,
99647
+ detailCommand: sourceRefsDetail
99648
+ });
98765
99649
  const envelope = sourceRefsNextActionEnvelope({
98766
99650
  context,
98767
99651
  ...options.workflowState !== undefined ? { workflowState: options.workflowState } : {},
@@ -99041,13 +99925,13 @@ function writeCompileContextSummary(input) {
99041
99925
  writeCompileContextTextSummary(input, coverageRepairRound, coverageScopeHint);
99042
99926
  }
99043
99927
  function compileDraftRevisionHints(slug, digest2) {
99044
- const patchCommand = `context compile draft-patch ${shellQuote(slug)} --input -`;
99928
+ const patchCommand = `context compile cycle ${shellQuote(slug)} --input - --format json`;
99045
99929
  const rebuildCommand = `context compile draft ${shellQuote(slug)} --input -`;
99046
99930
  return [{
99047
99931
  code: "compile-draft-patch-ready",
99048
99932
  severity: "info",
99049
99933
  message: "Current draft can be revised with a node-scoped patch instead of resubmitting all actions.",
99050
- next_action: "Replace, add, or remove only the affected action. replace_action fully replaces that action while keeping action_id; add_action receives a new action_id. To rebuild from scratch, submit a full draft with context compile draft <slug> --input -.",
99934
+ next_action: "Replace, add, or remove only the affected action, then submit the compile-draft-patch payload through context compile cycle. replace_action fully replaces that action while keeping action_id; add_action receives a new action_id. To rebuild from scratch, submit a full draft with context compile cycle <slug> --input - --format json.",
99051
99935
  command: patchCommand,
99052
99936
  patch_schema_version: COMPILE_DRAFT_PATCH_SCHEMA_VERSION,
99053
99937
  correct_shape: compileDraftPatchCorrectShape(),
@@ -99085,7 +99969,7 @@ function writeCompileDraftStatus(input) {
99085
99969
  view,
99086
99970
  draft_digest: input.digest,
99087
99971
  patch_schema_version: COMPILE_DRAFT_PATCH_SCHEMA_VERSION,
99088
- patch_command: hints[0]?.command ?? `context compile draft-patch ${shellQuote(input.session.node)} --input -`,
99972
+ patch_command: hints[0]?.command ?? `context compile cycle ${shellQuote(input.session.node)} --input - --format json`,
99089
99973
  ...input.session.suggested_patch_template !== undefined ? { suggested_patch_template: input.session.suggested_patch_template } : {},
99090
99974
  show_command: input.showCommand,
99091
99975
  next_command: input.showCommand,
@@ -99120,7 +100004,7 @@ function writeCompileDraftStatus(input) {
99120
100004
  function claimIdForActionIndex(index2) {
99121
100005
  return `claim-${String(index2 + 1).padStart(3, "0")}`;
99122
100006
  }
99123
- function stringArray9(value) {
100007
+ function stringArray11(value) {
99124
100008
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
99125
100009
  }
99126
100010
  function sourceRefNarrowingByActionIndex(hints) {
@@ -99129,13 +100013,13 @@ function sourceRefNarrowingByActionIndex(hints) {
99129
100013
  if (hint.code !== "compile-source-refs-narrowing-suggested" || typeof hint.op_index !== "number")
99130
100014
  continue;
99131
100015
  const diagnostics = hint.diagnostics ?? {};
99132
- const original = stringArray9(diagnostics.original_source_refs);
99133
- const narrowed = stringArray9(diagnostics.narrowed_source_refs);
99134
- const removed = stringArray9(diagnostics.removed_source_refs);
99135
- const leadIn = stringArray9(diagnostics.removed_lead_in_source_refs);
99136
- const redundant = stringArray9(diagnostics.removed_redundant_source_refs);
99137
- const suggestedRefs = stringArray9(diagnostics.suggested_source_refs);
99138
- const patchRefs = stringArray9(diagnostics.patch_source_refs);
100016
+ const original = stringArray11(diagnostics.original_source_refs);
100017
+ const narrowed = stringArray11(diagnostics.narrowed_source_refs);
100018
+ const removed = stringArray11(diagnostics.removed_source_refs);
100019
+ const leadIn = stringArray11(diagnostics.removed_lead_in_source_refs);
100020
+ const redundant = stringArray11(diagnostics.removed_redundant_source_refs);
100021
+ const suggestedRefs = stringArray11(diagnostics.suggested_source_refs);
100022
+ const patchRefs = stringArray11(diagnostics.patch_source_refs);
99139
100023
  if (original.length === 0 || narrowed.length === 0 || removed.length === 0)
99140
100024
  continue;
99141
100025
  byIndex.set(hint.op_index, {
@@ -99160,8 +100044,8 @@ function sourceRefNarrowingByActionIndex(hints) {
99160
100044
  function sourceSupportDiagnostics(support) {
99161
100045
  if (support?.verdict === undefined || support.verdict === "supported")
99162
100046
  return;
99163
- const missingHardTerms = stringArray9(support.missing_hard_terms);
99164
- const missingContentTerms = stringArray9(support.missing_content_terms);
100047
+ const missingHardTerms = stringArray11(support.missing_hard_terms);
100048
+ const missingContentTerms = stringArray11(support.missing_content_terms);
99165
100049
  const missingTerms = Array.isArray(support.missing_terms) ? support.missing_terms.slice(0, 12).filter((term) => term !== null && typeof term === "object") : [];
99166
100050
  if (missingHardTerms.length === 0 && missingContentTerms.length === 0 && missingTerms.length === 0)
99167
100051
  return;
@@ -99270,11 +100154,11 @@ function withPayloadMeta2(value, payload) {
99270
100154
  })
99271
100155
  };
99272
100156
  }
99273
- function stringArray10(value) {
100157
+ function stringArray12(value) {
99274
100158
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
99275
100159
  }
99276
100160
  function narrowingSuggestionRemovedCount(context) {
99277
- return (context.agent_hints ?? []).filter((hint) => hint.code === "compile-source-refs-narrowing-suggested").reduce((sum, hint) => sum + stringArray10(hint.diagnostics?.removed_source_refs).length, 0);
100161
+ return (context.agent_hints ?? []).filter((hint) => hint.code === "compile-source-refs-narrowing-suggested").reduce((sum, hint) => sum + stringArray12(hint.diagnostics?.removed_source_refs).length, 0);
99278
100162
  }
99279
100163
  function prepareEnvelopeOutput(input) {
99280
100164
  const warnings = (input.context.agent_hints ?? []).filter((hint) => hint.severity === "warning" || hint.severity === "error");
@@ -99368,27 +100252,12 @@ async function prepareCompileDraftWorkflow(input) {
99368
100252
  }
99369
100253
 
99370
100254
  // src/commands/compileDraftCommand.ts
99371
- function isRecord44(value) {
100255
+ function isRecord43(value) {
99372
100256
  return typeof value === "object" && value !== null && !Array.isArray(value);
99373
100257
  }
99374
- function draftActionCounts(draft) {
99375
- return {
99376
- total: draft.actions.length,
99377
- add: draft.actions.filter((action) => action.op === "add").length,
99378
- update: draft.actions.filter((action) => action.op === "update").length,
99379
- supersede: draft.actions.filter((action) => action.op === "supersede").length,
99380
- deprecate: draft.actions.filter((action) => action.op === "deprecate").length,
99381
- skip: draft.actions.filter((action) => action.op === "skip").length,
99382
- structure_challenge: draft.actions.filter((action) => action.op === "structure_challenge").length,
99383
- pending_ownership_challenge: draft.actions.filter((action) => action.op === "pending_ownership_challenge").length
99384
- };
99385
- }
99386
100258
  function compileCycleInputCommand(slug) {
99387
100259
  return `context compile cycle ${shellQuote(slug)} --input - --format json`;
99388
100260
  }
99389
- function compileCycleContinueCommand2(slug) {
99390
- return `context compile cycle ${shellQuote(slug)} --continue --format json`;
99391
- }
99392
100261
  function compileDraftInputRequiredError(slug) {
99393
100262
  const reasonCode = "compile-draft-input-required";
99394
100263
  const message = "context compile draft requires --input - unless --prepare is used to load the saved draft session";
@@ -99425,6 +100294,44 @@ function compileDraftInputRequiredError(slug) {
99425
100294
  }]
99426
100295
  });
99427
100296
  }
100297
+ function compileDraftPatchCommandError(slug) {
100298
+ const reasonCode = "compile-draft-patch-cycle-required";
100299
+ const command = compileCycleInputCommand(slug);
100300
+ const message = "submit compile draft patches through context compile cycle";
100301
+ const envelope = createNextActionEnvelope({
100302
+ allowed_actions: ["patch_payload", "show_view"],
100303
+ next_action: {
100304
+ kind: "patch_compile_draft",
100305
+ command,
100306
+ input_schema: "compile-draft-patch",
100307
+ reason_code: reasonCode,
100308
+ blocking: true
100309
+ },
100310
+ diagnostics: {
100311
+ summary: { reason_code: reasonCode, issue_count: 1 },
100312
+ warnings: [{
100313
+ code: reasonCode,
100314
+ severity: "error",
100315
+ message,
100316
+ reason_code: reasonCode
100317
+ }]
100318
+ },
100319
+ strict: false
100320
+ });
100321
+ return new ContextError(ExitCode.UserError, message, {
100322
+ category: ErrorCategory.UserInputInvalid,
100323
+ ...envelope,
100324
+ agent_hints: [{
100325
+ code: reasonCode,
100326
+ severity: "error",
100327
+ message,
100328
+ next_action: "Submit the same compile-draft-patch payload to the compile cycle command.",
100329
+ command,
100330
+ schema: "compile-draft-patch",
100331
+ schema_version: "compile.draft-patch.v2"
100332
+ }]
100333
+ });
100334
+ }
99428
100335
  async function writeCompileDraftChallengePayloads2(input) {
99429
100336
  const payloads = await compileDraftChallengePayloads({
99430
100337
  ctxDir: input.ctxDir,
@@ -99452,16 +100359,16 @@ async function writeCompileDraftChallengePayloads2(input) {
99452
100359
  });
99453
100360
  }
99454
100361
  }
99455
- function stringArray11(value) {
100362
+ function stringArray13(value) {
99456
100363
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
99457
100364
  }
99458
100365
  function preparedSourceSupportStatus(value) {
99459
- if (!isRecord44(value) || typeof value.verdict !== "string")
100366
+ if (!isRecord43(value) || typeof value.verdict !== "string")
99460
100367
  return;
99461
100368
  if (value.verdict === "supported")
99462
100369
  return { verdict: value.verdict };
99463
- const missingHardTerms = stringArray11(value.missing_hard_terms);
99464
- const missingContentTerms = stringArray11(value.missing_content_terms);
100370
+ const missingHardTerms = stringArray13(value.missing_hard_terms);
100371
+ const missingContentTerms = stringArray13(value.missing_content_terms);
99465
100372
  const missingTerms = Array.isArray(value.missing_terms) ? value.missing_terms.slice(0, 12).filter((term) => term !== null && typeof term === "object") : [];
99466
100373
  return {
99467
100374
  verdict: value.verdict,
@@ -99471,15 +100378,15 @@ function preparedSourceSupportStatus(value) {
99471
100378
  };
99472
100379
  }
99473
100380
  function preparedReconcileStatus(value, slug) {
99474
- const agentHints = isRecord44(value) && Array.isArray(value.agent_hints) ? value.agent_hints.filter(isRecord44) : [];
99475
- if (!isRecord44(value) || !Array.isArray(value.items))
100381
+ const agentHints = isRecord43(value) && Array.isArray(value.agent_hints) ? value.agent_hints.filter(isRecord43) : [];
100382
+ if (!isRecord43(value) || !Array.isArray(value.items))
99476
100383
  return { items: [], agentHints };
99477
- const target = isRecord44(value.target) ? value.target : undefined;
100384
+ const target = isRecord43(value.target) ? value.target : undefined;
99478
100385
  if (target !== undefined && target.node !== slug)
99479
100386
  return { items: [], agentHints };
99480
100387
  return {
99481
100388
  agentHints,
99482
- items: value.items.filter(isRecord44).flatMap((item) => {
100389
+ items: value.items.filter(isRecord43).flatMap((item) => {
99483
100390
  if (typeof item.item_id !== "string")
99484
100391
  return [];
99485
100392
  const sourceSupport = preparedSourceSupportStatus(item.source_support);
@@ -99528,125 +100435,7 @@ async function runDraftStatus(input) {
99528
100435
  });
99529
100436
  }
99530
100437
  async function runDraftPatch(input) {
99531
- const current = requireCurrentWorkflow(await readCurrentWorkflow(input.ctxDir));
99532
- if (current.family !== "compile") {
99533
- throw new ContextError(ExitCode.UserError, "compile draft patch requires an active compile workflow", {
99534
- category: ErrorCategory.UserInputInvalid
99535
- });
99536
- }
99537
- const payload = await readWorkflowPayloadByDigest({
99538
- ctxDir: input.ctxDir,
99539
- workflowId: current.workflow_id,
99540
- scopeId: nodeRunIdForSlug(input.slug),
99541
- payload: "compile-draft",
99542
- ...typeof input.options.payloadDigest === "string" ? { digest: input.options.payloadDigest } : {},
99543
- fallbackToUniqueScope: true
99544
- });
99545
- const session = parseCompileDraftSession(payload.value);
99546
- assertCompileDraftSessionNode(session, input.slug);
99547
- const patchInput = await readStructuredInput2(resolveStdinOnlyInput(input.options.input, "--input"));
99548
- const patch = parseCompileDraftPatch(patchInput);
99549
- const patched = applyCompileDraftPatch({
99550
- session,
99551
- patch,
99552
- expectedDigest: payload.digest
99553
- });
99554
- rejectRetiredDraftPatchFields(patchInput, input.slug);
99555
- const result = await compileDraft({
99556
- ctxDir: input.ctxDir,
99557
- slug: input.slug,
99558
- mode: "plan",
99559
- inputMode: "internal",
99560
- stdout: { write: () => true },
99561
- draftProvider: async () => patched.draft
99562
- });
99563
- const normalizedDraft = result.plan ?? patched.draft;
99564
- const nextSession = createCompileDraftSession({
99565
- node: input.slug,
99566
- draft: normalizedDraft,
99567
- ...result.agent_hints !== undefined ? { agentHints: result.agent_hints } : {}
99568
- });
99569
- const nextPayload = await writeWorkflowPayloadWithDigest({
99570
- ctxDir: input.ctxDir,
99571
- workflowId: current.workflow_id,
99572
- scopeId: nodeRunIdForSlug(input.slug),
99573
- payload: "compile-draft",
99574
- value: nextSession,
99575
- format: "yaml"
99576
- });
99577
- await writeCompileDraftChallengePayloads2({
99578
- ctxDir: input.ctxDir,
99579
- workflowId: current.workflow_id,
99580
- scopeId: nodeRunIdForSlug(input.slug),
99581
- draft: normalizedDraft
99582
- });
99583
- const continueCommand = compileCycleContinueCommand2(result.slug);
99584
- const envelope = createNextActionEnvelope({
99585
- workflow: {
99586
- id: current.workflow_id,
99587
- workflow_id: current.workflow_id,
99588
- family: current.family,
99589
- stage: current.stage,
99590
- terminal: false,
99591
- scope_id: workflowScope(current)
99592
- },
99593
- allowed_actions: ["continue_compile_cycle", "show_view"],
99594
- next_action: {
99595
- kind: "continue_compile_cycle",
99596
- command: continueCommand,
99597
- reason_code: "compile-draft-patched"
99598
- },
99599
- views: [{
99600
- id: "draft-status",
99601
- purpose: "Inspect the patched saved draft before continuing cycle if needed.",
99602
- evidence_role: "diagnostic",
99603
- expected: false,
99604
- budget_safety: "compact",
99605
- command: `context compile draft-status ${shellQuote(result.slug)} --format json`
99606
- }]
99607
- });
99608
- const outputHints = [...patch.agent_hints ?? [], ...result.agent_hints ?? []];
99609
- if (compileChangesFormat(input.options.format) === "json") {
99610
- writeJson5({
99611
- action: "patched",
99612
- status: "planned",
99613
- node: input.slug,
99614
- schema_version: envelope.schema_version,
99615
- allowed_actions: envelope.allowed_actions,
99616
- next_action: envelope.next_action,
99617
- views: envelope.views,
99618
- workflow: workflowMetadata(current),
99619
- draft: {
99620
- payload: nextPayload.payload,
99621
- scope_id: nextPayload.scope_id,
99622
- digest: nextPayload.digest,
99623
- format: nextPayload.format,
99624
- show_command: workflowPayloadShowCommand(nextPayload)
99625
- },
99626
- action_counts: draftActionCounts(normalizedDraft),
99627
- agent_hints: outputHints,
99628
- next_command: continueCommand
99629
- });
99630
- return;
99631
- }
99632
- process.stdout.write(formatFeedback({
99633
- symbol: outputHints.some((hint) => hint.severity === "warning" || hint.severity === "error") ? "⚠" : "✓",
99634
- action: "patched",
99635
- subject: input.slug,
99636
- headline: formatDraftPatchHeadline(result),
99637
- body: [
99638
- workflowSummaryLine(current),
99639
- ...draftPlanBody({
99640
- ctxDir: input.ctxDir,
99641
- slug: result.slug,
99642
- saved: false,
99643
- ...outputHints.length > 0 ? { hints: outputHints } : {},
99644
- draftDigest: nextPayload.digest,
99645
- result
99646
- })
99647
- ],
99648
- next: continueCommand
99649
- }));
100438
+ throw compileDraftPatchCommandError(input.slug);
99650
100439
  }
99651
100440
  async function draftFromSavedSession(input) {
99652
100441
  const current = requireCurrentWorkflow(await readCurrentWorkflow(input.ctxDir));
@@ -100160,7 +100949,7 @@ function registerCompileWorkflowSubcommands(command, run2) {
100160
100949
  command.command("draft-status <slug>").description("Print the current compile draft session summary").option("--view <view>", "output view: summary | detail | narrowing-detail").option("--format <format>", "output format: json | table", "json").action(async (slug, options) => {
100161
100950
  await run2(mergeOptions(options, { draftStatus: slug }));
100162
100951
  });
100163
- command.command("draft-patch <slug>").description("Apply a compile draft patch for one node").option("--input <-|stdin>", "compile draft patch JSON/YAML document; only '-' is accepted; use shell redirect or heredoc").option("--payload-digest <digest>", "optional compile draft payload digest stale guard").option("--format <format>", "output format: json | table", "json").action(async (slug, options) => {
100952
+ command.command("draft-patch <slug>", { hidden: true }).description("Use context compile cycle <slug> --input - --format json").option("--input <-|stdin>", "compile draft patch JSON/YAML document; only '-' is accepted; use shell redirect or heredoc").option("--payload-digest <digest>", "optional compile draft payload digest stale guard").option("--format <format>", "output format: json | table", "json").action(async (slug, options) => {
100164
100953
  await run2(mergeOptions(options, { draftPatch: slug, plan: true }));
100165
100954
  });
100166
100955
  command.command("coverage <slug>").description("Resolve coverage candidates for one node").option("--input <-|stdin>", "coverage disposition patch JSON/YAML document; only '-' is accepted; use shell redirect or heredoc").option("--skip <candidate-id>", "skip one or more coverage candidates; repeat for multiple", collectCoverageSkip, []).option("--skip-unresolved", "skip every unresolved coverage candidate for this node").option("--reason <text>", "reason for coverage skip shortcuts").option("--replace", "replace existing dispositions for patched candidates").option("--payload-digest <digest>", "optional workflow payload digest stale guard").option("--format <format>", "output format: json | table", "json").action(async (slug, options) => {
@@ -100233,11 +101022,6 @@ var COMPILE_MODE_COMMANDS = [
100233
101022
  command: "context compile draft-status <slug> --format json",
100234
101023
  description: "Inspect a saved compile draft session."
100235
101024
  },
100236
- {
100237
- mode: "draft-patch",
100238
- command: "context compile draft-patch <slug> --input -",
100239
- description: "Patch a saved compile draft session."
100240
- },
100241
101025
  {
100242
101026
  mode: "coverage-status",
100243
101027
  command: "context compile coverage <slug> --format json",
@@ -101642,11 +102426,6 @@ function assertDraftOptions(options) {
101642
102426
  if (typeof options.draftPatch === "string" && options.plan !== true) {
101643
102427
  options.plan = true;
101644
102428
  }
101645
- if (typeof options.draftPatch === "string" && typeof options.input !== "string") {
101646
- throw new ContextError(ExitCode.UserError, "context compile draft-patch requires --input", {
101647
- category: ErrorCategory.UserInputInvalid
101648
- });
101649
- }
101650
102429
  }
101651
102430
  function assertAspectCompileOptions(options, flags2) {
101652
102431
  if (flags2.wantsCode && (options.plan === true || options.delegated === true)) {
@@ -102467,6 +103246,13 @@ var AGENT_HINT_EMITTER_WORKFLOW_INVENTORY = [
102467
103246
  handles: ["node_ref", "block_id", "ownership_role"],
102468
103247
  notes: "Shared align payload diagnostics expose semantic ids and ownership roles; normal authoring remains intent-first."
102469
103248
  },
103249
+ {
103250
+ source: "src/workflow/alignStructureIntent.ts",
103251
+ family: "align structure intent compiler",
103252
+ policy: "semantic",
103253
+ handles: ["block_id", "node_slug", "ownership_role", "schema_version"],
103254
+ notes: "Intent compile diagnostics expose semantic block, node, role, and schema handles while keeping canonical decision expansion mechanical."
103255
+ },
102470
103256
  {
102471
103257
  source: "src/workflow/alignWorkflowSchemas.ts",
102472
103258
  family: "align schema example",
@@ -102736,8 +103522,8 @@ var COMMAND_MATRIX = [
102736
103522
  { command: "compile context", view: "production-semantic", handles: ["node_slug", "source_ref", "block_id", "payload"], notes: "Prepares one node context or source-ref view before drafting." },
102737
103523
  { command: "compile cycle", view: "production-semantic", handles: ["node_slug", "review_id", "workflow_id"], notes: "Runs one node through draft validation, prepare, safe review, and apply." },
102738
103524
  { command: "compile draft", view: "production-semantic", handles: ["node_slug", "source_ref", "payload"], notes: "Validates one compile draft from stdin in plan mode." },
103525
+ { command: "compile draft-patch", view: "production-semantic", handles: ["node_slug", "action_id", "operation"], notes: "Patches a saved compile draft session through semantic operations." },
102739
103526
  { command: "compile draft-status", view: "production-semantic", handles: ["node_slug", "payload"], notes: "Shows the current draft session for one node." },
102740
- { command: "compile draft-patch", view: "production-semantic", handles: ["node_slug", "payload"], notes: "Patches the current draft session for one node." },
102741
103527
  { command: "compile coverage", view: "production-semantic", handles: ["node_slug", "candidate_id", "payload"], notes: "Resolves coverage candidates through one node-scoped command." },
102742
103528
  { command: "compile close", view: "production-semantic", handles: ["workflow_id", "node_slug", "section_id"], notes: "Closes compile workflow after pending node work is settled." },
102743
103529
  { command: "reconcile", view: "production-semantic", handles: ["prepare_digest", "review_id", "scope_id"], notes: "Semantic reconciliation namespace." },
@@ -102923,6 +103709,13 @@ var AGENT_HINT_EMITTER_INVENTORY = [
102923
103709
  handles: ["workflow_payload", "prepare_digest", "review_id"],
102924
103710
  notes: "Reconcile errors route to previous semantic workflow step or schema."
102925
103711
  },
103712
+ {
103713
+ source: "src/commands/reconcilePrepareCandidateViews.ts",
103714
+ family: "reconcile prepare candidate views",
103715
+ policy: "semantic",
103716
+ handles: ["item_id", "candidate_id", "candidate_count"],
103717
+ notes: "Candidate index hints route agents from prepare item ids to scoped candidate detail views before semantic judgment."
103718
+ },
102926
103719
  {
102927
103720
  source: "src/commands/reconcilePrepareRefresh.ts",
102928
103721
  family: "reconcile stale prepare refresh",
@@ -105202,9 +105995,7 @@ function compileSchemaExample(name) {
105202
105995
  schema: "compile-draft-patch",
105203
105996
  schema_version: COMPILE_DRAFT_PATCH_SCHEMA_VERSION,
105204
105997
  consumed_by: [
105205
- "context compile draft-patch <slug> --input -",
105206
- "context compile cycle <slug> --input -",
105207
- "context compile cycle <slug> --continue --format json"
105998
+ "context compile cycle <slug> --input -"
105208
105999
  ],
105209
106000
  required: ["operations"],
105210
106001
  enums: {
@@ -105216,7 +106007,7 @@ function compileSchemaExample(name) {
105216
106007
  "The CLI reads the current draft session by default; add --payload-digest only when an explicit stale guard is needed.",
105217
106008
  "This is not the align finalize patch shape: do not use op/path/value JSON Pointer operations here.",
105218
106009
  "replace_action keeps the same action_id; add_action receives a new CLI-owned action_id.",
105219
- "When node-cycle returns partial-applied or review-required, the same node-cycle command may take this patch shape on stdin to patch the saved draft and continue the safe-default review/apply loop.",
106010
+ "When node-cycle returns partial-applied or review-required, submit this patch shape on stdin to context compile cycle <slug> --input - --format json to patch the saved draft and continue the safe-default review/apply loop.",
105220
106011
  "The CLI validates the whole patched draft before saving it, so failed patches do not corrupt the current draft session."
105221
106012
  ],
105222
106013
  example: {