@c4a/context 0.6.1-beta.3 → 0.6.1-beta.5

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.
@@ -49,10 +49,11 @@ knowledge/codegraph/module-a/...
49
49
  knowledge/codegraph/module-b/...
50
50
  ```
51
51
 
52
- For prose Views, omit `containment` when the page is an independent collection
53
- entry. The CLI then derives `knowledge/<collection>/<slug>.md`. Set
54
- `containment` only when the approved structure intentionally places the page
55
- under a parent path; it is not a required source/module wrapper.
52
+ For prose Views, provide a stable filename `slug` and omit `path`; the CLI
53
+ derives the path. Omit `containment` when the page is an independent collection
54
+ entry, producing `knowledge/<collection>/<slug>.md`. Set `containment` only
55
+ when the approved structure intentionally places the page under a parent path;
56
+ it is not a required source/module wrapper.
56
57
 
57
58
  The registry stores this as one date entry containing several `modules` entries,
58
59
  and materializes each module at `sources/repo/<date>/<module>`.
@@ -179,7 +180,10 @@ with the next declared command in `workflow.current.commands`.
179
180
  Each command item declares its effect and availability. The current route's
180
181
  `gate` identifies the decision and authority boundary. Write commands are bound
181
182
  to the workflow revision; after one succeeds, rerun status instead of reusing
182
- the old command.
183
+ the old command. An external command also declares
184
+ `execution.target: agent-host`; execute it as a top-level Agent-host action so
185
+ network and credential-store access are not lost inside a restricted child
186
+ sandbox.
183
187
 
184
188
  ### `allSources("repo")`
185
189
 
@@ -245,6 +249,10 @@ context review approve-all <collection> --managed --format json
245
249
  context review approve-all --all --managed --format json
246
250
  ```
247
251
 
252
+ The default JSON result reports counts and change totals without listing every
253
+ candidate id or materialized path. Add `--verbose` only when debugging requires
254
+ the complete candidate and page details.
255
+
248
256
  Managed structure confirmation and Review use only the revision-bound commands
249
257
  returned by `workflow.current`. Source boundaries and unread source bodies,
250
258
  external operations, payload validation, deterministic close, and verification
@@ -324,9 +332,17 @@ Register each source with
324
332
  flag: `--url`, `--doc-token`, or `--wiki-token`. Multiple documents may share
325
333
  one date batch; when `--module` is omitted, the CLI derives an opaque,
326
334
  credential-safe module id. Capture reads the
327
- remote document through the CLI runner, writes normalized snapshot files under
328
- `sources/lark/<date>/` as sibling document files tracked by one date-level `manifest.json`, and does not write access credentials into the
329
- workspace.
335
+ remote document through the CLI runner as structured Docx XML. Context keeps a
336
+ redacted XML audit asset, projects supported blocks deterministically into
337
+ readable Markdown, and registers external resources such as document citations,
338
+ images, video, whiteboards, and Base references in the snapshot manifest even
339
+ when their binary content is not downloaded. The projection does not infer or
340
+ summarize document meaning. Its fidelity report closes discovered blocks against
341
+ converted and intentionally skipped blocks; a non-empty unsupported block is a
342
+ fidelity error and prevents downstream Review until capture support is fixed.
343
+ Snapshot files live under `sources/lark/<date>/` as sibling document files
344
+ tracked by one date-level `manifest.json`. Access credentials and transient
345
+ signed media URLs are not written into the workspace.
330
346
 
331
347
  Use a typed document reference in project declarations:
332
348
 
@@ -374,15 +390,56 @@ context run align:file:<source-name>:architecture --view structure-summary --inp
374
390
  context run align:file:<source-name>:architecture --stage --input <structure.yaml> --format json
