@c4a/context 0.6.1-beta.4 → 0.6.1-beta.6

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/README.md CHANGED
@@ -55,15 +55,17 @@ configuration from a user's requirements.
55
55
  | `defineProject()` | Declares the complete project graph. |
56
56
  | `source()` and `allSources()` | References registered repo, file, or Lark source boundaries. |
57
57
  | `extractTs()` | Extracts TypeScript/TSX symbols and relationships into `codegraph` candidates. |
58
+ | `extractCustom()` | Runs a project-owned code extractor while Context owns candidate, evidence, freshness, and Review state. |
58
59
  | `alignProse()` and `compileProse()` | Structures document evidence and compiles source-bound knowledge candidates. |
59
60
  | `reviewValidity()` | Declares the review gate for one collection or the project. |
60
61
  | `customPhase()` | Adds project-specific orchestration when built-in phase factories are not enough. |
61
62
  | `kbPackage()` | Builds an Agent knowledge-base package from approved knowledge and templates. |
62
63
  | `llmsPackage()` | Builds a single text bundle for model context or RAG import. |
63
64
 
64
- Use the built-in phase factories first. `customPhase()` is an escape hatch for
65
- project-specific orchestration, not a replacement for source, extraction,
66
- review, and package lifecycle rules.
65
+ Use `extractCustom()` when a repository needs a non-TypeScript or aggregated
66
+ code extractor. Use `customPhase()` only for orchestration that does not publish
67
+ knowledge candidates; it is not a replacement for source, extraction, Review,
68
+ and package lifecycle rules.
67
69
 
68
70
  ## Knowledge Collections
69
71
 
