@c4a/context-cli 0.5.35-alpha.3 → 0.5.35-beta.1
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 +501 -147
- package/package.json +1 -1
- package/plugin/commands/align.md +3 -0
- package/plugin/skills/skill-align-workflow/SKILL.md +3 -0
package/cli.js
CHANGED
|
@@ -45002,6 +45002,17 @@ function hasCitedFencedDetail(detail, basisTexts) {
|
|
|
45002
45002
|
return false;
|
|
45003
45003
|
return fencedBlocksIn(detail).some((block) => cited.includes(block));
|
|
45004
45004
|
}
|
|
45005
|
+
function fencedPayloadLines(block) {
|
|
45006
|
+
return block.split(/\r?\n/u).filter((line) => !/^\s*(?:```|~~~)/u.test(line)).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
45007
|
+
}
|
|
45008
|
+
function citedFencedDetailSupportsExcerpt(detail, basisTexts) {
|
|
45009
|
+
const citedBlocks = fencedBlocksIn(basisText(basisTexts));
|
|
45010
|
+
const detailBlocks = fencedBlocksIn(detail);
|
|
45011
|
+
return detailBlocks.length > 0 && detailBlocks.every((block) => citedBlocks.some((cited) => cited.includes(block) || fencedPayloadLines(block).every((line) => cited.includes(line))));
|
|
45012
|
+
}
|
|
45013
|
+
function stripFencedBlocks(value) {
|
|
45014
|
+
return value.replace(FENCED_DETAIL_BLOCK_RE, " ");
|
|
45015
|
+
}
|
|
45005
45016
|
var FENCED_DETAIL_BLOCK_RE;
|
|
45006
45017
|
var init_sectionDetail = __esm(() => {
|
|
45007
45018
|
init_normalize();
|
|
@@ -45235,13 +45246,18 @@ function sourceTextSupportDiagnostic(content3, citedText, thresholds = DEFAULT_T
|
|
|
45235
45246
|
function sourceSectionSupportDiagnostic(input) {
|
|
45236
45247
|
const detail = typeof input.detail === "string" ? input.detail.trim() : "";
|
|
45237
45248
|
const content3 = input.content;
|
|
45249
|
+
const thresholds = thresholdsForKind(input.kind);
|
|
45238
45250
|
if (detail.length === 0) {
|
|
45239
|
-
|
|
45240
|
-
|
|
45241
|
-
|
|
45242
|
-
|
|
45251
|
+
const diagnostic = sourceTextSupportDiagnostic(content3, input.citedText, thresholds);
|
|
45252
|
+
if (input.kind === "example" && diagnostic.verdict === "unsupported" && citedFencedDetailSupportsExcerpt(content3, input.citedText)) {
|
|
45253
|
+
const prose = stripFencedBlocks(content3).trim();
|
|
45254
|
+
const proseDiagnostic = prose.length === 0 ? { ...diagnostic, verdict: "supported", missingContentTerms: [], missingHardTerms: [] } : sourceTextSupportDiagnostic(prose, stripFencedBlocks(input.citedText), thresholds);
|
|
45255
|
+
if (prose.length === 0 || proseDiagnostic.verdict !== "unsupported" && proseDiagnostic.missingHardTerms.length === 0) {
|
|
45256
|
+
return { ...proseDiagnostic, checkedFields: ["content"] };
|
|
45257
|
+
}
|
|
45258
|
+
}
|
|
45259
|
+
return { ...diagnostic, checkedFields: ["content"] };
|
|
45243
45260
|
}
|
|
45244
|
-
const thresholds = thresholdsForKind(input.kind);
|
|
45245
45261
|
const contentDiagnostic = sourceTextSupportDiagnostic(content3, input.citedText, thresholds);
|
|
45246
45262
|
const detailDiagnostic = sourceTextSupportDiagnostic(detail, input.citedText, thresholds);
|
|
45247
45263
|
const combined = sourceTextSupportDiagnostic(`${content3}
|
|
@@ -46456,10 +46472,13 @@ function createCompileChangesOutput(input) {
|
|
|
46456
46472
|
let nodesChanged = 0;
|
|
46457
46473
|
let nonBlockingBlocksChanged = 0;
|
|
46458
46474
|
let nonBlockingNodesChanged = 0;
|
|
46475
|
+
const firstCompileSlugs = [];
|
|
46459
46476
|
for (const node3 of input.nodes) {
|
|
46460
46477
|
const actionableBlocks = blockingChangedBlocksForNode(node3);
|
|
46461
46478
|
const nonBlockingBlocks = nonBlockingChangedBlocksForNode(node3);
|
|
46462
46479
|
const locatorOnlyChanges = node3.locator_only_changes ?? [];
|
|
46480
|
+
if (node3.reason === "first-compile")
|
|
46481
|
+
firstCompileSlugs.push(node3.slug);
|
|
46463
46482
|
if (node3.reason === "first-compile" || actionableBlocks.length > 0 || locatorOnlyChanges.length > 0)
|
|
46464
46483
|
nodesChanged += 1;
|
|
46465
46484
|
if (nonBlockingBlocks.length > 0)
|
|
@@ -46475,6 +46494,7 @@ function createCompileChangesOutput(input) {
|
|
|
46475
46494
|
sectionsChanged.add(`${node3.slug}:${section}`);
|
|
46476
46495
|
}
|
|
46477
46496
|
}
|
|
46497
|
+
firstCompileSlugs.sort((left, right) => left.localeCompare(right));
|
|
46478
46498
|
const status = input.unknownInputs.length > 0 ? "unknown-input" : "ready";
|
|
46479
46499
|
return {
|
|
46480
46500
|
schema_version: INCREMENTAL_SCHEMA_VERSION,
|
|
@@ -46496,6 +46516,14 @@ function createCompileChangesOutput(input) {
|
|
|
46496
46516
|
unknown_inputs: input.unknownInputs.length,
|
|
46497
46517
|
partial: input.unknownInputs.length > 0
|
|
46498
46518
|
},
|
|
46519
|
+
...firstCompileSlugs.length > 0 ? {
|
|
46520
|
+
first_compile_pending: {
|
|
46521
|
+
remaining: firstCompileSlugs.length,
|
|
46522
|
+
remaining_slugs: firstCompileSlugs,
|
|
46523
|
+
commands: firstCompileSlugs.map((slug) => `context compile --context ${slug}`),
|
|
46524
|
+
next_action: "Compile each remaining first-compile Node before running context compile --close."
|
|
46525
|
+
}
|
|
46526
|
+
} : {},
|
|
46499
46527
|
nodes: input.nodes,
|
|
46500
46528
|
...input.ignoredLocatorChanges !== undefined && input.ignoredLocatorChanges.length > 0 ? { ignored_locator_changes: input.ignoredLocatorChanges } : {},
|
|
46501
46529
|
unknown_inputs: input.unknownInputs
|
|
@@ -46561,35 +46589,35 @@ var init_compileIgnoredSources = __esm(() => {
|
|
|
46561
46589
|
});
|
|
46562
46590
|
|
|
46563
46591
|
// src/workflow/compileChangesInputs.ts
|
|
46592
|
+
function alignNodeFromOwnership(node3) {
|
|
46593
|
+
return {
|
|
46594
|
+
slug: node3.slug,
|
|
46595
|
+
type: node3.type,
|
|
46596
|
+
sources: [...node3.sources],
|
|
46597
|
+
contextSources: [...node3.context_sources ?? []],
|
|
46598
|
+
hasExplicitSources: true,
|
|
46599
|
+
plannedSections: [...node3.planned_sections ?? []]
|
|
46600
|
+
};
|
|
46601
|
+
}
|
|
46564
46602
|
async function readAlignNodes(ctxDir) {
|
|
46565
46603
|
try {
|
|
46566
|
-
const
|
|
46567
|
-
|
|
46568
|
-
|
|
46569
|
-
|
|
46570
|
-
|
|
46571
|
-
|
|
46572
|
-
|
|
46573
|
-
|
|
46574
|
-
|
|
46575
|
-
|
|
46576
|
-
|
|
46577
|
-
|
|
46578
|
-
|
|
46579
|
-
}))
|
|
46580
|
-
};
|
|
46581
|
-
}
|
|
46604
|
+
const locatedNodes = await scanWorkspaceNodes(ctxDir);
|
|
46605
|
+
const nodes = new Map(locatedNodes.map((located) => [located.parsed.node.id, {
|
|
46606
|
+
slug: located.parsed.node.id,
|
|
46607
|
+
type: located.parsed.node.type,
|
|
46608
|
+
sources: [...located.parsed.node.sources],
|
|
46609
|
+
contextSources: [...located.parsed.node.context_sources ?? []],
|
|
46610
|
+
hasExplicitSources: true,
|
|
46611
|
+
plannedSections: [...located.parsed.node.planned_sections ?? []]
|
|
46612
|
+
}]));
|
|
46613
|
+
const ownership = await readCurrentSourceOwnership(ctxDir);
|
|
46614
|
+
for (const node3 of ownership?.nodes ?? []) {
|
|
46615
|
+
if (!nodes.has(node3.slug))
|
|
46616
|
+
nodes.set(node3.slug, alignNodeFromOwnership(node3));
|
|
46582
46617
|
}
|
|
46583
46618
|
return {
|
|
46584
46619
|
status: "ready",
|
|
46585
|
-
nodes: nodes.
|
|
46586
|
-
slug: located.parsed.node.id,
|
|
46587
|
-
type: located.parsed.node.type,
|
|
46588
|
-
sources: [...located.parsed.node.sources],
|
|
46589
|
-
contextSources: [...located.parsed.node.context_sources ?? []],
|
|
46590
|
-
hasExplicitSources: true,
|
|
46591
|
-
plannedSections: [...located.parsed.node.planned_sections ?? []]
|
|
46592
|
-
}))
|
|
46620
|
+
nodes: [...nodes.values()]
|
|
46593
46621
|
};
|
|
46594
46622
|
} catch {
|
|
46595
46623
|
return { status: "unknown-input", reason: "knowledge-scan-failed" };
|
|
@@ -49453,7 +49481,7 @@ function lineRangeText(range) {
|
|
|
49453
49481
|
return `${range.start}:${range.end}`;
|
|
49454
49482
|
}
|
|
49455
49483
|
function requestFullTextPageCommand(slug, blockId, range) {
|
|
49456
|
-
return `context compile --context ${slug} --request-full-text ${blockId} --request-full-text-range ${range} --format json`;
|
|
49484
|
+
return `context compile --context ${slug} --request-full-text ${blockId} --request-full-text-range ${range} --view text --format json`;
|
|
49457
49485
|
}
|
|
49458
49486
|
function isFenceLine(line) {
|
|
49459
49487
|
return /^\s*(```|~~~)/u.test(line);
|
|
@@ -49828,7 +49856,7 @@ function requestableFullTextBlockIds(ownership, slug) {
|
|
|
49828
49856
|
}
|
|
49829
49857
|
function requestFullTextCommand(slug, blockIds) {
|
|
49830
49858
|
const flags2 = blockIds.length > 0 ? blockIds.map((blockId) => ` --request-full-text ${blockId}`).join("") : " --request-full-text <block_id>";
|
|
49831
|
-
return `context compile --context ${slug}${flags2}`;
|
|
49859
|
+
return `context compile --context ${slug}${flags2} --view text --format json`;
|
|
49832
49860
|
}
|
|
49833
49861
|
function requestFullTextError(input) {
|
|
49834
49862
|
const hint = {
|
|
@@ -50033,7 +50061,7 @@ async function appendFinalizedBlock(input) {
|
|
|
50033
50061
|
request_full_text: {
|
|
50034
50062
|
available: true,
|
|
50035
50063
|
block_id: blockId,
|
|
50036
|
-
command_hint: `context compile --context ${input.nodeSlug} --request-full-text ${blockId}`
|
|
50064
|
+
command_hint: `context compile --context ${input.nodeSlug} --request-full-text ${blockId} --view text --format json`
|
|
50037
50065
|
}
|
|
50038
50066
|
} : {}
|
|
50039
50067
|
};
|
|
@@ -50254,7 +50282,7 @@ function compileContextRuntimeHints(context) {
|
|
|
50254
50282
|
message: `${expandableSecondaryBlockIds.length} secondary shared block(s) are compacted and not citation-eligible.`,
|
|
50255
50283
|
target_node: context.node.slug,
|
|
50256
50284
|
next_action: "Request full text only when you need to inspect background. Expanded secondary text still cannot support Section source_refs.",
|
|
50257
|
-
command: `context compile --context ${context.node.slug}${flags2}`,
|
|
50285
|
+
command: `context compile --context ${context.node.slug}${flags2} --view text --format json`,
|
|
50258
50286
|
available_block_ids: expandableSecondaryBlockIds
|
|
50259
50287
|
});
|
|
50260
50288
|
}
|
|
@@ -52747,6 +52775,23 @@ function nearbyCitationEligibleSourceRefs(input) {
|
|
|
52747
52775
|
})).filter((item) => item.distance <= 3).sort((left, right) => left.distance - right.distance || left.range.start - right.range.start);
|
|
52748
52776
|
return refs.slice(0, 8).map((item) => item.sourceRef);
|
|
52749
52777
|
}
|
|
52778
|
+
function suggestedSplitDraftActions(diagnostics) {
|
|
52779
|
+
const selectedBlocks = [...diagnostics.selected_blocks ?? []].sort((left, right) => left.manifest_index - right.manifest_index || left.source_ref.localeCompare(right.source_ref));
|
|
52780
|
+
if (selectedBlocks.length === 0) {
|
|
52781
|
+
return diagnostics.source_refs.map((sourceRef) => ({ op: "add", source_refs: [sourceRef] }));
|
|
52782
|
+
}
|
|
52783
|
+
const runs = [];
|
|
52784
|
+
for (const block of selectedBlocks) {
|
|
52785
|
+
const current = runs.at(-1);
|
|
52786
|
+
const previous3 = current?.at(-1);
|
|
52787
|
+
if (current === undefined || previous3 === undefined || block.manifest_index !== previous3.manifest_index + 1) {
|
|
52788
|
+
runs.push([block]);
|
|
52789
|
+
} else {
|
|
52790
|
+
current.push(block);
|
|
52791
|
+
}
|
|
52792
|
+
}
|
|
52793
|
+
return runs.map((run2) => ({ op: "add", source_refs: run2.map((block) => block.source_ref) }));
|
|
52794
|
+
}
|
|
52750
52795
|
function normalizedForRawCompare2(value) {
|
|
52751
52796
|
return normalizeMarkdown(value).trim();
|
|
52752
52797
|
}
|
|
@@ -52783,11 +52828,17 @@ async function assertResolvedSourceRefs(ctxDir, sourceRefs2, slug, context, labe
|
|
|
52783
52828
|
}
|
|
52784
52829
|
});
|
|
52785
52830
|
}
|
|
52831
|
+
const suggestedSplitActions = suggestedSplitDraftActions(diagnostics);
|
|
52786
52832
|
throw draftError(slug, context, `${label} could not be resolved to one contiguous source_ref; split the action or include every intervening citation-eligible source_ref`, {
|
|
52787
52833
|
path: label,
|
|
52788
52834
|
reasonCode: "source-refs-not-contiguous",
|
|
52789
52835
|
currentValue: sourceRefs2,
|
|
52790
|
-
diagnostics
|
|
52836
|
+
diagnostics: {
|
|
52837
|
+
...diagnostics,
|
|
52838
|
+
repair_options: ["split_by_contiguous_runs", "include_missing_intervening_source_refs"],
|
|
52839
|
+
...suggestedSplitActions.length > 1 ? { suggested_split_actions: suggestedSplitActions } : {},
|
|
52840
|
+
next_action: "Use suggested_split_actions as separate draft actions, or include every missing_intervening_blocks[].source_ref if one Section truly covers that intervening evidence."
|
|
52841
|
+
}
|
|
52791
52842
|
});
|
|
52792
52843
|
}
|
|
52793
52844
|
}
|
|
@@ -57303,7 +57354,7 @@ async function pathExistsNoFollow(path3) {
|
|
|
57303
57354
|
}
|
|
57304
57355
|
function displayLanguage(language) {
|
|
57305
57356
|
if (!language || language.trim().length === 0)
|
|
57306
|
-
return "
|
|
57357
|
+
return "English (default)";
|
|
57307
57358
|
const normalized = language.trim().toLowerCase();
|
|
57308
57359
|
if (["zh", "zh-cn", "chinese", "中文", "汉语"].includes(normalized))
|
|
57309
57360
|
return "Chinese";
|
|
@@ -57316,56 +57367,47 @@ function renderAgentsGuide(input) {
|
|
|
57316
57367
|
const projectRoot = location.layout === "embedded" ? ".." : ".";
|
|
57317
57368
|
return `# C4A Workspace Instructions
|
|
57318
57369
|
|
|
57319
|
-
This directory is the C4A data root
|
|
57320
|
-
|
|
57321
|
-
- Workspace
|
|
57322
|
-
-
|
|
57323
|
-
- Project root relative to this file
|
|
57324
|
-
-
|
|
57325
|
-
|
|
57326
|
-
|
|
57327
|
-
|
|
57328
|
-
|
|
57329
|
-
-
|
|
57330
|
-
-
|
|
57331
|
-
-
|
|
57332
|
-
|
|
57333
|
-
|
|
57334
|
-
|
|
57335
|
-
|
|
57336
|
-
|
|
57337
|
-
|
|
57338
|
-
|
|
57339
|
-
|
|
57340
|
-
|
|
57341
|
-
|
|
57342
|
-
|
|
57343
|
-
|
|
57344
|
-
|
|
57345
|
-
|
|
57346
|
-
|
|
57347
|
-
|
|
57348
|
-
|
|
57349
|
-
|
|
57350
|
-
|
|
57351
|
-
-
|
|
57352
|
-
-
|
|
57353
|
-
-
|
|
57354
|
-
-
|
|
57355
|
-
|
|
57356
|
-
|
|
57357
|
-
|
|
57358
|
-
-
|
|
57359
|
-
-
|
|
57360
|
-
- Users may intentionally edit \`config.yaml\` and \`aspects/*/prompt.md\`; after doing so, run \`context doctor\` or \`context status\`.
|
|
57361
|
-
- Use \`context doctor\`, \`context verify\`, and \`context status\` to inspect workspace health instead of inferring state from partial files.
|
|
57362
|
-
- \`context status\` is local-only and must be run from the workspace root. When an agent starts in a child directory, run \`context status\` from the project root or have the user reposition the shell; \`context workspace locate\` is a developer/debug fallback, not a normal production handoff.
|
|
57363
|
-
- Aspect prompts live under \`aspects/\` and are long-lived workspace files.
|
|
57364
|
-
|
|
57365
|
-
## Layout Notes
|
|
57366
|
-
|
|
57367
|
-
- \`embedded\` layout keeps this data root under the project \`.context/\` directory and is intended for normal code repositories.
|
|
57368
|
-
- \`root\` layout uses the current directory as the C4A data root. It is intended only for dedicated knowledge repositories; keep product source code outside this root unless you intentionally want C4A commands to treat it as part of the knowledge workspace.
|
|
57370
|
+
This directory is the C4A data root.
|
|
57371
|
+
|
|
57372
|
+
- Workspace: ${input.workspaceName}
|
|
57373
|
+
- Layout: ${location.layout}
|
|
57374
|
+
- Project root: \`${projectRoot}\` (relative to this file)
|
|
57375
|
+
- Language: ${displayLanguage(input.language)} (used for generated titles, summaries, and workflow reports)
|
|
57376
|
+
|
|
57377
|
+
## TL;DR — Non-negotiables
|
|
57378
|
+
|
|
57379
|
+
- **The CLI owns this data root.** All reads and writes go through \`context ...\` commands. Never use generic tools (\`Read\`, \`Glob\`, \`Grep\`, \`ls\`, \`find\`, \`cat\`, \`rg\`, \`head\`, \`tail\`, \`jq\`, \`sed\`, \`python3\`, \`node\`, shell pipes) against \`.context/**\`, \`output/**\`, \`archive/**\`, \`decisions/**\`, or \`/tmp\` files produced by C4A.
|
|
57380
|
+
- **Consume \`context ... --format json\` stdout directly.** Don't pipe it through \`jq\`, \`sed\`, \`cat\`, \`2>&1\`, or any wrapper.
|
|
57381
|
+
- **State-changing commands run sequentially.** Never run \`reconcile apply\`, \`compile --close\`, \`align --finalize\`, \`capture\`, \`drop\`, \`purge\`, or \`mdrive ... add|update|delete|supersede|deprecate\` in parallel against this workspace.
|
|
57382
|
+
- **Names are distinct.** \`/context:*\` = user slash command, \`context ...\` = CLI primitive, \`context:skill-*\` = packaged skill. Don't invent \`/context:skill-*\` or \`/context:compile-draft\`.
|
|
57383
|
+
|
|
57384
|
+
## Managed directories
|
|
57385
|
+
|
|
57386
|
+
These paths are CLI-owned. Hand-editing breaks the ledger, index, or cache.
|
|
57387
|
+
|
|
57388
|
+
| Path | Use this instead |
|
|
57389
|
+
|---|---|
|
|
57390
|
+
| \`raw/\`, \`raw/_sources.yaml\` | \`context capture\`, \`context capture --code\`, \`context source list|get\` |
|
|
57391
|
+
| \`knowledge/\`, \`knowledge/_index.md\`, \`knowledge/changelog.md\` | \`/context:compile\`, \`context mdrive ...\` |
|
|
57392
|
+
| \`decisions/semantic.yaml\` | \`context reconcile prepare|review|apply\` |
|
|
57393
|
+
| \`archive/\` | \`context drop\`, \`context purge\`, \`context capture\` restore |
|
|
57394
|
+
| \`config.yaml\`, \`aspects/*/prompt.md\` | hand-editing OK; run \`context doctor\` or \`context status\` afterward |
|
|
57395
|
+
|
|
57396
|
+
Workflow input goes through stdin (e.g. \`context align --finalize - <<'JSON'\`). Do not write scratch files under \`output/\` root or pipe heredocs through other commands.
|
|
57397
|
+
|
|
57398
|
+
## Discovery — trust the CLI, not this file
|
|
57399
|
+
|
|
57400
|
+
This file describes the workspace, not the workflows. For align / compile / drop procedures, follow the relevant \`/context:*\` slash command or \`context:skill-*\` skill. Command flags, view names, and schemas may evolve; ask the CLI:
|
|
57401
|
+
|
|
57402
|
+
- \`context status\` — current workspace state (run from project root)
|
|
57403
|
+
- \`context doctor\`, \`context verify\` — health checks
|
|
57404
|
+
- \`context schema <name>\` — input schemas with allowed enums and examples
|
|
57405
|
+
- \`context <cmd> --help\` — command flags and view options
|
|
57406
|
+
|
|
57407
|
+
## Layout
|
|
57408
|
+
|
|
57409
|
+
- **embedded** — data root lives at \`.context/\` under the project root. Normal code repositories.
|
|
57410
|
+
- **root** — data root is the current directory itself. Use only for dedicated knowledge repositories; keep product source code outside this root.
|
|
57369
57411
|
`;
|
|
57370
57412
|
}
|
|
57371
57413
|
async function writeAgentsGuide(input) {
|
|
@@ -57382,8 +57424,19 @@ async function writeAgentsGuide(input) {
|
|
|
57382
57424
|
}
|
|
57383
57425
|
let claudeLinkCreated = false;
|
|
57384
57426
|
if (!await pathExistsNoFollow(claudePath)) {
|
|
57385
|
-
|
|
57386
|
-
|
|
57427
|
+
try {
|
|
57428
|
+
await symlink("AGENTS.md", claudePath);
|
|
57429
|
+
claudeLinkCreated = true;
|
|
57430
|
+
} catch (err2) {
|
|
57431
|
+
const code3 = err2.code;
|
|
57432
|
+
if (code3 === "EPERM" || code3 === "EINVAL" || code3 === "ENOSYS") {
|
|
57433
|
+
await writeFile4(claudePath, `# See [AGENTS.md](./AGENTS.md)
|
|
57434
|
+
`, "utf8");
|
|
57435
|
+
claudeLinkCreated = true;
|
|
57436
|
+
} else {
|
|
57437
|
+
throw err2;
|
|
57438
|
+
}
|
|
57439
|
+
}
|
|
57387
57440
|
}
|
|
57388
57441
|
return { agentsPath, agentsWritten, claudePath, claudeLinkCreated };
|
|
57389
57442
|
}
|
|
@@ -66579,13 +66632,87 @@ function removeDroppedContextSources2(input) {
|
|
|
66579
66632
|
function shouldArchiveNode2(node3) {
|
|
66580
66633
|
return node3.sections.length === 0 && node3.children.length === 0 && node3.containsList.length === 0 && node3.body.trim().length === 0;
|
|
66581
66634
|
}
|
|
66635
|
+
function shouldArchiveDroppedCodeNavigationNode(node3, sourceSlug3) {
|
|
66636
|
+
return node3.node.code_package === sourceSlug3 && (node3.node.code_symbols?.length ?? 0) === 0 && node3.sections.length === 0 && node3.children.length === 0 && node3.body.trim().length === 0;
|
|
66637
|
+
}
|
|
66638
|
+
function archiveLocatedNode(input) {
|
|
66639
|
+
if (input.archivedSlugs.has(input.located.parsed.node.id))
|
|
66640
|
+
return;
|
|
66641
|
+
if (input.located.path.length === 0) {
|
|
66642
|
+
input.deletedFiles.add(input.located.filePath);
|
|
66643
|
+
} else {
|
|
66644
|
+
detachNodeAtPath(input.located.root, input.located.path);
|
|
66645
|
+
input.touchedFiles.add(input.located.filePath);
|
|
66646
|
+
}
|
|
66647
|
+
input.archivedSlugs.add(input.located.parsed.node.id);
|
|
66648
|
+
}
|
|
66649
|
+
function archiveEmptyAffectedNodes(input) {
|
|
66650
|
+
let changed = false;
|
|
66651
|
+
for (const located of input.nodes) {
|
|
66652
|
+
if (!input.affectedSlugs.has(located.parsed.node.id))
|
|
66653
|
+
continue;
|
|
66654
|
+
if (input.archivedSlugs.has(located.parsed.node.id))
|
|
66655
|
+
continue;
|
|
66656
|
+
if (!shouldArchiveNode2(located.parsed))
|
|
66657
|
+
continue;
|
|
66658
|
+
archiveLocatedNode({
|
|
66659
|
+
located,
|
|
66660
|
+
deletedFiles: input.deletedFiles,
|
|
66661
|
+
touchedFiles: input.touchedFiles,
|
|
66662
|
+
archivedSlugs: input.archivedSlugs
|
|
66663
|
+
});
|
|
66664
|
+
changed = true;
|
|
66665
|
+
}
|
|
66666
|
+
return changed;
|
|
66667
|
+
}
|
|
66668
|
+
function archiveDroppedCodeNavigationNodes(input) {
|
|
66669
|
+
let changed = false;
|
|
66670
|
+
for (const located of input.nodes) {
|
|
66671
|
+
if (input.archivedSlugs.has(located.parsed.node.id))
|
|
66672
|
+
continue;
|
|
66673
|
+
if (!shouldArchiveDroppedCodeNavigationNode(located.parsed, input.sourceSlug))
|
|
66674
|
+
continue;
|
|
66675
|
+
archiveLocatedNode({
|
|
66676
|
+
located,
|
|
66677
|
+
deletedFiles: input.deletedFiles,
|
|
66678
|
+
touchedFiles: input.touchedFiles,
|
|
66679
|
+
archivedSlugs: input.archivedSlugs
|
|
66680
|
+
});
|
|
66681
|
+
changed = true;
|
|
66682
|
+
}
|
|
66683
|
+
return changed;
|
|
66684
|
+
}
|
|
66685
|
+
function containsEntryTargetSlug(parentSlug, entry) {
|
|
66686
|
+
const href = entry.href.split(/[?#]/u)[0]?.replace(/^\.\//u, "").replace(/\.md$/u, "") ?? "";
|
|
66687
|
+
if (href.length === 0 || /^[a-z][a-z0-9+.-]*:/iu.test(href))
|
|
66688
|
+
return entry.slug.length > 0 ? entry.slug : null;
|
|
66689
|
+
const parentParts = parentSlug.split("/").filter((part) => part.length > 0);
|
|
66690
|
+
const rootSlug = parentParts[0] ?? "";
|
|
66691
|
+
if (href === rootSlug || href.startsWith(`${rootSlug}/`))
|
|
66692
|
+
return href;
|
|
66693
|
+
if (rootSlug.length > 0 && href.startsWith("symbol/"))
|
|
66694
|
+
return `${rootSlug}/${href}`;
|
|
66695
|
+
if (parentParts.length > 1)
|
|
66696
|
+
return `${parentParts.slice(0, -1).join("/")}/${href}`;
|
|
66697
|
+
return rootSlug.length > 0 ? `${rootSlug}/${href}` : href;
|
|
66698
|
+
}
|
|
66699
|
+
function containsEntryMatchesArchivedSlug(parentSlug, entry, archivedSlug) {
|
|
66700
|
+
if (entry.slug === archivedSlug)
|
|
66701
|
+
return true;
|
|
66702
|
+
return containsEntryTargetSlug(parentSlug, entry) === archivedSlug;
|
|
66703
|
+
}
|
|
66582
66704
|
function removeReferencesToArchivedNodes2(input) {
|
|
66583
66705
|
if (input.archivedSlugs.size === 0)
|
|
66584
66706
|
return;
|
|
66585
66707
|
const visit2 = (filePath, node3) => {
|
|
66586
66708
|
const beforeContains = node3.containsList.length;
|
|
66587
|
-
|
|
66588
|
-
|
|
66709
|
+
node3.containsList = node3.containsList.filter((entry) => {
|
|
66710
|
+
for (const slug of input.archivedSlugs) {
|
|
66711
|
+
if (containsEntryMatchesArchivedSlug(node3.node.id, entry, slug))
|
|
66712
|
+
return false;
|
|
66713
|
+
}
|
|
66714
|
+
return true;
|
|
66715
|
+
});
|
|
66589
66716
|
if (node3.containsList.length !== beforeContains)
|
|
66590
66717
|
input.touchedFiles.add(filePath);
|
|
66591
66718
|
for (const section of node3.sections) {
|
|
@@ -66717,6 +66844,8 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
66717
66844
|
const touchedFiles = new Set;
|
|
66718
66845
|
const deletedFiles = new Set;
|
|
66719
66846
|
const archivedSlugs = new Set;
|
|
66847
|
+
const affectedSlugs = new Set(plan.affected_nodes.map((node3) => node3.slug));
|
|
66848
|
+
const sourceSlug3 = codeSourceSlug(source2);
|
|
66720
66849
|
let removedSections = 0;
|
|
66721
66850
|
let reindexedSections = 0;
|
|
66722
66851
|
for (const planNode of plan.affected_nodes) {
|
|
@@ -66727,17 +66856,32 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
66727
66856
|
removedSections += result.removedSections;
|
|
66728
66857
|
reindexedSections += result.reindexedSections;
|
|
66729
66858
|
if (result.archiveNode && located.path.length === 0) {
|
|
66730
|
-
|
|
66731
|
-
archivedSlugs.add(located.parsed.node.id);
|
|
66859
|
+
archiveLocatedNode({ located, deletedFiles, touchedFiles, archivedSlugs });
|
|
66732
66860
|
} else if (result.archiveNode) {
|
|
66733
|
-
|
|
66734
|
-
touchedFiles.add(located.filePath);
|
|
66735
|
-
archivedSlugs.add(located.parsed.node.id);
|
|
66861
|
+
archiveLocatedNode({ located, deletedFiles, touchedFiles, archivedSlugs });
|
|
66736
66862
|
} else if (result.removedSections > 0 || result.reindexedSections > 0) {
|
|
66737
66863
|
touchedFiles.add(located.filePath);
|
|
66738
66864
|
}
|
|
66739
66865
|
}
|
|
66740
|
-
|
|
66866
|
+
while (true) {
|
|
66867
|
+
removeReferencesToArchivedNodes2({ files, archivedSlugs, touchedFiles });
|
|
66868
|
+
const changed = archiveEmptyAffectedNodes({
|
|
66869
|
+
nodes,
|
|
66870
|
+
affectedSlugs,
|
|
66871
|
+
deletedFiles,
|
|
66872
|
+
touchedFiles,
|
|
66873
|
+
archivedSlugs
|
|
66874
|
+
});
|
|
66875
|
+
const changedNavigation = archiveDroppedCodeNavigationNodes({
|
|
66876
|
+
nodes,
|
|
66877
|
+
sourceSlug: sourceSlug3,
|
|
66878
|
+
deletedFiles,
|
|
66879
|
+
touchedFiles,
|
|
66880
|
+
archivedSlugs
|
|
66881
|
+
});
|
|
66882
|
+
if (!changed && !changedNavigation)
|
|
66883
|
+
break;
|
|
66884
|
+
}
|
|
66741
66885
|
removeDroppedContextSources2({ files, sourceId: source2.id, deletedFiles, touchedFiles });
|
|
66742
66886
|
const owners = new Set;
|
|
66743
66887
|
for (const node3 of plan.affected_nodes)
|
|
@@ -66758,7 +66902,7 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
66758
66902
|
touchedKnowledgeFiles,
|
|
66759
66903
|
plan
|
|
66760
66904
|
});
|
|
66761
|
-
await replaceCodeGraphEdges(input.ctxDir, `code:${
|
|
66905
|
+
await replaceCodeGraphEdges(input.ctxDir, `code:${sourceSlug3}`, []);
|
|
66762
66906
|
await replaceExternalDepsForOwners(input.ctxDir, [], owners);
|
|
66763
66907
|
const renderContext = touchedFiles.size > 0 ? await buildRenderWorkspaceContext(input.ctxDir, files.filter((file) => !deletedFiles.has(file.filePath))) : undefined;
|
|
66764
66908
|
for (const filePath of touchedFiles) {
|
|
@@ -77458,7 +77602,7 @@ function nodeContextSourceRefRows(value) {
|
|
|
77458
77602
|
citation_eligible: snippet.citation_eligible === true,
|
|
77459
77603
|
context_only: snippet.context_only === true,
|
|
77460
77604
|
...quotePreview !== undefined ? { quote_preview: quotePreview } : {},
|
|
77461
|
-
...node3 !== undefined && blockId !== undefined && canRequestFullTextForSnippet(snippet) ? { request_full_text_command: `context compile --context ${shellQuote(node3)} --request-full-text ${shellQuote(blockId)} --format json` } : {}
|
|
77605
|
+
...node3 !== undefined && blockId !== undefined && canRequestFullTextForSnippet(snippet) ? { request_full_text_command: `context compile --context ${shellQuote(node3)} --request-full-text ${shellQuote(blockId)} --view text --format json` } : {}
|
|
77462
77606
|
};
|
|
77463
77607
|
});
|
|
77464
77608
|
}
|
|
@@ -84551,10 +84695,115 @@ function plannedSectionSourceRefGroups(context, rows) {
|
|
|
84551
84695
|
source_refs: run2.map((row) => row.source_ref)
|
|
84552
84696
|
})),
|
|
84553
84697
|
draft_action_templates: templates,
|
|
84554
|
-
draft_action_template: templates[0] ?? draftActionTemplate(plan.section_kind, [])
|
|
84698
|
+
...status === "ready_with_splits" ? {} : { draft_action_template: templates[0] ?? draftActionTemplate(plan.section_kind, []) }
|
|
84699
|
+
};
|
|
84700
|
+
});
|
|
84701
|
+
}
|
|
84702
|
+
|
|
84703
|
+
// src/commands/compileSourceRefsCodeText.ts
|
|
84704
|
+
function recordArray(value) {
|
|
84705
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)) : [];
|
|
84706
|
+
}
|
|
84707
|
+
function exampleSourceRefs(sectionGroups) {
|
|
84708
|
+
const refs = new Set;
|
|
84709
|
+
for (const group of sectionGroups) {
|
|
84710
|
+
if (group.section_kind !== "example")
|
|
84711
|
+
continue;
|
|
84712
|
+
for (const sourceRef of Array.isArray(group.source_refs) ? group.source_refs : []) {
|
|
84713
|
+
if (typeof sourceRef === "string")
|
|
84714
|
+
refs.add(sourceRef);
|
|
84715
|
+
}
|
|
84716
|
+
}
|
|
84717
|
+
return refs;
|
|
84718
|
+
}
|
|
84719
|
+
function fencedCodeTextBySourceRef(context) {
|
|
84720
|
+
const out2 = new Map;
|
|
84721
|
+
for (const snippet of context.raw_snippets) {
|
|
84722
|
+
if (typeof snippet.source_ref !== "string" || typeof snippet.quote !== "string")
|
|
84723
|
+
continue;
|
|
84724
|
+
if (!/```[\s\S]*```/u.test(snippet.quote))
|
|
84725
|
+
continue;
|
|
84726
|
+
out2.set(snippet.source_ref, snippet.quote);
|
|
84727
|
+
}
|
|
84728
|
+
return out2;
|
|
84729
|
+
}
|
|
84730
|
+
function enrichRows(rows, exampleRefs, fullTextBySourceRef) {
|
|
84731
|
+
return recordArray(rows).map((row) => {
|
|
84732
|
+
const sourceRef = typeof row.source_ref === "string" ? row.source_ref : undefined;
|
|
84733
|
+
const fullText = sourceRef !== undefined && exampleRefs.has(sourceRef) ? fullTextBySourceRef.get(sourceRef) : undefined;
|
|
84734
|
+
if (fullText === undefined)
|
|
84735
|
+
return row;
|
|
84736
|
+
return {
|
|
84737
|
+
...row,
|
|
84738
|
+
quote_full_text: fullText,
|
|
84739
|
+
quote_full_text_reason: "example-code-block",
|
|
84740
|
+
quote_full_text_field: "items[].quote_full_text"
|
|
84555
84741
|
};
|
|
84556
84742
|
});
|
|
84557
84743
|
}
|
|
84744
|
+
function withExampleCodeFullText(input) {
|
|
84745
|
+
const exampleRefs = exampleSourceRefs(input.sectionGroups);
|
|
84746
|
+
if (exampleRefs.size === 0)
|
|
84747
|
+
return input.projected;
|
|
84748
|
+
const fullTextBySourceRef = fencedCodeTextBySourceRef(input.context);
|
|
84749
|
+
if (fullTextBySourceRef.size === 0)
|
|
84750
|
+
return input.projected;
|
|
84751
|
+
return {
|
|
84752
|
+
...input.projected,
|
|
84753
|
+
items: enrichRows(input.projected.items, exampleRefs, fullTextBySourceRef),
|
|
84754
|
+
context_items: enrichRows(input.projected.context_items, exampleRefs, fullTextBySourceRef)
|
|
84755
|
+
};
|
|
84756
|
+
}
|
|
84757
|
+
|
|
84758
|
+
// src/commands/compileSourceRefsScaffold.ts
|
|
84759
|
+
init_compile();
|
|
84760
|
+
function recordArray2(value) {
|
|
84761
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)) : [];
|
|
84762
|
+
}
|
|
84763
|
+
function stringArray7(value) {
|
|
84764
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
84765
|
+
}
|
|
84766
|
+
function defaultScaffoldSectionKind(context) {
|
|
84767
|
+
return context.node.planned_sections?.[0] ?? "description";
|
|
84768
|
+
}
|
|
84769
|
+
function plannedTemplateActions(sectionGroups) {
|
|
84770
|
+
return sectionGroups.filter((group) => group.status === "ready" || group.status === "ready_with_splits").flatMap((group) => recordArray2(group.draft_action_templates));
|
|
84771
|
+
}
|
|
84772
|
+
function sourceRefsDraftScaffold(input) {
|
|
84773
|
+
const requested = new Set(input.requestedBlockIds ?? []);
|
|
84774
|
+
const plannedActions = requested.size === 0 ? plannedTemplateActions(input.sectionGroups) : [];
|
|
84775
|
+
if (plannedActions.length > 0) {
|
|
84776
|
+
return {
|
|
84777
|
+
schema_version: COMPILE_DRAFT_SCHEMA_VERSION,
|
|
84778
|
+
target_node: input.context.node.slug,
|
|
84779
|
+
selection: {
|
|
84780
|
+
mode: "planned_section_groups",
|
|
84781
|
+
selected_action_count: plannedActions.length,
|
|
84782
|
+
planned_section_groups: input.sectionGroups.filter((group) => group.status === "ready" || group.status === "ready_with_splits").map((group) => group.section_id).filter((sectionId) => typeof sectionId === "string")
|
|
84783
|
+
},
|
|
84784
|
+
usage: "Fill each action.content, adjust kind when needed, then submit the actions with context compile --draft <node> --input - --plan.",
|
|
84785
|
+
actions: plannedActions.map((action) => ({ ...action }))
|
|
84786
|
+
};
|
|
84787
|
+
}
|
|
84788
|
+
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)));
|
|
84789
|
+
const kind = defaultScaffoldSectionKind(input.context);
|
|
84790
|
+
return {
|
|
84791
|
+
schema_version: COMPILE_DRAFT_SCHEMA_VERSION,
|
|
84792
|
+
target_node: input.context.node.slug,
|
|
84793
|
+
selection: {
|
|
84794
|
+
mode: requested.size > 0 ? "requested_block_ids" : "visible_citation_eligible_source_refs",
|
|
84795
|
+
selected_action_count: selectedRows.length,
|
|
84796
|
+
...requested.size > 0 ? { requested_block_ids: [...requested] } : {}
|
|
84797
|
+
},
|
|
84798
|
+
usage: "Fill each action.content, adjust kind when needed, then submit the actions with context compile --draft <node> --input - --plan.",
|
|
84799
|
+
actions: selectedRows.map((row) => ({
|
|
84800
|
+
op: "add",
|
|
84801
|
+
kind,
|
|
84802
|
+
content: "",
|
|
84803
|
+
source_refs: stringArray7([row.source_ref])
|
|
84804
|
+
}))
|
|
84805
|
+
};
|
|
84806
|
+
}
|
|
84558
84807
|
|
|
84559
84808
|
// src/commands/compileWorkflowViews.ts
|
|
84560
84809
|
function compileChangesFormat(value) {
|
|
@@ -84576,12 +84825,17 @@ function compileOutputView(value) {
|
|
|
84576
84825
|
return "source-refs";
|
|
84577
84826
|
if (value === "issues")
|
|
84578
84827
|
return "issues";
|
|
84579
|
-
|
|
84828
|
+
if (value === "text")
|
|
84829
|
+
return "text";
|
|
84830
|
+
throw new ContextError(ExitCode.UserError, "--view must be full, summary, source-refs, issues, or text", {
|
|
84580
84831
|
category: ErrorCategory.UserInputInvalid,
|
|
84581
84832
|
flag: "--view"
|
|
84582
84833
|
});
|
|
84583
84834
|
}
|
|
84584
84835
|
function compileChangesNextHint(changes) {
|
|
84836
|
+
if (changes.first_compile_pending !== undefined && changes.first_compile_pending.remaining > 0) {
|
|
84837
|
+
return `${changes.first_compile_pending.remaining} first-compile node(s) remain; run first_compile_pending.commands[] before context compile --close`;
|
|
84838
|
+
}
|
|
84585
84839
|
if (changes.reason === "no-changed-nodes") {
|
|
84586
84840
|
if ((changes.stats.non_blocking_blocks_changed ?? 0) > 0) {
|
|
84587
84841
|
return "only non-blocking context/source changes were detected; compile draft can stop";
|
|
@@ -84610,6 +84864,11 @@ function compileChangesNextHint(changes) {
|
|
|
84610
84864
|
}
|
|
84611
84865
|
function compileChangesNext(changes) {
|
|
84612
84866
|
const reason = compileChangesNextHint(changes);
|
|
84867
|
+
if (changes.first_compile_pending !== undefined && changes.first_compile_pending.commands.length > 0) {
|
|
84868
|
+
const command = changes.first_compile_pending.commands[0];
|
|
84869
|
+
if (command !== undefined)
|
|
84870
|
+
return { command, reason };
|
|
84871
|
+
}
|
|
84613
84872
|
if (changes.reason === "no-changed-nodes")
|
|
84614
84873
|
return { reason };
|
|
84615
84874
|
if (changes.status === "unknown-input") {
|
|
@@ -84659,6 +84918,7 @@ function compactCompileChanges(changes) {
|
|
|
84659
84918
|
unknown_input_count: node3.unknown_inputs.length,
|
|
84660
84919
|
source_ids: [...new Set(node3.changed_blocks.map((block) => block.source_id))]
|
|
84661
84920
|
})),
|
|
84921
|
+
...changes.first_compile_pending !== undefined ? { first_compile_pending: changes.first_compile_pending } : {},
|
|
84662
84922
|
ignored_locator_change_count: changes.ignored_locator_changes?.length ?? 0,
|
|
84663
84923
|
unknown_inputs: changes.unknown_inputs
|
|
84664
84924
|
};
|
|
@@ -84826,14 +85086,14 @@ function writeCompileContextSummary(input) {
|
|
|
84826
85086
|
}
|
|
84827
85087
|
writeCompileContextTextSummary(input, coverageRepairRound, coverageScopeHint);
|
|
84828
85088
|
}
|
|
84829
|
-
function
|
|
85089
|
+
function recordArray3(value) {
|
|
84830
85090
|
return Array.isArray(value) ? value.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)) : [];
|
|
84831
85091
|
}
|
|
84832
85092
|
function objectRecord(value) {
|
|
84833
85093
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
84834
85094
|
}
|
|
84835
85095
|
function projectedSourceRefRows(value) {
|
|
84836
|
-
return
|
|
85096
|
+
return recordArray3(value.items).concat(recordArray3(value.context_items)).filter((row) => typeof row.source_ref === "string" && typeof row.block_id === "string" && typeof row.citation_eligible === "boolean");
|
|
84837
85097
|
}
|
|
84838
85098
|
function compileSourceRefsBaseCommand(slug) {
|
|
84839
85099
|
return `context compile --context ${shellQuote(slug)} --view source-refs --format json`;
|
|
@@ -84849,30 +85109,6 @@ function sourceRefsDraftScaffoldCommand(slug, options = {}) {
|
|
|
84849
85109
|
"--format json"
|
|
84850
85110
|
].join(" ");
|
|
84851
85111
|
}
|
|
84852
|
-
function defaultScaffoldSectionKind(context) {
|
|
84853
|
-
return context.node.planned_sections?.[0] ?? "description";
|
|
84854
|
-
}
|
|
84855
|
-
function sourceRefsDraftScaffold(input) {
|
|
84856
|
-
const requested = new Set(input.requestedBlockIds ?? []);
|
|
84857
|
-
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)));
|
|
84858
|
-
const kind = defaultScaffoldSectionKind(input.context);
|
|
84859
|
-
return {
|
|
84860
|
-
schema_version: COMPILE_DRAFT_SCHEMA_VERSION,
|
|
84861
|
-
target_node: input.context.node.slug,
|
|
84862
|
-
selection: {
|
|
84863
|
-
mode: requested.size > 0 ? "requested_block_ids" : "visible_citation_eligible_source_refs",
|
|
84864
|
-
selected_action_count: selectedRows.length,
|
|
84865
|
-
...requested.size > 0 ? { requested_block_ids: [...requested] } : {}
|
|
84866
|
-
},
|
|
84867
|
-
usage: "Fill each action.content, adjust kind when needed, then submit the actions with context compile --draft <node> --input - --plan.",
|
|
84868
|
-
actions: selectedRows.map((row) => ({
|
|
84869
|
-
op: "add",
|
|
84870
|
-
kind,
|
|
84871
|
-
content: "",
|
|
84872
|
-
source_refs: [row.source_ref]
|
|
84873
|
-
}))
|
|
84874
|
-
};
|
|
84875
|
-
}
|
|
84876
85112
|
function sourceRefsSectionGroupHint(sectionGroups) {
|
|
84877
85113
|
if (sectionGroups.length === 0)
|
|
84878
85114
|
return [];
|
|
@@ -84918,16 +85154,18 @@ function sourceRefsViewHints(input) {
|
|
|
84918
85154
|
}
|
|
84919
85155
|
function writeCompileSourceRefs(context, format, options = {}) {
|
|
84920
85156
|
const projected = projectNodeContextSourceRefs(context, options, compileSourceRefsBaseCommand(context.node.slug));
|
|
84921
|
-
const projectedHints =
|
|
85157
|
+
const projectedHints = recordArray3(projected.agent_hints);
|
|
84922
85158
|
const projectedCounts = objectRecord(projected.counts);
|
|
84923
|
-
const windowRows =
|
|
85159
|
+
const windowRows = recordArray3(projected.items).concat(recordArray3(projected.context_items));
|
|
84924
85160
|
const sectionGroups = plannedSectionSourceRefGroups(context, projectedSourceRefRows(projected));
|
|
85161
|
+
const projectedForOutput = withExampleCodeFullText({ projected, context, sectionGroups });
|
|
84925
85162
|
const draftScaffoldCommand = sourceRefsDraftScaffoldCommand(context.node.slug, options);
|
|
84926
85163
|
const requestedScaffoldBlockIds = options.draftScaffoldBlockIds ?? [];
|
|
84927
|
-
const scaffoldRows = requestedScaffoldBlockIds.length > 0 ?
|
|
85164
|
+
const scaffoldRows = requestedScaffoldBlockIds.length > 0 ? recordArray3(context.raw_snippets) : windowRows;
|
|
84928
85165
|
const draftScaffold = options.draftScaffold === true ? sourceRefsDraftScaffold({
|
|
84929
85166
|
context,
|
|
84930
85167
|
rows: scaffoldRows,
|
|
85168
|
+
sectionGroups,
|
|
84931
85169
|
...requestedScaffoldBlockIds.length > 0 ? { requestedBlockIds: requestedScaffoldBlockIds } : {}
|
|
84932
85170
|
}) : undefined;
|
|
84933
85171
|
const scaffoldHint = {
|
|
@@ -84940,7 +85178,7 @@ function writeCompileSourceRefs(context, format, options = {}) {
|
|
|
84940
85178
|
const viewHints = sourceRefsViewHints({ projectedHints, sectionGroups, scaffoldHint });
|
|
84941
85179
|
if (format === "json") {
|
|
84942
85180
|
writeJson3({
|
|
84943
|
-
...
|
|
85181
|
+
...projectedForOutput,
|
|
84944
85182
|
...sectionGroups.length > 0 ? { planned_section_groups: sectionGroups } : {},
|
|
84945
85183
|
draft_scaffold_command: draftScaffoldCommand,
|
|
84946
85184
|
...draftScaffold !== undefined ? { draft_scaffold: draftScaffold } : {},
|
|
@@ -84949,7 +85187,7 @@ function writeCompileSourceRefs(context, format, options = {}) {
|
|
|
84949
85187
|
planned_section_groups: sectionGroups.length,
|
|
84950
85188
|
planned_section_groups_ready: sectionGroups.filter((group) => group.status === "ready" || group.status === "ready_with_splits").length,
|
|
84951
85189
|
planned_section_groups_split: sectionGroups.filter((group) => group.status === "ready_with_splits").length,
|
|
84952
|
-
...draftScaffold !== undefined ? { draft_scaffold_actions:
|
|
85190
|
+
...draftScaffold !== undefined ? { draft_scaffold_actions: recordArray3(draftScaffold.actions).length } : {}
|
|
84953
85191
|
},
|
|
84954
85192
|
agent_hints: viewHints
|
|
84955
85193
|
});
|
|
@@ -85041,7 +85279,7 @@ function writeCompileDraftStatus(input) {
|
|
|
85041
85279
|
function claimIdForActionIndex(index2) {
|
|
85042
85280
|
return `claim-${String(index2 + 1).padStart(3, "0")}`;
|
|
85043
85281
|
}
|
|
85044
|
-
function
|
|
85282
|
+
function stringArray8(value) {
|
|
85045
85283
|
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
85046
85284
|
}
|
|
85047
85285
|
function sourceRefNarrowingByActionIndex(hints) {
|
|
@@ -85050,9 +85288,9 @@ function sourceRefNarrowingByActionIndex(hints) {
|
|
|
85050
85288
|
if (hint.code !== "compile-source-refs-narrowing-suggested" || typeof hint.op_index !== "number")
|
|
85051
85289
|
continue;
|
|
85052
85290
|
const diagnostics = hint.diagnostics ?? {};
|
|
85053
|
-
const original =
|
|
85054
|
-
const narrowed =
|
|
85055
|
-
const removed =
|
|
85291
|
+
const original = stringArray8(diagnostics.original_source_refs);
|
|
85292
|
+
const narrowed = stringArray8(diagnostics.narrowed_source_refs);
|
|
85293
|
+
const removed = stringArray8(diagnostics.removed_source_refs);
|
|
85056
85294
|
if (original.length === 0 || narrowed.length === 0 || removed.length === 0)
|
|
85057
85295
|
continue;
|
|
85058
85296
|
byIndex.set(hint.op_index, {
|
|
@@ -85070,8 +85308,8 @@ function sourceRefNarrowingByActionIndex(hints) {
|
|
|
85070
85308
|
function sourceSupportDiagnostics(support) {
|
|
85071
85309
|
if (support?.verdict === undefined || support.verdict === "supported")
|
|
85072
85310
|
return;
|
|
85073
|
-
const missingHardTerms =
|
|
85074
|
-
const missingContentTerms =
|
|
85311
|
+
const missingHardTerms = stringArray8(support.missing_hard_terms);
|
|
85312
|
+
const missingContentTerms = stringArray8(support.missing_content_terms);
|
|
85075
85313
|
const contextOnlyMatches = Array.isArray(support.context_only_hard_term_matches) ? support.context_only_hard_term_matches.slice(0, 12).map((match) => ({
|
|
85076
85314
|
...typeof match.term === "string" ? { term: match.term } : {},
|
|
85077
85315
|
...typeof match.line_range === "string" ? { line_range: match.line_range } : {},
|
|
@@ -85163,11 +85401,11 @@ function withPayloadMeta2(value, payload) {
|
|
|
85163
85401
|
})
|
|
85164
85402
|
};
|
|
85165
85403
|
}
|
|
85166
|
-
function
|
|
85404
|
+
function stringArray9(value) {
|
|
85167
85405
|
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
85168
85406
|
}
|
|
85169
85407
|
function narrowingSuggestionRemovedCount(context) {
|
|
85170
|
-
return (context.agent_hints ?? []).filter((hint) => hint.code === "compile-source-refs-narrowing-suggested").reduce((sum, hint) => sum +
|
|
85408
|
+
return (context.agent_hints ?? []).filter((hint) => hint.code === "compile-source-refs-narrowing-suggested").reduce((sum, hint) => sum + stringArray9(hint.diagnostics?.removed_source_refs).length, 0);
|
|
85171
85409
|
}
|
|
85172
85410
|
function prepareViewFromCompileView(view, viewWasExplicit) {
|
|
85173
85411
|
if (view === "source-refs") {
|
|
@@ -85342,7 +85580,7 @@ async function writeCompileDraftChallengePayloads2(input) {
|
|
|
85342
85580
|
});
|
|
85343
85581
|
}
|
|
85344
85582
|
}
|
|
85345
|
-
function
|
|
85583
|
+
function stringArray10(value) {
|
|
85346
85584
|
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
85347
85585
|
}
|
|
85348
85586
|
function preparedSourceSupportStatus(value) {
|
|
@@ -85350,8 +85588,8 @@ function preparedSourceSupportStatus(value) {
|
|
|
85350
85588
|
return;
|
|
85351
85589
|
if (value.verdict === "supported")
|
|
85352
85590
|
return { verdict: value.verdict };
|
|
85353
|
-
const missingHardTerms =
|
|
85354
|
-
const missingContentTerms =
|
|
85591
|
+
const missingHardTerms = stringArray10(value.missing_hard_terms);
|
|
85592
|
+
const missingContentTerms = stringArray10(value.missing_content_terms);
|
|
85355
85593
|
return {
|
|
85356
85594
|
verdict: value.verdict,
|
|
85357
85595
|
...missingHardTerms.length > 0 ? { missing_hard_terms: missingHardTerms } : {},
|
|
@@ -85666,6 +85904,78 @@ async function runCompileDraftCommand(input) {
|
|
|
85666
85904
|
return false;
|
|
85667
85905
|
}
|
|
85668
85906
|
|
|
85907
|
+
// src/commands/compileRequestFullTextView.ts
|
|
85908
|
+
function textViewNextCommand(command) {
|
|
85909
|
+
if (command === undefined)
|
|
85910
|
+
return;
|
|
85911
|
+
if (command.includes("--view text"))
|
|
85912
|
+
return command;
|
|
85913
|
+
if (command.includes("--format json"))
|
|
85914
|
+
return command.replace("--format json", "--view text --format json");
|
|
85915
|
+
return `${command} --view text`;
|
|
85916
|
+
}
|
|
85917
|
+
function pageItem(context, page) {
|
|
85918
|
+
const snippet = context.raw_snippets[page.raw_snippet_index];
|
|
85919
|
+
const nextCommand2 = textViewNextCommand(page.next_command);
|
|
85920
|
+
return {
|
|
85921
|
+
block_id: snippet?.block_id ?? context.request_full_text?.requested_block_ids[0] ?? "<unknown>",
|
|
85922
|
+
raw_snippet_index: page.raw_snippet_index,
|
|
85923
|
+
...page.source_ref !== undefined || snippet?.source_ref !== undefined ? { source_ref: page.source_ref ?? snippet?.source_ref } : {},
|
|
85924
|
+
line_range: page.line_range,
|
|
85925
|
+
line_start: page.line_start,
|
|
85926
|
+
line_end: page.line_end,
|
|
85927
|
+
text: page.text,
|
|
85928
|
+
text_field: "items[].text",
|
|
85929
|
+
...page.next_range !== undefined ? { next_range: page.next_range } : {},
|
|
85930
|
+
...nextCommand2 !== undefined ? { next_command: nextCommand2 } : {}
|
|
85931
|
+
};
|
|
85932
|
+
}
|
|
85933
|
+
function tokenEstimate4(items) {
|
|
85934
|
+
const chars = items.reduce((sum, item) => sum + (typeof item.text === "string" ? item.text.length : 0), 0);
|
|
85935
|
+
return Math.ceil(chars / 4);
|
|
85936
|
+
}
|
|
85937
|
+
function writeCompileRequestFullTextView(context, format) {
|
|
85938
|
+
const pages = context.request_full_text?.pages ?? [];
|
|
85939
|
+
const items = pages.map((page) => pageItem(context, page));
|
|
85940
|
+
if (format === "json") {
|
|
85941
|
+
writeJson3({
|
|
85942
|
+
schema_version: "compile.request_full_text.view.v1",
|
|
85943
|
+
view: "text",
|
|
85944
|
+
view_of: "NodeContext.request_full_text.pages",
|
|
85945
|
+
node: context.node.slug,
|
|
85946
|
+
text_field: "items[].text",
|
|
85947
|
+
requested_block_ids: context.request_full_text?.requested_block_ids ?? [],
|
|
85948
|
+
item_id_field: "block_id",
|
|
85949
|
+
token_budget: "request-full-text-page",
|
|
85950
|
+
token_used: tokenEstimate4(items),
|
|
85951
|
+
shown_count: items.length,
|
|
85952
|
+
total: items.length,
|
|
85953
|
+
omitted_count: 0,
|
|
85954
|
+
truncated: items.some((item) => item.next_range !== undefined),
|
|
85955
|
+
selection_policy: {
|
|
85956
|
+
id: "request-full-text-v1",
|
|
85957
|
+
order: [{ field: "requested_block_ids", direction: "input" }]
|
|
85958
|
+
},
|
|
85959
|
+
items,
|
|
85960
|
+
how_to_explore: items.filter((item) => typeof item.next_command === "string").map((item) => ({
|
|
85961
|
+
level: "next_page",
|
|
85962
|
+
block_id: item.block_id,
|
|
85963
|
+
command: item.next_command,
|
|
85964
|
+
reason: "continue reading this full-text block page"
|
|
85965
|
+
}))
|
|
85966
|
+
});
|
|
85967
|
+
return;
|
|
85968
|
+
}
|
|
85969
|
+
const lines = [`Request full text for ${context.node.slug}`];
|
|
85970
|
+
for (const item of items) {
|
|
85971
|
+
lines.push("", `### ${String(item.block_id)} ${String(item.line_range)}`, String(item.text ?? ""));
|
|
85972
|
+
if (typeof item.next_command === "string")
|
|
85973
|
+
lines.push(`next: ${item.next_command}`);
|
|
85974
|
+
}
|
|
85975
|
+
process.stdout.write(lines.join(`
|
|
85976
|
+
`));
|
|
85977
|
+
}
|
|
85978
|
+
|
|
85669
85979
|
// src/commands/workflowCompileHelpers.ts
|
|
85670
85980
|
init_cliFeedback();
|
|
85671
85981
|
init_errors();
|
|
@@ -85837,7 +86147,7 @@ function compileScopeForOptions(options) {
|
|
|
85837
86147
|
|
|
85838
86148
|
// src/commands/workflowCompileCommand.ts
|
|
85839
86149
|
function registerCompileWorkflowCommand(program2) {
|
|
85840
|
-
program2.command("compile").description("Workflow helpers for /context:compile").option("--code [slug]", "compile deterministic code projection for an active aspect:code source").option("--scan-changes", "print incremental compile workset without creating a workflow lock").addOption(new Option("--scan", "removed; use --scan-changes").hideHelp()).option("--format <format>", "with --scan-changes/--context, output format: json | table", "table").option("--view <view>", "compact output view: full | summary | source-refs | issues").option("--ignore-source <source-id>", "with --scan-changes or --context, ignore refresh-applied source ids", collectIgnoredSource, []).option("--context <slug>", "prepare NodeContext payload for one align node and print summary/digests").option("--source <source-id>", "with --context --view source-refs, narrow source refs to one source id").option("--heading <heading-prefix>", "with --context --view source-refs, narrow source refs to a heading path prefix or heading text").option("--token-budget <n>", "with --context --view source-refs, limit output by approximate token budget").option("--draft-scaffold", "with --context --view source-refs, include a compile-draft skeleton for visible citation refs").option("--cover-uncovered-only", "with --context, return only unresolved coverage candidates for a targeted repair round").option("--request-full-text <block-id>", "with --context, expand one visible finalized evidence block", collectRequestedBlock, []).option("--request-full-text-range <start:end>", "with --request-full-text, read a block-relative line page").option("--node-cycle <slug>", "validate one node draft, prepare reconcile, review safe defaults, and apply in one command").option("--delegated", "with a new compile workflow, record user-authorized delegated mode for low-risk review decisions").option("--draft <slug>", "validate a compile draft JSON/YAML document from stdin, or with --prepare reuse the saved draft").option("--prepare", "with --draft --plan, also prepare the semantic reconcile payload").option("--draft-status <slug>", "print the current compile draft session summary").option("--draft-patch <slug>", "apply a compile draft patch for one node").option("--input <stdin>", "compile draft JSON/YAML document used with --draft; use '-' for stdin").option("--accept-safe-defaults", "with --node-cycle, accept mechanically safe defaults and stop if anything needs judgment").option("--coverage-disposition <stdin>", "coverage disposition patch JSON/YAML document; use '-' for stdin").option("--coverage-skip <candidate-id>", "skip one coverage candidate without writing a disposition file").option("--coverage-skip-unresolved", "skip every unresolved coverage candidate in the node payload").option("--coverage-disposition-node <slug>", "node slug for --coverage-disposition").option("--coverage-disposition-replace", "replace existing dispositions for the patched coverage candidates").option("--payload-digest <digest>", "optional workflow payload digest stale guard for write commands").option("--reason <text>", "reason for coverage skip shortcuts").option("--plan", "validate the draft without writing knowledge").option("--close", "run compile close: compact, rebuild index, append changelog, verify").option("--save-input", "with --draft, save the consumed draft under output/compile/compile.<slug>.draft.yaml").action(async (options) => {
|
|
86150
|
+
program2.command("compile").description("Workflow helpers for /context:compile").option("--code [slug]", "compile deterministic code projection for an active aspect:code source").option("--scan-changes", "print incremental compile workset without creating a workflow lock").addOption(new Option("--scan", "removed; use --scan-changes").hideHelp()).option("--format <format>", "with --scan-changes/--context, output format: json | table", "table").option("--view <view>", "compact output view: full | summary | source-refs | issues | text").option("--ignore-source <source-id>", "with --scan-changes or --context, ignore refresh-applied source ids", collectIgnoredSource, []).option("--context <slug>", "prepare NodeContext payload for one align node and print summary/digests").option("--source <source-id>", "with --context --view source-refs, narrow source refs to one source id").option("--heading <heading-prefix>", "with --context --view source-refs, narrow source refs to a heading path prefix or heading text").option("--token-budget <n>", "with --context --view source-refs, limit output by approximate token budget").option("--draft-scaffold", "with --context --view source-refs, include a compile-draft skeleton for visible citation refs").option("--cover-uncovered-only", "with --context, return only unresolved coverage candidates for a targeted repair round").option("--request-full-text <block-id>", "with --context, expand one visible finalized evidence block", collectRequestedBlock, []).option("--request-full-text-range <start:end>", "with --request-full-text, read a block-relative line page").option("--node-cycle <slug>", "validate one node draft, prepare reconcile, review safe defaults, and apply in one command").option("--delegated", "with a new compile workflow, record user-authorized delegated mode for low-risk review decisions").option("--draft <slug>", "validate a compile draft JSON/YAML document from stdin, or with --prepare reuse the saved draft").option("--prepare", "with --draft --plan, also prepare the semantic reconcile payload").option("--draft-status <slug>", "print the current compile draft session summary").option("--draft-patch <slug>", "apply a compile draft patch for one node").option("--input <stdin>", "compile draft JSON/YAML document used with --draft; use '-' for stdin").option("--accept-safe-defaults", "with --node-cycle, accept mechanically safe defaults and stop if anything needs judgment").option("--coverage-disposition <stdin>", "coverage disposition patch JSON/YAML document; use '-' for stdin").option("--coverage-skip <candidate-id>", "skip one coverage candidate without writing a disposition file").option("--coverage-skip-unresolved", "skip every unresolved coverage candidate in the node payload").option("--coverage-disposition-node <slug>", "node slug for --coverage-disposition").option("--coverage-disposition-replace", "replace existing dispositions for the patched coverage candidates").option("--payload-digest <digest>", "optional workflow payload digest stale guard for write commands").option("--reason <text>", "reason for coverage skip shortcuts").option("--plan", "validate the draft without writing knowledge").option("--close", "run compile close: compact, rebuild index, append changelog, verify").option("--save-input", "with --draft, save the consumed draft under output/compile/compile.<slug>.draft.yaml").action(async (options) => {
|
|
85841
86151
|
if (options.scan === true) {
|
|
85842
86152
|
throw new ContextError(ExitCode.UserError, "context compile --scan was removed; use context compile --scan-changes", {
|
|
85843
86153
|
category: ErrorCategory.UserInputInvalid,
|
|
@@ -85854,7 +86164,7 @@ function registerCompileWorkflowCommand(program2) {
|
|
|
85854
86164
|
const wantsChanges = options.scanChanges === true;
|
|
85855
86165
|
const actionCount = countActions(wantsCode, wantsChanges, typeof options.context === "string", typeof options.nodeCycle === "string", typeof options.draft === "string", typeof options.draftStatus === "string", typeof options.draftPatch === "string", typeof options.coverageDisposition === "string", typeof options.coverageSkip === "string", options.coverageSkipUnresolved === true, options.close === true);
|
|
85856
86166
|
if (actionCount !== 1) {
|
|
85857
|
-
throw new ContextError(ExitCode.UserError, "usage: context compile --code [slug] | --scan-changes [--delegated] | --context <slug> [--view source-refs] [--source <source-id>] [--heading <heading-prefix>] [--token-budget <n>] [--draft-scaffold] [--request-full-text <block-id> [--request-full-text-range <start:end>]] [--delegated] | --node-cycle <slug> --input - --accept-safe-defaults [--delegated] | --draft <slug> --input - --plan [--prepare] [--delegated] | --draft <slug> --plan --prepare | --draft-status <slug> | --draft-patch <slug> --input - --plan [--payload-digest <digest>] | --coverage-disposition - --coverage-disposition-node <slug> [--payload-digest <digest>] | --coverage-skip <candidate-id> --coverage-disposition-node <slug> --reason <text> | --coverage-skip-unresolved --coverage-disposition-node <slug> --reason <text> | --close. Code sources are not processed by bare context compile; use context compile --code.", {
|
|
86167
|
+
throw new ContextError(ExitCode.UserError, "usage: context compile --code [slug] | --scan-changes [--delegated] | --context <slug> [--view source-refs|text] [--source <source-id>] [--heading <heading-prefix>] [--token-budget <n>] [--draft-scaffold] [--request-full-text <block-id> [--request-full-text-range <start:end>]] [--delegated] | --node-cycle <slug> --input - --accept-safe-defaults [--delegated] | --draft <slug> --input - --plan [--prepare] [--delegated] | --draft <slug> --plan --prepare | --draft-status <slug> | --draft-patch <slug> --input - --plan [--payload-digest <digest>] | --coverage-disposition - --coverage-disposition-node <slug> [--payload-digest <digest>] | --coverage-skip <candidate-id> --coverage-disposition-node <slug> --reason <text> | --coverage-skip-unresolved --coverage-disposition-node <slug> --reason <text> | --close. Code sources are not processed by bare context compile; use context compile --code.", {
|
|
85858
86168
|
category: ErrorCategory.UserInputInvalid,
|
|
85859
86169
|
agent_hints: [{
|
|
85860
86170
|
code: "compile-code-explicit-required",
|
|
@@ -85868,14 +86178,15 @@ function registerCompileWorkflowCommand(program2) {
|
|
|
85868
86178
|
const viewWasExplicit = typeof options.view === "string";
|
|
85869
86179
|
const view = compileOutputView(options.view);
|
|
85870
86180
|
const wantsDraftPrepare = typeof options.draft === "string" && options.prepare === true;
|
|
86181
|
+
const requestFullTextBlockIds = ignoredSourceIds(options.requestFullText);
|
|
85871
86182
|
if (view !== "full") {
|
|
85872
86183
|
if (!wantsChanges && typeof options.context !== "string" && !wantsDraftPrepare) {
|
|
85873
86184
|
throw new ContextError(ExitCode.UserError, "--view is only valid with --scan-changes, --context, or --draft --prepare", {
|
|
85874
86185
|
category: ErrorCategory.UserInputInvalid
|
|
85875
86186
|
});
|
|
85876
86187
|
}
|
|
85877
|
-
if (wantsChanges && view === "source-refs") {
|
|
85878
|
-
throw new ContextError(ExitCode.UserError,
|
|
86188
|
+
if (wantsChanges && (view === "source-refs" || view === "text")) {
|
|
86189
|
+
throw new ContextError(ExitCode.UserError, `--view ${view} is only valid with --context`, {
|
|
85879
86190
|
category: ErrorCategory.UserInputInvalid
|
|
85880
86191
|
});
|
|
85881
86192
|
}
|
|
@@ -85889,8 +86200,12 @@ function registerCompileWorkflowCommand(program2) {
|
|
|
85889
86200
|
category: ErrorCategory.UserInputInvalid
|
|
85890
86201
|
});
|
|
85891
86202
|
}
|
|
86203
|
+
if (view === "text" && (typeof options.context !== "string" || requestFullTextBlockIds.length === 0)) {
|
|
86204
|
+
throw new ContextError(ExitCode.UserError, "--view text requires --context <slug> --request-full-text <block-id>", {
|
|
86205
|
+
category: ErrorCategory.UserInputInvalid
|
|
86206
|
+
});
|
|
86207
|
+
}
|
|
85892
86208
|
}
|
|
85893
|
-
const requestFullTextBlockIds = ignoredSourceIds(options.requestFullText);
|
|
85894
86209
|
const requestFullTextRange = parseRequestFullTextRange(options.requestFullTextRange);
|
|
85895
86210
|
const coverUncoveredOnly = options.coverUncoveredOnly === true;
|
|
85896
86211
|
const draftScaffold = options.draftScaffold === true;
|
|
@@ -86098,11 +86413,15 @@ function registerCompileWorkflowCommand(program2) {
|
|
|
86098
86413
|
}
|
|
86099
86414
|
if (typeof options.context === "string") {
|
|
86100
86415
|
let context = await getNodeContext(ctx.ctxDir, options.context, {
|
|
86101
|
-
...view !== "source-refs" && !coverUncoveredOnly ? { mode: "changed-only" } : {},
|
|
86416
|
+
...view !== "source-refs" && view !== "text" && requestFullTextBlockIds.length === 0 && !coverUncoveredOnly ? { mode: "changed-only" } : {},
|
|
86102
86417
|
...ignoreSourceIds.length > 0 ? { ignoreSourceIds } : {},
|
|
86103
86418
|
...requestFullTextBlockIds.length > 0 ? { requestFullTextBlockIds } : {},
|
|
86104
86419
|
...requestFullTextRange !== undefined ? { requestFullTextRange } : {}
|
|
86105
86420
|
});
|
|
86421
|
+
if (view === "text") {
|
|
86422
|
+
writeCompileRequestFullTextView(context, compileChangesFormat(options.format));
|
|
86423
|
+
return;
|
|
86424
|
+
}
|
|
86106
86425
|
const sourceFinalize = await readCurrentSourceOwnershipRecord(ctx.ctxDir).then((record) => record === null ? undefined : publishedSourceOwnershipSummary(record));
|
|
86107
86426
|
const selectedCoverageStatus = coverUncoveredOnly ? await readCoverageWorkspaceStatus(ctx.ctxDir) : undefined;
|
|
86108
86427
|
const selectedCoverageCandidates = selectedCoverageStatus?.candidates.filter((candidate) => candidate.node_slug === context.node.slug && candidate.status === "unresolved");
|
|
@@ -86425,6 +86744,20 @@ var AGENT_HINT_EMITTER_WORKFLOW_INVENTORY = [
|
|
|
86425
86744
|
handles: ["node_slug", "section_id", "source_ref"],
|
|
86426
86745
|
notes: "Compile applies semantic draft actions."
|
|
86427
86746
|
},
|
|
86747
|
+
{
|
|
86748
|
+
source: "src/workflow/compileChangesOutput.ts",
|
|
86749
|
+
family: "compile changes output",
|
|
86750
|
+
policy: "semantic",
|
|
86751
|
+
handles: ["node_slug", "first_compile_pending", "next_action"],
|
|
86752
|
+
notes: "Incremental compile output routes agents through remaining Node slugs and compile commands instead of cache probing."
|
|
86753
|
+
},
|
|
86754
|
+
{
|
|
86755
|
+
source: "src/workflow/compileChangesTypes.ts",
|
|
86756
|
+
family: "compile changes contract",
|
|
86757
|
+
policy: "semantic",
|
|
86758
|
+
handles: ["node_slug", "first_compile_pending", "next_action"],
|
|
86759
|
+
notes: "Compile changes types define semantic pending-work handles and next actions for Agent views."
|
|
86760
|
+
},
|
|
86428
86761
|
{
|
|
86429
86762
|
source: "src/workflow/compileClose.ts",
|
|
86430
86763
|
family: "compile close",
|
|
@@ -86453,6 +86786,13 @@ var AGENT_HINT_EMITTER_WORKFLOW_INVENTORY = [
|
|
|
86453
86786
|
handles: ["draft_digest", "action_id", "node_slug"],
|
|
86454
86787
|
notes: "Draft patch hints use session digest and action ids."
|
|
86455
86788
|
},
|
|
86789
|
+
{
|
|
86790
|
+
source: "src/workflow/compileDraftSourceRefs.ts",
|
|
86791
|
+
family: "compile draft source refs",
|
|
86792
|
+
policy: "semantic",
|
|
86793
|
+
handles: ["source_ref", "block_id", "node_slug"],
|
|
86794
|
+
notes: "Source_ref diagnostics provide nearby refs, split actions, and citation handles rather than storage inspection steps."
|
|
86795
|
+
},
|
|
86456
86796
|
{
|
|
86457
86797
|
source: "src/workflow/compileDraftTypes.ts",
|
|
86458
86798
|
family: "compile draft types",
|
|
@@ -86743,6 +87083,20 @@ var AGENT_HINT_EMITTER_INVENTORY = [
|
|
|
86743
87083
|
handles: ["project_id", "cache_status", "pending_compile"],
|
|
86744
87084
|
notes: "Next commands are cache/status commands, not physical cache inspection."
|
|
86745
87085
|
},
|
|
87086
|
+
{
|
|
87087
|
+
source: "src/commands/captureCodeInputHints.ts",
|
|
87088
|
+
family: "code capture input hints",
|
|
87089
|
+
policy: "semantic",
|
|
87090
|
+
handles: ["target_path", "module_path", "received_targets"],
|
|
87091
|
+
notes: "Code capture input errors route agents through plan and module capture commands rather than package probing."
|
|
87092
|
+
},
|
|
87093
|
+
{
|
|
87094
|
+
source: "src/commands/captureCommand.ts",
|
|
87095
|
+
family: "capture command output",
|
|
87096
|
+
policy: "semantic",
|
|
87097
|
+
handles: ["source_id", "capture_mode", "agent_hints"],
|
|
87098
|
+
notes: "Capture output serializes structured hints from mode-specific handlers."
|
|
87099
|
+
},
|
|
86746
87100
|
{
|
|
86747
87101
|
source: "src/commands/captureNote.ts",
|
|
86748
87102
|
family: "note capture code anchors",
|
package/package.json
CHANGED
package/plugin/commands/align.md
CHANGED
|
@@ -30,6 +30,7 @@ Keep the prompt shape stable: read fixed schema/protocol first, then existing kn
|
|
|
30
30
|
- `--unwrap` only removes the workflow metadata envelope. It does not turn a summary view into detail output.
|
|
31
31
|
3. Reuse existing knowledge before inventing candidates. For named terms or entities, prefer `context mdrive glossary match <name>` and `context mdrive node list --format json` over direct file reads. Treat `match.kind`, `match.matched`, and `match.rank` as stable lookup hints: exact title/slug/alias hits should usually reuse the existing Node instead of creating another one.
|
|
32
32
|
- Apply packaged `context:skill-align-workflow` Node classification gates before candidate ops and again before finalize: Action requires scale plus process evidence; Entity requires a concrete A/B tag or pure `term`; Domain requires child Nodes; fake Entities need at least two suspicious signals before downgrade. Scope/process words in a source title, such as "方案", "架构", "流程", "策略", or "演练", are review signals for the title/type choice, not proof that the Node is an Entity.
|
|
33
|
+
- Code projection Nodes are reusable knowledge handles. When prose evidence should attach to an existing code symbol Node, reuse the code slug (for example `pkg/symbol/button`) instead of creating a parallel document Node. If that code slug is not already in finalized prose ownership, declare it in the current `nodes[]` with the same node type and compatible tags/title, add the desired `planned_sections`, and point `sections[].owner` plus `block_ownership[].owners` at that slug. Do not cite `aspect:code:*` source refs from prose Sections; prose Sections cite only the current document evidence.
|
|
33
34
|
4. Submit generated workflow payloads directly through stdin, preferably as JSON. Use YAML schemas only for reading examples when helpful; generated artifacts should avoid YAML quoting/indentation failure loops. Do not create `/tmp` or workspace scratch files for align payloads. The CLI owns ids, reducer validation, workflow payload storage, and mechanical aggregate. You own semantic discovery, Node type/tag decisions, structure decisions, and user-facing questions.
|
|
34
35
|
- Save coarse-read with `context align --coarse-read - --format json`.
|
|
35
36
|
The latest `align-coarse-read` payload is only the most recent checkpoint; durable multi-source reading notes are stored under `align-candidate-ledger.source_readings`.
|
|
@@ -80,6 +81,8 @@ Submit it with `context align --ownership-patch - --format json`. Keep `base_dig
|
|
|
80
81
|
|
|
81
82
|
If `align-segments.incremental.mode` is `incremental`, the finalize step is a delta merge: submit only the Nodes and block ownership supported by the current scanned sources, and reference previous finalized Nodes when they are parents, dependencies, domain children, owners, or visibility targets. Absence of an old Node or edge is not a delete signal. Do not redeclare an old parent/domain just to attach a new child. `sections[].owner` must be a Node declared in the current payload; previous finalized Nodes can be referenced structurally but do not receive new section plans from this incremental payload. Existing or previously removed Node slugs cannot change `node_type`; `context align --scan --full` does not bypass that guard. Use a new slug for a different type, or retire the old slug through `context drop` or explicit structure correction before re-aligning.
|
|
82
83
|
|
|
84
|
+
For code-projection Nodes, distinguish "reuse the existing knowledge file" from "previous finalized prose ownership". A freshly projected code Node may exist in `knowledge/` but not yet appear in finalized ownership. To attach current prose evidence to it, declare that same slug in the current finalize payload and plan only prose-owned Sections for the current evidence; the compile step will merge the prose source and Sections into the existing code Node while preserving code metadata and code-owned Sections.
|
|
85
|
+
|
|
83
86
|
`nodes[].planned_sections` is the distinct set of Section kinds planned for that Node. List each kind at most once; do not copy `sections[].section_kind` one-for-one when a Node has multiple Sections of the same kind.
|
|
84
87
|
|
|
85
88
|
For large finalize decisions, use `block_ownership_defaults[]` instead of enumerating every block. Each default names a `source_id` plus the same ownership fields as a block-level entry except `block_id`; the CLI expands it across that source's coverable blocks. Put only exceptions in `block_ownership[]`, which override defaults for their `block_id`. Keep the payload on stdin; do not generate temp JSON files just to list hundreds of ownership rows.
|
|
@@ -18,6 +18,7 @@ Run the align workflow through the CLI-owned beta.8 payload chain: scan segments
|
|
|
18
18
|
- Finalized structure is represented by `align-structure-decision`.
|
|
19
19
|
- Retired payloads include candidate tables, decision patches, and full-tree finalize documents.
|
|
20
20
|
- Existing knowledge is the lookup registry. Use `context mdrive glossary match <name>` / `context mdrive node list --format json` for term/entity reuse; do not read `knowledge/**` and do not create a separate registry file.
|
|
21
|
+
- Code projection Nodes are existing knowledge handles. When document evidence belongs on a code symbol, reuse the code slug instead of creating a parallel document Node. If the slug exists only as projected code knowledge and is not yet in finalized prose ownership, declare that same slug in the current `nodes[]`, add the prose `planned_sections`, and route `sections[].owner` plus `block_ownership[].owners` to it.
|
|
21
22
|
- Keep cache-friendly prompt order: fixed protocol and schemas first, existing knowledge lookup second, source-shared payload views third, current candidate batch last. Preserve CLI JSON order and do not add timestamps, random ids, scratch paths, or host paths to generated payloads.
|
|
22
23
|
- `align-segments.generation_policy` is the workspace language contract for generated Node titles, summaries, rationale prose, and planned Section wording. Source-bound Section wording should stay close to the cited source language when it differs from the workspace language. Preserve product names, code identifiers, slugs, flags, `block_id` handles, and `source_ref` tokens exactly when needed.
|
|
23
24
|
- Source titles and headings are ordinary evidence, not structural authority. Do not automatically copy them into Node titles or aliases; classify the evidence referent first, then generate a title that fits the final Node type.
|
|
@@ -43,6 +44,8 @@ Use this only inside `/context:align`.
|
|
|
43
44
|
|
|
44
45
|
If `align-segments.incremental.mode` is `incremental`, finalize is a delta merge. Submit only the Nodes and ownership supported by the current scanned sources; reference previous finalized Nodes when they are parents, dependencies, domain children, owners, or visibility targets. Absence of an old Node or edge is not a delete signal. Do not redeclare an old parent/domain just to attach a new child. `sections[].owner` must be a Node declared in the current payload; previous finalized Nodes can be referenced structurally but do not receive new section plans from this incremental payload. Existing or previously removed Node slugs cannot change `node_type`; `context align --scan --full` does not bypass that guard. Use a new slug for a different type, or retire the old slug through `context drop` or explicit structure correction before re-aligning.
|
|
45
46
|
|
|
47
|
+
For code-projection Nodes, "existing knowledge file" and "previous finalized prose ownership" are different states. A freshly projected code Node can be reused by declaring the same slug in the current finalize payload and planning only prose-owned Sections for the current evidence. Compile merges the prose source and Sections into the existing code Node while preserving code metadata and code-owned Sections. Prose Sections must cite document evidence, not `aspect:code:*` source refs.
|
|
48
|
+
|
|
46
49
|
`nodes[].planned_sections` is the distinct set of Section kinds planned for that Node. List each kind at most once; do not copy `sections[].section_kind` one-for-one when a Node has multiple Sections of the same kind.
|
|
47
50
|
|
|
48
51
|
For large finalize decisions, use `block_ownership_defaults[]` instead of enumerating every block. Each default names a `source_id` plus the same ownership fields as a block-level entry except `block_id`; the CLI expands it across that source's coverable blocks. Put only exceptions in `block_ownership[]`, which override defaults for their `block_id`. Keep the payload on stdin; do not generate temp JSON files just to list hundreds of ownership rows.
|