375
391
  ```
376
392
 
393
+ When `workflow.current.batch` is present, several independent document slots
394
+ can be prepared in one Agent pass and validated or staged through one command:
395
+
396
+ ```yaml
397
+ schema: context.prose.structure-batch.v1
398
+ items:
399
+ - phase_id: align:file:<source-a>:architecture
400
+ input: .tmp/agent-payloads/<source-a>-structure.yaml
401
+ - phase_id: align:file:<source-b>:architecture
402
+ input: .tmp/agent-payloads/<source-b>-structure.yaml
403
+ ```
404
+
405
+ ```bash
406
+ context run --batch-input .tmp/agent-payloads/prose-structure-batch.yaml --validate --format json
407
+ context run --batch-input .tmp/agent-payloads/prose-structure-batch.yaml --stage --managed --format json
408
+ ```
409
+
410
+ Batch preflight validates every payload before writing. Stage writes ready
411
+ slots serially; it does not merge documents or decide their semantic shape.
412
+
413
+ Align results expose a recommended `payload_target.path` under
414
+ `.tmp/agent-payloads/`. Agents should use it for transient structure inputs and
415
+ may remove the file after a successful stage. The CLI continues to accept an
416
+ explicit alternative path; this is an authoring convention, not validation.
417
+
418
+ For the ordinary path, `read-plan` is a complete authoring packet: it includes
419
+ the payload contract, a budgeted canonical source-ref map, exact source-body
420
+ resources, and a direct `--stage` command. Read the bodies, author the payload,
421
+ and run that stage command. Request `source-index` only when the packet reports
422
+ omitted refs, and request `existing-knowledge` only when reusing or checking an
423
+ approved identity. The separate schema and validate views are optional
424
+ diagnostic tools, not required lifecycle steps.
425
+
377
426
  `--validate`, `--stage`, and `--confirm` are mutually exclusive operations. An
378
427
  `--input` without an operation is rejected unless the selected view explicitly
379
428
  consumes that input. Deterministic boundary repairs run internally before the
380
- result is returned. Successful validation returns a stage command with the
429
+ result is returned. `self_healed` includes input/output Section counts, the
430
+ number of original Sections split, and structural reason codes. Stage performs validation before writing and returns the
431
+ same diagnostics on failure; in managed mode, a valid stage also confirms the
432
+ structure. Successful standalone validation returns a stage command with the
381
433
  same file path. JSON run output keeps `next_action` first;
382
434
  schema and full reports stay behind explicit Views, while `--verbose` restores
383
435
  the full phase result and repeated contracts. Long diagnostics return a compact
384
436
  first page plus an exact diagnostics continuation command.
385
437
 
438
+ Validation returns `state: ready | repair-required | invalid`. Only `ready`
439
+ sets `valid: true` and may proceed to stage. `error_free: true` with
440
+ `state: repair-required` means no error diagnostic remains, but a declared
441
+ confirmation blocker still requires repair; it is not a successful result.
442
+
386
443
  `existing-knowledge` is the authoring-time lookup for approved identities. It
387
444
  returns stable NodeRefs, ViewRefs, titles, tags, collections, and section counts
388
445
  without exposing workspace storage paths. `--query` performs deterministic
@@ -414,7 +471,20 @@ After capture, the capture phase itself exposes collection-neutral `read-plan`,
414
471
  Status selects `route.document.classification-required` until every captured
415
472
  target has an evidence-backed, user-confirmed align declaration. Align then
416
473
  adds `schema` and `structure-summary` for structure work. Agents should not
417
- inspect `sources/` or `.tmp` directly.
474
+ scan `sources/` or `.tmp` to invent evidence. They may read only the exact
475
+ source-body files selected as required resources by the current Route; those
476
+ files carry stable content digests and must be read in full before a receipt is
477
+ reported. Read all required direct paths, then execute the Route's single
478
+ `resources.after_read.command`; the CLI writes and carries the merged receipt
479
+ set without requiring Agent-authored JSON. That acknowledgement response
480
+ already contains the re-evaluated `workflow.current`, so no additional status
481
+ command is needed.
482
+
483
+ Generated Context Views use the same content-addressed rule. Materialization
484
+ returns a receipt-set path and an exact post-read command. Read the complete
485
+ file, then execute that command; unchanged content remains current across
486
+ workflow revisions, while write and external commands still require the exact
487
+ current revision.
418
488
 
419
489
  Compile `read-plan`, `blockers`, and `diagnostics` Views are workspace-read-only
420
490
  and may run concurrently. Compile `--validate`, compile `--stage`, structure
@@ -451,9 +521,9 @@ compile:file:<source-name>:architecture
451
521
  compile:lark:<source-name>:architecture
452
522
  ```
453
523
 
454
- Compile requires confirmed `unapproved/structure.yaml`. It freezes the current
455
- structure for the compile round; if the user wants to change nodes, section
456
- ownership, or relationships, return to the align/structure gate.
524
+ Compile requires confirmed CLI-managed lifecycle structure. It freezes the
525
+ current structure for the compile round; if the user wants to change nodes,
526
+ section ownership, or relationships, return to the align/structure gate.
457
527
 
458
528
  Common commands:
459
529
 
@@ -537,7 +607,7 @@ package from a larger monorepo source.
537
607
  Use `context source inspect <date>/<module>` to list detected module/package
538
608
  boundaries before choosing the source. Use `context run <phase-id> --dry-run
539
609
  --format json` to check the resolved modules, file counts, symbol counts, and
540
- candidate estimate before writing `unapproved/entities.jsonl`. The dry-run
610
+ candidate estimate before writing the ignored lifecycle candidate ledger. The dry-run
541
611
  preview also includes `knowledgeTree` and `knowledgePathExamples`, which show
542
612
  where approved Markdown will land after review apply.
543
613
  Its module and total summaries distinguish `discoveredFiles`, `analyzedFiles`,