package/README.zh-CN.md CHANGED
@@ -47,13 +47,15 @@ export default defineProject({
47
47
  | `defineProject()` | 声明完整的项目处理图。 |
48
48
  | `source()` 和 `allSources()` | 引用已经登记的代码仓库、本地文件或飞书来源边界。 |
49
49
  | `extractTs()` | 从 TypeScript/TSX 中提取符号和关系,生成 `codegraph` 候选。 |
50
+ | `extractCustom()` | 运行项目自有代码提取器,同时由 Context 维护候选、证据、新鲜度和审核状态。 |
50
51
  | `alignProse()` 和 `compileProse()` | 整理文档证据,并生成与来源绑定的知识候选。 |
51
52
  | `reviewValidity()` | 声明单个知识类型或整个项目的审核门禁。 |
52
53
  | `customPhase()` | 在内置阶段无法覆盖时增加项目专用编排。 |
53
54
  | `kbPackage()` | 使用审核通过的知识和模板构建 Agent 知识库。 |
54
55
  | `llmsPackage()` | 构建供模型上下文或 RAG 导入使用的单文件文本包。 |
55
56
 
56
- 优先使用内置阶段。`customPhase()` 是项目专用编排的扩展口,不应该绕开来源、提取、审核和打包的生命周期规则。
57
+ 非 TypeScript 或需要聚合代码事实时使用 `extractCustom()`。`customPhase()`
58
+ 只用于不发布知识候选的项目专用编排,不能绕开来源、提取、审核和打包生命周期。
57
59
 
58
60
  ## 知识分类
59
61
 
@@ -332,9 +332,20 @@ Register each source with
332
332
  flag: `--url`, `--doc-token`, or `--wiki-token`. Multiple documents may share
333
333
  one date batch; when `--module` is omitted, the CLI derives an opaque,
334
334
  credential-safe module id. Capture reads the
335
- remote document through the CLI runner, writes normalized snapshot files under
336
- `sources/lark/<date>/` as sibling document files tracked by one date-level `manifest.json`, and does not write access credentials into the
337
- 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
341
+ against converted and intentionally skipped blocks and reports evidence
342
+ completeness separately from Markdown projection quality. Unknown non-empty XML
343
+ blocks receive a generic, auditable, non-interactive projection and do not block
344
+ downstream work. Missing source content or unresolved external-resource identity
345
+ remains an evidence error and prevents downstream Review.
346
+ Snapshot files live under `sources/lark/<date>/` as sibling document files
347
+ tracked by one date-level `manifest.json`. Access credentials and transient
348
+ signed media URLs are not written into the workspace.
338
349
 
339
350
  Use a typed document reference in project declarations:
340
351
 
@@ -642,6 +653,56 @@ lookup exact when multiple files contain the same symbol name, kind, and digest;
642
653
  the complete ref remains opaque to agents. New pages keep only top-level
643
654
  `candidate_fingerprint` and do not emit `code_origin`.
644
655
 
656
+ ### `extractCustom`
657
+
658
+ Use a project-owned extractor when code facts cannot be represented by the
659
+ TypeScript symbol extractor, for example a language-specific parser or an
660
+ aggregated repository protocol:
661
+
662
+ ```ts
663
+ extractCustom({
664
+ id: "extract:service:protocol",
665
+ sources: [service],
666
+ collection: "codegraph",
667
+ extract: async ({ projectRoot }) => ({
668
+ candidates: [{
669
+ nodeRef: "service/protocol",
670
+ kind: "protocol",
671
+ visibility: "exported",
672
+ module: "service",
673
+ markdown: renderProtocol(projectRoot),
674
+ evidence: [{
675
+ source: "20260811/service",
676
+ file: "src/protocol.ts",
677
+ symbol: "protocol",
678
+ kind: "variable",
679
+ digest: "0123456789ab",
680
+ }],
681
+ review: {
682
+ title: "Service protocol",
683
+ summary: "Aggregated protocol boundary.",
684
+ signals: ["source-backed"],
685
+ reason: "Review the project-owned extraction.",
686
+ },
687
+ }],
688
+ }),
689
+ });
690
+ ```
691
+
692
+ `sources` is the complete registered repo scope for the phase. Every candidate
693
+ and edge carries structured `evidence`; the CLI validates that evidence against
694
+ the declared sources, creates canonical `source_ref` values, writes the symbol
695
+ index, candidate ledger and Review snapshots atomically, and records a phase
696
+ fingerprint. `context status` therefore treats this phase exactly like another
697
+ pending code extraction target, and Review can verify snapshot freshness
698
+ without a placeholder `extractTs` phase.
699
+
700
+ The extractor returns knowledge semantics (`nodeRef`, rendered Markdown,
701
+ Review summary and source-backed evidence). It must not write `knowledge/`,
702
+ `.tmp/context-runtime/lifecycle/candidates.jsonl`, extraction fingerprints or
703
+ Review snapshots directly. Context owns those files and preserves rejected and
704
+ unchanged-approved decisions across reruns.
705
+
645
706
  ### `reviewValidity`
646
707
 
647
708
  Declare the review step for a collection:
@@ -713,8 +774,9 @@ customPhase("custom:20260712/sample:review", async (ctx) => {
713
774
  });
714
775
  ```
715
776
 
716
- Custom phases are an escape hatch. Prefer built-in factories for source,
717
- extract, review, and package workflows. The supported runtime helpers are:
777
+ Custom phases are an orchestration escape hatch. Use `extractCustom()` instead
778
+ when project code needs to publish codegraph candidates. The supported runtime
779
+ helpers are:
718
780
 
719
781
  - `ctx.ensureSources(...)` for repo source readiness.
720
782
  - `ctx.extract.ts(...)` for declared TypeScript extraction.
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>[];
package/index.js CHANGED
@@ -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) {
@@ -11941,6 +11966,7 @@ export {
11941
11966
  llmsPackage,
11942
11967
  kbPackage,
11943
11968
  extractTs,
11969
+ extractCustom,
11944
11970
  defineProject,
11945
11971
  customPhase,
11946
11972
  compileProse,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/context",
3
- "version": "0.6.1-beta.4",
3
+ "version": "0.6.1-beta.6",
4
4
  "type": "module",
5
5
  "description": "Context SDK — project-local configuration and workspace primitives",
6
6
  "license": "MIT",
package/phases.d.ts CHANGED
@@ -74,6 +74,56 @@ export type ExtractTsPhaseDefinition = {
74
74
  initialStatus: "draft";
75
75
  };
76
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
+ };
77
127
  export declare const NO_ENTRY_DETECTED: "NO_ENTRY_DETECTED";
78
128
  export declare class ExtractTsConfigurationError extends TypeError {
79
129
  readonly code: "NO_ENTRY_DETECTED";
@@ -137,7 +187,7 @@ export type CustomPhaseDefinition = {
137
187
  writes: readonly PhaseResourceReference[];
138
188
  run: ContextPhase;
139
189
  };
140
- export type PhaseDefinition = ExtractTsPhaseDefinition | CaptureFilePhaseDefinition | CaptureLarkPhaseDefinition | AlignProsePhaseDefinition | CompileProsePhaseDefinition | ReviewValidityPhaseDefinition | CustomPhaseDefinition;
190
+ export type PhaseDefinition = ExtractTsPhaseDefinition | ExtractCustomPhaseDefinition | CaptureFilePhaseDefinition | CaptureLarkPhaseDefinition | AlignProsePhaseDefinition | CompileProsePhaseDefinition | ReviewValidityPhaseDefinition | CustomPhaseDefinition;
141
191
  export declare function mdxJsonDocs(options?: {
142
192
  include?: readonly string[];
143
193
  documentExtensions?: readonly string[];
@@ -168,6 +218,12 @@ export declare const extractTs: (definition: {
168
218
  exportedOnly?: boolean;
169
219
  transform?: MarkdownTransform | readonly MarkdownTransform[];
170
220
  }) => ExtractTsPhaseDefinition;
221
+ export declare const extractCustom: (definition: {
222
+ id: string;
223
+ sources: readonly RepoProjectSourceDefinition[];
224
+ collection: "codegraph";
225
+ extract: CustomCodeExtractor;
226
+ }) => ExtractCustomPhaseDefinition;
171
227
  export declare const reviewValidity: (definition: {
172
228
  collection: KnowledgeCollection;
173
229
  payload?: string;