@@ -580,6 +650,56 @@ lookup exact when multiple files contain the same symbol name, kind, and digest;
580
650
  the complete ref remains opaque to agents. New pages keep only top-level
581
651
  `candidate_fingerprint` and do not emit `code_origin`.
582
652
 
653
+ ### `extractCustom`
654
+
655
+ Use a project-owned extractor when code facts cannot be represented by the
656
+ TypeScript symbol extractor, for example a language-specific parser or an
657
+ aggregated repository protocol:
658
+
659
+ ```ts
660
+ extractCustom({
661
+ id: "extract:service:protocol",
662
+ sources: [service],
663
+ collection: "codegraph",
664
+ extract: async ({ projectRoot }) => ({
665
+ candidates: [{
666
+ nodeRef: "service/protocol",
667
+ kind: "protocol",
668
+ visibility: "exported",
669
+ module: "service",
670
+ markdown: renderProtocol(projectRoot),
671
+ evidence: [{
672
+ source: "20260811/service",
673
+ file: "src/protocol.ts",
674
+ symbol: "protocol",
675
+ kind: "variable",
676
+ digest: "0123456789ab",
677
+ }],
678
+ review: {
679
+ title: "Service protocol",
680
+ summary: "Aggregated protocol boundary.",
681
+ signals: ["source-backed"],
682
+ reason: "Review the project-owned extraction.",
683
+ },
684
+ }],
685
+ }),
686
+ });
687
+ ```
688
+
689
+ `sources` is the complete registered repo scope for the phase. Every candidate
690
+ and edge carries structured `evidence`; the CLI validates that evidence against
691
+ the declared sources, creates canonical `source_ref` values, writes the symbol
692
+ index, candidate ledger and Review snapshots atomically, and records a phase
693
+ fingerprint. `context status` therefore treats this phase exactly like another
694
+ pending code extraction target, and Review can verify snapshot freshness
695
+ without a placeholder `extractTs` phase.
696
+
697
+ The extractor returns knowledge semantics (`nodeRef`, rendered Markdown,
698
+ Review summary and source-backed evidence). It must not write `knowledge/`,
699
+ `.tmp/context-runtime/lifecycle/candidates.jsonl`, extraction fingerprints or
700
+ Review snapshots directly. Context owns those files and preserves rejected and
701
+ unchanged-approved decisions across reruns.
702
+
583
703
  ### `reviewValidity`
584
704
 
585
705
  Declare the review step for a collection:
@@ -619,7 +739,8 @@ structure slots and every declared `pendingStructureTargets` item in the round;
619
739
  codegraph waits for every pending extract phase in the confirmed module round.
620
740
  Candidate count/hash therefore describes the complete current batch rather than
621
741
  one page, source slot, or module. Deterministic close later merges all active
622
- slots into `knowledge/structure.yaml`.
742
+ slots into `knowledge/structure.yaml`, retains only their source, collection,
743
+ and consumed snapshot hash as `source_inputs`, then removes the lifecycle slots.
623
744
 
624
745
  `status.structureBatch` lists unclassified, configuration-required, pending,
625
746
  and active structure slots together with the execution policy for the round.
@@ -650,8 +771,9 @@ customPhase("custom:20260712/sample:review", async (ctx) => {
650
771
  });
651
772
  ```
652
773
 
653
- Custom phases are an escape hatch. Prefer built-in factories for source,
654
- extract, review, and package workflows. The supported runtime helpers are:
774
+ Custom phases are an orchestration escape hatch. Use `extractCustom()` instead
775
+ when project code needs to publish codegraph candidates. The supported runtime
776
+ helpers are:
655
777
 
656
778
  - `ctx.ensureSources(...)` for repo source readiness.
657
779
  - `ctx.extract.ts(...)` for declared TypeScript extraction.
@@ -91,13 +91,13 @@ Read node_modules/@c4a/context/docs/reference/template-variables.md.
91
91
  |---|---|---|
92
92
  | `packageName` | string | Package name from `kbPackage()` / `llmsPackage()`. |
93
93
  | `packageKind` | string | `kb` or `llms`. |
94
- | `knowledgeNamespace` | string | KB knowledge namespace; defaults to the package name and may be explicitly overridden. Empty for non-KB packages. |
95
- | `namespacedKnowledge` | boolean | Whether the KB package has a knowledge namespace. |
94
+ | `knowledgeNamespace` | string | Legacy configured namespace when an older workspace still declares one; otherwise empty. It does not change output paths. |
95
+ | `namespacedKnowledge` | boolean | Always `false`; retained so older templates remain renderable. |
96
96
  | `skillsRoot` | string | Skills root, currently `skills`. |
97
- | `wikisRoot` | string | Final wikis root, such as `wikis/component-lib-kb` or `wikis/platform/component-lib`. |
98
- | `guidesRoot` | string | Final guides root, such as `guides/component-lib-kb` or `guides/platform/component-lib`. |
99
- | `rulesRoot` | string | Final rules root, such as `rules/component-lib-kb` or `rules/platform/component-lib`. |
100
- | `featsRoot` | string | Final feats root, such as `feats/component-lib-kb` or `feats/platform/component-lib`. |
97
+ | `wikisRoot` | string | Final wikis root: `wikis`. |
98
+ | `guidesRoot` | string | Final guides root: `guides`. |
99
+ | `rulesRoot` | string | Final rules root: `rules`. |
100
+ | `featsRoot` | string | Final feats root: `feats`. |
101
101
  | `skillName` | string | Author-maintained name of the Skill currently being rendered. Empty outside a `skills/<name>/...` template. |
102
102
  | `skillPath` | string | Final package-relative `SKILL.md` path for the Skill currently being rendered. Empty outside a Skill template. |
103
103
  | `knowledgeCount` | number | Selected approved Markdown file count. |
@@ -139,7 +139,7 @@ Each item contains:
139
139
  | `internal_collection` | Alias for `internalCollection`. |
140
140
  | `collection` | Internal approved collection; alias for `internalCollection`. |
141
141
  | `okf_root` | OKF output root, for example `wikis`, `guides`, `rules`, or `feats`. |
142
- | `okf_root_path` | Final package-relative OKF root; for KB packages it includes the distribution namespace. |
142
+ | `okf_root_path` | Final flat package-relative OKF root. |
143
143
  | `node_ref` | Stable NodeRef from approved frontmatter, for example `entity/button`. |
144
144
  | `view_ref` | Stable ViewRef from approved frontmatter, for example `architecture:entity/button`. |
145
145
  | `pathWithinCollection` | Path below the OKF root, for example `component-lib/symbol/button.md`. |
@@ -177,7 +177,7 @@ Each group contains:
177
177
  | `internalCollection` | Internal approved collection; alias for `collection`. |
178
178
  | `internal_collection` | Alias for `internalCollection`. |
179
179
  | `okf_root` | OKF output root for this group, for example `wikis`, `guides`, `rules`, or `feats`. |
180
- | `okf_root_path` | Final package-relative OKF root; for KB packages it includes the distribution namespace. |
180
+ | `okf_root_path` | Final flat package-relative OKF root. |
181
181
  | `title` | Display title; defaults to `name`, or the OKF root title for a root group. |
182
182
  | `count` | Number of selected pages in this group. |
183
183
  | `hasIndex` | Whether the active package navigation policy generates `indexPath`. |
@@ -236,6 +236,7 @@ non-root directory gets its own index only when it contains more than 50
236
236
  descendant knowledge pages. Configure this with
237
237
  `kbPackage({ navigation: { foldDirectoryIndexes, maxInlineEntries } })`.
238
238
 
239
- The output is only a starter. Edit
240
- `src/package-templates/kb/wikis/index.md` to add project-specific reading
241
- paths, API entry points, or task-focused navigation before `context build`.
239
+ The output is only a starter. Edit the files under
240
+ `src/package-templates/kb/` when the package needs different reading paths or
241
+ navigation before `context build`. An unchanged generated starter must instead
242
+ be explicitly accepted through the current package-template Review Route.
package/index.d.ts CHANGED
@@ -5,8 +5,8 @@ export type { CodegraphCollection, DocumentMainlineCollection, EntityStatus, Kno
5
5
  export { assertDocumentMainlineCollection, assertKnowledgeCollection, assertMainlineCollection, assertOkfRoot, assertTopLevelNamespace, DOC_MAINLINE_COLLECTIONS, DEFAULT_PACKAGE_NAVIGATION, KNOWLEDGE_COLLECTIONS, MAINLINE_COLLECTIONS, OKF_ROOTS, TOP_LEVEL_NAMESPACES, } from "./contracts.js";
6
6
  export { assertDocumentEvidenceSectionMetadata, DOCUMENT_COMPILE_ACTION_SCHEMA_VERSION, DOCUMENT_EVIDENCE_SECTION_VALIDATION_STAGES, DOCUMENT_SECTION_CONTENT_MODES, DOCUMENT_STRUCTURE_SCHEMA_VERSION, } from "./documentEvidence.js";
7
7
  export type { DocumentEvidenceSectionMetadata, DocumentEvidenceSectionValidationOptions, DocumentEvidenceSectionValidationStage, DocumentSectionContentMode, } from "./documentEvidence.js";
8
- export { alignProse, captureFile, captureLark, compileProse, customPhase, extractTs, ExtractTsConfigurationError, NO_ENTRY_DETECTED, mdxJsonDocs, reviewValidity, } from "./phases.js";
9
- export type { AlignProsePhaseDefinition, CaptureFilePhaseDefinition, CaptureLarkPhaseDefinition, CompileProsePhaseDefinition, ContextPhase, ContextPhaseContext, CustomPhaseDefinition, ExtractTsPhaseDefinition, PhaseDefinition, PhaseResourceReference, ReviewValidityPhaseDefinition, ReviewValidityScope, } from "./phases.js";
8
+ export { alignProse, captureFile, captureLark, compileProse, customPhase, extractCustom, extractTs, ExtractTsConfigurationError, NO_ENTRY_DETECTED, mdxJsonDocs, reviewValidity, } from "./phases.js";
9
+ export type { AlignProsePhaseDefinition, CaptureFilePhaseDefinition, CaptureLarkPhaseDefinition, CompileProsePhaseDefinition, ContextPhase, ContextPhaseContext, CustomPhaseDefinition, CustomCodeCandidateDraft, CustomCodeCandidateEdge, CustomCodeCandidateReview, CustomCodeEvidence, CustomCodeExtractionContext, CustomCodeExtractionResult, CustomCodeExtractor, ExtractCustomPhaseDefinition, ExtractTsPhaseDefinition, PhaseDefinition, PhaseResourceReference, ReviewValidityPhaseDefinition, ReviewValidityScope, } from "./phases.js";
10
10
  export { allSources, DEFAULT_FILE_SOURCES_REGISTRY_PATH, DEFAULT_LARK_SOURCES_REGISTRY_PATH, DEFAULT_REPO_SOURCES_REGISTRY_PATH, loadSourcesRegistry, resolveSourceReference, source, } from "./sources.js";
11
11
  export type { DocumentSourceDefinition, DocumentSourceReference, DocumentSourceType, FileSourceDefinition, FileSourceReference, FileSourceRegistryEntry, LarkSourceDefinition, LarkSourceReference, LarkSourceRegistryEntry, LoadSourcesRegistryOptions, ProjectSourceDefinition, RepoProjectSourceDefinition, RepoSourceDefinition, RepoSourceReference, RepoSourceRegistryEntry, RepoSourcesRegistry, SourceCollectionReference, SourceDefinition, SourceReference, SourcesRegistry, SourceType, } from "./sources.js";
12
12
  export type TemplateVarValue = string | number | boolean | null | Record<string, unknown> | readonly Record<string, unknown>[];
@@ -19,6 +19,7 @@ export type PackageTemplateInput = string | {
19
19
  vars?: Record<string, TemplateVarValue>;
20
20
  };
21
21
  export type PackageDistributionDefinition = {
22
+ /** @deprecated Accepted for older workspaces; package output roots are flat. */
22
23
  knowledgeNamespace: string;
23
24
  };
24
25
  export type BasePackageDefinition = {
package/index.js CHANGED
@@ -7088,9 +7088,9 @@ var sourceSnapshotResource = (sourceDefinition, sourceType) => ({
7088
7088
  sourceType,
7089
7089
  path: `sources/${sourceType}/${getSourceName(sourceDefinition)}/manifest.json`
7090
7090
  });
7091
- var unapprovedStructureResource = (collection, status) => ({
7092
- kind: "unapproved.structure",
7093
- path: "unapproved/structure.yaml",
7091
+ var lifecycleStructureResource = (collection, status) => ({
7092
+ kind: "lifecycle.structure",
7093
+ path: ".tmp/context-runtime/lifecycle/structure.yaml",
7094
7094
  profileCollection: collection,
7095
7095
  ...status === undefined ? {} : { status }
7096
7096
  });
@@ -7150,7 +7150,7 @@ var alignProse = (definition) => {
7150
7150
  kind: "source",
7151
7151
  source: definition.source
7152
7152
  }],
7153
- writes: [unapprovedStructureResource(definition.collection, "draft")],
7153
+ writes: [lifecycleStructureResource(definition.collection, "draft")],
7154
7154
  source: definition.source,
7155
7155
  collection: definition.collection
7156
7156
  };
@@ -7160,7 +7160,7 @@ var alignProse = (definition) => {
7160
7160
  kind: "phase.align.prose",
7161
7161
  id: `align:${sourceType}:${sourceId}:${definition.collection}`,
7162
7162
  reads: [sourceSnapshotResource(definition.source, sourceType)],
7163
- writes: [unapprovedStructureResource(definition.collection, "draft")],
7163
+ writes: [lifecycleStructureResource(definition.collection, "draft")],
7164
7164
  source: definition.source,
7165
7165
  sourceType,
7166
7166
  collection: definition.collection
@@ -7176,12 +7176,12 @@ var compileProse = (definition) => {
7176
7176
  reads: [{
7177
7177
  kind: "source",
7178
7178
  source: definition.source
7179
- }, unapprovedStructureResource(definition.collection, "confirmed")],
7179
+ }, lifecycleStructureResource(definition.collection, "confirmed")],
7180
7180
  writes: [
7181
- unapprovedStructureResource(definition.collection, "frozen"),
7181
+ lifecycleStructureResource(definition.collection, "frozen"),
7182
7182
  {
7183
- kind: "unapproved.entities",
7184
- path: "unapproved/entities.jsonl",
7183
+ kind: "lifecycle.candidates",
7184
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7185
7185
  status: "draft"
7186
7186
  }
7187
7187
  ],
@@ -7196,13 +7196,13 @@ var compileProse = (definition) => {
7196
7196
  id: `compile:${sourceType}:${sourceId}:${definition.collection}`,
7197
7197
  reads: [
7198
7198
  sourceSnapshotResource(definition.source, sourceType),
7199
- unapprovedStructureResource(definition.collection, "confirmed")
7199
+ lifecycleStructureResource(definition.collection, "confirmed")
7200
7200
  ],
7201
7201
  writes: [
7202
- unapprovedStructureResource(definition.collection, "frozen"),
7202
+ lifecycleStructureResource(definition.collection, "frozen"),
7203
7203
  {
7204
- kind: "unapproved.entities",
7205
- path: "unapproved/entities.jsonl",
7204
+ kind: "lifecycle.candidates",
7205
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7206
7206
  status: "draft"
7207
7207
  }
7208
7208
  ],
@@ -7234,8 +7234,8 @@ var extractTs = (definition) => {
7234
7234
  source: sourceDefinition
7235
7235
  }],
7236
7236
  writes: [{
7237
- kind: "unapproved.entities",
7238
- path: "unapproved/entities.jsonl",
7237
+ kind: "lifecycle.candidates",
7238
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7239
7239
  collection: definition.collection,
7240
7240
  status: "draft"
7241
7241
  }],
@@ -7247,7 +7247,7 @@ var extractTs = (definition) => {
7247
7247
  exportedOnly: definition.exportedOnly ?? mode === "exports",
7248
7248
  out: {
7249
7249
  kind: "codegraph-entities",
7250
- candidateFile: "unapproved/entities.jsonl",
7250
+ candidateFile: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7251
7251
  approvedPagesDir: `knowledge/${definition.collection}`,
7252
7252
  initialStatus: "draft"
7253
7253
  }
@@ -7257,6 +7257,31 @@ var extractTs = (definition) => {
7257
7257
  }
7258
7258
  return phase;
7259
7259
  };
7260
+ var extractCustom = (definition) => {
7261
+ const id = definition.id.trim();
7262
+ if (id.length === 0)
7263
+ throw new TypeError("extractCustom id must be a non-empty phase id");
7264
+ if (definition.sources.length === 0)
7265
+ throw new TypeError("extractCustom sources must contain at least one repo source");
7266
+ if (definition.collection !== "codegraph") {
7267
+ throw new TypeError(`extractCustom collection must be codegraph: ${definition.collection}`);
7268
+ }
7269
+ const sources = definition.sources.map((sourceDefinition) => bindSourceType(sourceDefinition, "repo", "extractCustom source"));
7270
+ return {
7271
+ kind: "phase.extract.custom",
7272
+ id,
7273
+ reads: sources.map((sourceDefinition) => ({ kind: "source", source: sourceDefinition })),
7274
+ writes: [{
7275
+ kind: "lifecycle.candidates",
7276
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7277
+ collection: definition.collection,
7278
+ status: "draft"
7279
+ }],
7280
+ sources,
7281
+ collection: definition.collection,
7282
+ extract: definition.extract
7283
+ };
7284
+ };
7260
7285
  var reviewValidity = (definition) => {
7261
7286
  const payload = definition.payload ?? "review-payload.json";
7262
7287
  if ("scope" in definition) {
@@ -7267,8 +7292,8 @@ var reviewValidity = (definition) => {
7267
7292
  kind: "phase.review.validity",
7268
7293
  id: "review:all:validity",
7269
7294
  reads: [{
7270
- kind: "unapproved.entities",
7271
- path: "unapproved/entities.jsonl",
7295
+ kind: "lifecycle.candidates",
7296
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7272
7297
  status: "draft"
7273
7298
  }],
7274
7299
  writes: [
@@ -7281,8 +7306,12 @@ var reviewValidity = (definition) => {
7281
7306
  path: "knowledge"
7282
7307
  },
7283
7308
  {
7284
- kind: "unapproved.entities",
7285
- path: "unapproved/entities.jsonl",
7309
+ kind: "knowledge.decisions",
7310
+ path: "knowledge/decisions.json"
7311
+ },
7312
+ {
7313
+ kind: "lifecycle.candidates",
7314
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7286
7315
  status: "rejected"
7287
7316
  }
7288
7317
  ],
@@ -7297,8 +7326,8 @@ var reviewValidity = (definition) => {
7297
7326
  kind: "phase.review.validity",
7298
7327
  id: `review:${definition.collection}:validity`,
7299
7328
  reads: [{
7300
- kind: "unapproved.entities",
7301
- path: "unapproved/entities.jsonl",
7329
+ kind: "lifecycle.candidates",
7330
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7302
7331
  collection: definition.collection,
7303
7332
  status: "draft"
7304
7333
  }],
@@ -7314,8 +7343,12 @@ var reviewValidity = (definition) => {
7314
7343
  status: "approved"
7315
7344
  },
7316
7345
  {
7317
- kind: "unapproved.entities",
7318
- path: "unapproved/entities.jsonl",
7346
+ kind: "knowledge.decisions",
7347
+ path: "knowledge/decisions.json"
7348
+ },
7349
+ {
7350
+ kind: "lifecycle.candidates",
7351
+ path: ".tmp/context-runtime/lifecycle/candidates.jsonl",
7319
7352
  collection: definition.collection,
7320
7353
  status: "rejected"
7321
7354
  }
@@ -11772,22 +11805,8 @@ function assertUniquePhaseIds(phases) {
11772
11805
  firstById.set(phase.id, { index, kind: phase.kind });
11773
11806
  }
11774
11807
  }
11775
- function assertUniquePackageKnowledgeNamespaces(packages) {
11776
- const firstByNamespace = new Map;
11777
- for (const [index, pkg] of packages.entries()) {
11778
- const namespace = pkg.kind === "package.kb" ? pkg.distribution?.knowledgeNamespace : undefined;
11779
- if (namespace === undefined)
11780
- continue;
11781
- const first = firstByNamespace.get(namespace);
11782
- if (first !== undefined) {
11783
- throw new TypeError(`Duplicate package knowledge namespace ${JSON.stringify(namespace)}: packages[${first.index}] (${first.name}) conflicts with packages[${index}] (${pkg.name}). Every distributable knowledge package namespace must be unique.`);
11784
- }
11785
- firstByNamespace.set(namespace, { index, name: pkg.name });
11786
- }
11787
- }
11788
11808
  var defineProject = (project) => {
11789
11809
  assertUniquePhaseIds(project.phases);
11790
- assertUniquePackageKnowledgeNamespaces(project.packages);
11791
11810
  return {
11792
11811
  kind: "context.project",
11793
11812
  project
@@ -11926,15 +11945,12 @@ var createPackageDefinitionBase = (kind, definition) => {
11926
11945
  };
11927
11946
  var kbPackage = (definition) => {
11928
11947
  const base = createPackageDefinitionBase("kb", definition);
11929
- const distribution = normalizePackageDistribution(definition.distribution ?? { knowledgeNamespace: definition.name });
11930
- if (distribution === undefined) {
11931
- throw new TypeError("KB package distribution must resolve to a knowledge namespace.");
11932
- }
11948
+ const distribution = normalizePackageDistribution(definition.distribution);
11933
11949
  return {
11934
11950
  kind: "package.kb",
11935
11951
  ...base,
11936
11952
  navigation: normalizePackageNavigation(definition.navigation),
11937
- distribution
11953
+ ...distribution === undefined ? {} : { distribution }
11938
11954
  };
11939
11955
  };
11940
11956
  var llmsPackage = (definition) => ({
@@ -11950,6 +11966,7 @@ export {
11950
11966
  llmsPackage,
11951
11967
  kbPackage,
11952
11968
  extractTs,
11969
+ extractCustom,
11953
11970
  defineProject,
11954
11971
  customPhase,
11955
11972
  compileProse,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/context",
3
- "version": "0.6.1-beta.3",
3
+ "version": "0.6.1-beta.5",
4
4
  "type": "module",
5
5
  "description": "Context SDK — project-local configuration and workspace primitives",
6
6
  "license": "MIT",
package/phases.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type EntityStatus, type FileCaptureProcessorDefinition, type KnowledgeCollection, type MarkdownTransform, type PackageKind, type PackageSelectDefinition, type DocumentMainlineCollection } from "./contracts.js";
1
+ import { type FileCaptureProcessorDefinition, type KnowledgeCollection, type MarkdownTransform, type PackageKind, type PackageSelectDefinition, type DocumentMainlineCollection } from "./contracts.js";
2
2
  import { DOCUMENT_COMPILE_ACTION_SCHEMA_VERSION } from "./documentEvidence.js";
3
3
  import type { DocumentSourceDefinition, DocumentSourceType, FileSourceDefinition, FileSourceReference, LarkSourceDefinition, LarkSourceReference, RepoProjectSourceDefinition, SourceCollectionReference, SourceDefinition } from "./sources.js";
4
4
  export type PhaseResourceReference = {
@@ -10,13 +10,13 @@ export type PhaseResourceReference = {
10
10
  sourceType: DocumentSourceType;
11
11
  path: string;
12
12
  } | {
13
- kind: "unapproved.entities";
13
+ kind: "lifecycle.candidates";
14
14
  path: string;
15
15
  collection?: KnowledgeCollection;
16
- status?: EntityStatus;
16
+ status?: "draft" | "rejected";
17
17
  } | {
18
- kind: "unapproved.structure";
19
- path: "unapproved/structure.yaml";
18
+ kind: "lifecycle.structure";
19
+ path: ".tmp/context-runtime/lifecycle/structure.yaml";
20
20
  profileCollection?: DocumentMainlineCollection;
21
21
  status?: "draft" | "confirmed" | "frozen";
22
22
  } | {
@@ -28,6 +28,9 @@ export type PhaseResourceReference = {
28
28
  kind: "knowledge.approved";
29
29
  path: "knowledge";
30
30
  select?: PackageSelectDefinition;
31
+ } | {
32
+ kind: "knowledge.decisions";
33
+ path: "knowledge/decisions.json";
31
34
  } | {
32
35
  kind: "package.template";
33
36
  path: string;
@@ -71,6 +74,56 @@ export type ExtractTsPhaseDefinition = {
71
74
  initialStatus: "draft";
72
75
  };
73
76
  };
77
+ export interface CustomCodeEvidence {
78
+ source: string;
79
+ file: string;
80
+ symbol: string;
81
+ kind: string;
82
+ digest: string;
83
+ line?: number;
84
+ }
85
+ export interface CustomCodeCandidateReview {
86
+ title: string;
87
+ summary: string;
88
+ behaviorSummary?: string;
89
+ edgeSummary?: string;
90
+ signals: readonly string[];
91
+ reason: string;
92
+ }
93
+ export interface CustomCodeCandidateEdge {
94
+ type: "contains" | "depends_on";
95
+ from: string;
96
+ to: string;
97
+ relationType: string;
98
+ evidence: readonly CustomCodeEvidence[];
99
+ }
100
+ export interface CustomCodeCandidateDraft {
101
+ nodeRef: string;
102
+ kind: string;
103
+ visibility: string;
104
+ module: string;
105
+ markdown: string;
106
+ evidence: readonly CustomCodeEvidence[];
107
+ review: CustomCodeCandidateReview;
108
+ edges?: readonly CustomCodeCandidateEdge[];
109
+ }
110
+ export interface CustomCodeExtractionResult {
111
+ candidates: readonly CustomCodeCandidateDraft[];
112
+ }
113
+ export interface CustomCodeExtractionContext {
114
+ projectRoot: string;
115
+ runId: string;
116
+ }
117
+ export type CustomCodeExtractor = (context: CustomCodeExtractionContext) => CustomCodeExtractionResult | Promise<CustomCodeExtractionResult>;
118
+ export type ExtractCustomPhaseDefinition = {
119
+ kind: "phase.extract.custom";
120
+ id: string;
121
+ reads: readonly PhaseResourceReference[];
122
+ writes: readonly PhaseResourceReference[];
123
+ sources: readonly RepoProjectSourceDefinition[];
124
+ collection: "codegraph";
125
+ extract: CustomCodeExtractor;
126
+ };
74
127
  export declare const NO_ENTRY_DETECTED: "NO_ENTRY_DETECTED";
75
128
  export declare class ExtractTsConfigurationError extends TypeError {
76
129
  readonly code: "NO_ENTRY_DETECTED";
@@ -134,7 +187,7 @@ export type CustomPhaseDefinition = {
134
187
  writes: readonly PhaseResourceReference[];
135
188
  run: ContextPhase;
136
189
  };
137
- export type PhaseDefinition = ExtractTsPhaseDefinition | CaptureFilePhaseDefinition | CaptureLarkPhaseDefinition | AlignProsePhaseDefinition | CompileProsePhaseDefinition | ReviewValidityPhaseDefinition | CustomPhaseDefinition;
190
+ export type PhaseDefinition = ExtractTsPhaseDefinition | ExtractCustomPhaseDefinition | CaptureFilePhaseDefinition | CaptureLarkPhaseDefinition | AlignProsePhaseDefinition | CompileProsePhaseDefinition | ReviewValidityPhaseDefinition | CustomPhaseDefinition;
138
191
  export declare function mdxJsonDocs(options?: {
139
192
  include?: readonly string[];
140
193
  documentExtensions?: readonly string[];
@@ -165,6 +218,12 @@ export declare const extractTs: (definition: {
165
218
  exportedOnly?: boolean;
166
219
  transform?: MarkdownTransform | readonly MarkdownTransform[];
167
220
  }) => ExtractTsPhaseDefinition;
221
+ export declare const extractCustom: (definition: {
222
+ id: string;
223
+ sources: readonly RepoProjectSourceDefinition[];
224
+ collection: "codegraph";
225
+ extract: CustomCodeExtractor;
226
+ }) => ExtractCustomPhaseDefinition;
168
227
  export declare const reviewValidity: (definition: {
169
228
  collection: KnowledgeCollection;
170
229
  payload?: string;