@c4a/context-cli 0.6.1-beta.6 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -80200,7 +80200,7 @@ function renderProseSections(input) {
80200
80200
  function renderApprovedParentIndexMarkdown(input) {
80201
80201
  const localized = localizeProseSourceRefs([...new Set(input.record.source_refs)]);
80202
80202
  const title = input.record.review.title;
80203
- const description = input.record.review.summary.trim() || `${title} parent index.`;
80203
+ const description = input.record.review.behavior_summary?.trim() || `${title} parent index.`;
80204
80204
  const nodeType = input.record.kind;
80205
80205
  const children = input.record.parent_index?.children;
80206
80206
  if (children === undefined || children.length === 0) {
@@ -80255,7 +80255,7 @@ function renderApprovedProseMarkdown(input) {
80255
80255
  const localized = localizeProseSourceRefs(canonicalRefs);
80256
80256
  const localRefsByCanonicalRef = new Map(canonicalRefs.map((ref2, index2) => [ref2, localized.localRefs[index2] ?? ""]));
80257
80257
  const title = input.record.review.title;
80258
- const description = input.record.review.summary.trim() || `${title} document knowledge.`;
80258
+ const description = input.record.review.behavior_summary?.trim() || `${title} document knowledge.`;
80259
80259
  const nodeType = input.record.kind;
80260
80260
  const tags = [...new Set(["docs", "prose", nodeType, input.record.module].filter((tag) => tag.length > 0))];
80261
80261
  const frontmatter = import_yaml23.default.stringify({
@@ -81981,7 +81981,6 @@ import { dirname as dirname24, join as join39, posix as pathPosix, relative as r
81981
81981
  init_cliFeedback();
81982
81982
  init_errors();
81983
81983
  init_exitCode();
81984
- var import_yaml25 = __toESM(require_dist3(), 1);
81985
81984
 
81986
81985
  // src/project/packageDistribution.ts
81987
81986
  function packageKnowledgeNamespace(pkg) {
@@ -82101,6 +82100,122 @@ function planKnowledgeDirectoryIndexes(items, navigation) {
82101
82100
  }).sort((left, right) => left.relPath.localeCompare(right.relPath));
82102
82101
  }
82103
82102
 
82103
+ // src/project/packageKnowledgeProjection.ts
82104
+ var import_yaml25 = __toESM(require_dist3(), 1);
82105
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u;
82106
+ var CONTEXT_METADATA_BLOCK_RE = /<!--\s*context:(summary|source_refs|audit)\b[\s\S]*?\/context:\1\s*-->[ \t]*(?:\r?\n){0,2}/giu;
82107
+ var CONTEXT_SECTION_OPEN_RE = /^[ \t]*<!--\s*context:section\b[^>]*-->[ \t]*(?:\r?\n){0,2}/gimu;
82108
+ var CONTEXT_SECTION_CLOSE_RE = /(?:\r?\n)?^[ \t]*<!--\s*\/context:section\s*-->[ \t]*(?:\r?\n){0,2}/gimu;
82109
+ var PACKAGE_OMITTED_FIELDS = [
82110
+ "node_ref",
82111
+ "view_ref",
82112
+ "node_type",
82113
+ "node_tags",
82114
+ "generated",
82115
+ "children",
82116
+ "visibility",
82117
+ "code_symbols",
82118
+ "relationship_mode",
82119
+ "code_edges",
82120
+ "candidate_fingerprint",
82121
+ "resource",
82122
+ "sources"
82123
+ ];
82124
+ var PACKAGE_INVENTORY_FIELDS = [
82125
+ "node_type",
82126
+ "node_tags",
82127
+ "generated",
82128
+ "visibility",
82129
+ "code_symbols",
82130
+ "candidate_fingerprint"
82131
+ ];
82132
+ var COMPILER_ONLY_TAGS = new Set(["docs", "prose", "parent-index"]);
82133
+ function isRecord15(value) {
82134
+ return value !== null && typeof value === "object" && !Array.isArray(value);
82135
+ }
82136
+ function stringList2(value) {
82137
+ if (!Array.isArray(value))
82138
+ return [];
82139
+ return value.filter((item) => typeof item === "string" && item.trim().length > 0);
82140
+ }
82141
+ function parseKnowledgeFrontmatter(content3) {
82142
+ const match = FRONTMATTER_RE.exec(content3);
82143
+ if (match?.[1] === undefined)
82144
+ return {};
82145
+ try {
82146
+ const parsed = import_yaml25.parse(match[1]);
82147
+ return isRecord15(parsed) ? parsed : {};
82148
+ } catch {
82149
+ return {};
82150
+ }
82151
+ }
82152
+ function isSourceRoutingTag(tag, sources) {
82153
+ return sources.some((source3) => {
82154
+ const separator = source3.indexOf(":");
82155
+ if (separator < 0)
82156
+ return false;
82157
+ const locator = source3.slice(separator + 1);
82158
+ return locator.startsWith(`${tag}/`);
82159
+ });
82160
+ }
82161
+ function projectedTags(frontmatter) {
82162
+ const sources = stringList2(frontmatter.sources);
82163
+ return [...new Set([
82164
+ ...stringList2(frontmatter.tags).filter((tag) => !COMPILER_ONLY_TAGS.has(tag) && !isSourceRoutingTag(tag, sources)),
82165
+ ...stringList2(frontmatter.node_tags)
82166
+ ])];
82167
+ }
82168
+ function packageKnowledgeDescription(value) {
82169
+ if (typeof value !== "string")
82170
+ return value;
82171
+ const normalized = value.trim();
82172
+ if (/^Reachable edges:\s[\s\S]*\.\s*$/u.test(normalized))
82173
+ return;
82174
+ const withoutGeneratedEdges = normalized.replace(/\s+Reachable edges:\s[\s\S]*\.\s*$/u, "").trim();
82175
+ if (withoutGeneratedEdges.length > 0)
82176
+ return withoutGeneratedEdges;
82177
+ return normalized;
82178
+ }
82179
+ function packageKnowledgeFrontmatter(frontmatter) {
82180
+ const projected = { ...frontmatter };
82181
+ for (const field of PACKAGE_OMITTED_FIELDS)
82182
+ delete projected[field];
82183
+ const description = packageKnowledgeDescription(projected.description);
82184
+ if (description === undefined)
82185
+ delete projected.description;
82186
+ else
82187
+ projected.description = description;
82188
+ const tags = projectedTags(frontmatter);
82189
+ if (tags.length > 0)
82190
+ projected.tags = tags;
82191
+ else
82192
+ delete projected.tags;
82193
+ return projected;
82194
+ }
82195
+ function packageKnowledgeMetadata(frontmatter) {
82196
+ const metadata = {};
82197
+ for (const field of PACKAGE_INVENTORY_FIELDS) {
82198
+ if (frontmatter[field] !== undefined)
82199
+ metadata[field] = frontmatter[field];
82200
+ }
82201
+ return Object.keys(metadata).length > 0 ? metadata : undefined;
82202
+ }
82203
+ function projectPackageKnowledgeMarkdown(content3) {
82204
+ const match = FRONTMATTER_RE.exec(content3);
82205
+ if (match === null)
82206
+ return content3;
82207
+ const frontmatter = parseKnowledgeFrontmatter(content3);
82208
+ if (Object.keys(frontmatter).length === 0)
82209
+ return content3;
82210
+ const body = content3.slice(match[0].length).replace(CONTEXT_METADATA_BLOCK_RE, "").replace(CONTEXT_SECTION_OPEN_RE, "").replace(CONTEXT_SECTION_CLOSE_RE, `
82211
+ `);
82212
+ const yaml3 = import_yaml25.stringify(packageKnowledgeFrontmatter(frontmatter)).trimEnd();
82213
+ return `---
82214
+ ${yaml3}
82215
+ ---
82216
+ ${body}`;
82217
+ }
82218
+
82104
82219
  // src/project/packageIndexes.ts
82105
82220
  var MARKDOWN_LINK_RE = /(?<!!)\[[^\]\n]*\]\(([^)\n]+)\)/gu;
82106
82221
  var OKF_OUTPUT_ROOTS = new Set(["wikis", "guides", "rules", "feats"]);
@@ -82145,20 +82260,6 @@ async function walkFiles2(root2) {
82145
82260
  files.sort((left, right) => left.relPath.localeCompare(right.relPath));
82146
82261
  return files;
82147
82262
  }
82148
- function isRecord15(value) {
82149
- return value !== null && typeof value === "object" && !Array.isArray(value);
82150
- }
82151
- function parseFrontmatter4(content3) {
82152
- const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(content3);
82153
- if (!match?.[1])
82154
- return {};
82155
- try {
82156
- const parsed = import_yaml25.parse(match[1]);
82157
- return isRecord15(parsed) ? parsed : {};
82158
- } catch {
82159
- return {};
82160
- }
82161
- }
82162
82263
  function stringField5(record, key, fallback = "") {
82163
82264
  const value = record[key];
82164
82265
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : fallback;
@@ -82233,7 +82334,9 @@ function addTreeNode(nodes, segments, item, depth = 0, prefix = "") {
82233
82334
  }
82234
82335
  function knowledgeInventory(files, templateRelPath, navigation = DEFAULT_PACKAGE_NAVIGATION, pkg) {
82235
82336
  const items = files.map((file) => {
82236
- const frontmatter = parseFrontmatter4(file.content);
82337
+ const productionFrontmatter = parseKnowledgeFrontmatter(file.content);
82338
+ const frontmatter = packageKnowledgeFrontmatter(productionFrontmatter);
82339
+ const productionMetadata = packageKnowledgeMetadata(productionFrontmatter);
82237
82340
  const logicalOutputRelPath = okfPackagePathForKnowledgePath(file.relPath);
82238
82341
  const outputRelPath = pkg === undefined ? logicalOutputRelPath : packageKnowledgeOutputPath(pkg, file.relPath);
82239
82342
  const sourcePath = file.relPath;
@@ -82241,12 +82344,12 @@ function knowledgeInventory(files, templateRelPath, navigation = DEFAULT_PACKAGE
82241
82344
  const { collection: okfRoot, pathWithinCollection, segments, parentPath } = splitKnowledgePath(logicalOutputRelPath);
82242
82345
  const okfRootPath = pkg === undefined ? okfRoot : packageOkfRootPath(pkg, okfRoot);
82243
82346
  const group = groupNameForSegments(segments);
82244
- const sources = Array.isArray(frontmatter.sources) ? frontmatter.sources : [];
82347
+ const sources = Array.isArray(productionFrontmatter.sources) ? productionFrontmatter.sources : [];
82245
82348
  const firstSource = sources.find((source4) => typeof source4 === "string");
82246
82349
  const source3 = (firstSource ?? "").replace(/^repo:/u, "") || group;
82247
82350
  const hrefFromTemplate = relativeMarkdownHref(templateRelPath, outputRelPath);
82248
- const nodeRef = stringField5(frontmatter, "node_ref");
82249
- const viewRef = stringField5(frontmatter, "view_ref");
82351
+ const nodeRef = stringField5(productionFrontmatter, "node_ref");
82352
+ const viewRef = stringField5(productionFrontmatter, "view_ref");
82250
82353
  return {
82251
82354
  path: outputRelPath,
82252
82355
  sourcePath,
@@ -82273,7 +82376,8 @@ function knowledgeInventory(files, templateRelPath, navigation = DEFAULT_PACKAGE
82273
82376
  parentPath,
82274
82377
  depth: segments.length,
82275
82378
  segments,
82276
- tags: tagsField(frontmatter)
82379
+ tags: tagsField(frontmatter),
82380
+ ...productionMetadata === undefined ? {} : { production_metadata: productionMetadata }
82277
82381
  };
82278
82382
  });
82279
82383
  const byGroup = new Map;
@@ -82908,7 +83012,8 @@ function packageBuildInventory(input) {
82908
83012
  title: item.title,
82909
83013
  type: item.type,
82910
83014
  group: item.group,
82911
- source: item.source
83015
+ source: item.source,
83016
+ ...item.production_metadata === undefined ? {} : { production_metadata: item.production_metadata }
82912
83017
  })),
82913
83018
  groups: inventory.groups.map((group) => ({
82914
83019
  name: group.name,
@@ -83260,7 +83365,7 @@ init_workspace();
83260
83365
  init_packageTemplateReview();
83261
83366
  var KNOWLEDGE_ROOT4 = "knowledge";
83262
83367
  var PACKAGE_FINGERPRINT_ROOT = join42(".tmp", "context-runtime", "packages");
83263
- var PACKAGE_BUILDER_PROTOCOL_VERSION = "v10-flat-package-roots";
83368
+ var PACKAGE_BUILDER_PROTOCOL_VERSION = "v11-consumer-frontmatter";
83264
83369
  function assertPackageOutputDir(pkg) {
83265
83370
  const expected = `dist/${pkg.name}`;
83266
83371
  if (pkg.outDir !== expected || !isSafeRelativePath2(pkg.outDir)) {
@@ -83487,7 +83592,7 @@ function knowledgeBundle(pkg, files) {
83487
83592
  if (file.relPath !== distPath) {
83488
83593
  lines.push(`<!-- approved_path: ${file.relPath} -->`, "");
83489
83594
  }
83490
- lines.push(file.content.trim());
83595
+ lines.push(projectPackageKnowledgeMarkdown(file.content).trim());
83491
83596
  return lines.join(`
83492
83597
  `);
83493
83598
  }).join(`
@@ -83548,7 +83653,7 @@ async function writeSelectedKnowledge(input) {
83548
83653
  assertSafeRenderedPath2(outputRelPath, "knowledge path");
83549
83654
  const outputPath = join42(input.projectRoot, input.pkg.outDir, outputRelPath);
83550
83655
  await mkdir23(dirname26(outputPath), { recursive: true });
83551
- await writeFile19(outputPath, file.content, "utf8");
83656
+ await writeFile19(outputPath, projectPackageKnowledgeMarkdown(file.content), "utf8");
83552
83657
  written++;
83553
83658
  }
83554
83659
  return written;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/context-cli",
3
- "version": "0.6.1-beta.6",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "description": "Local CLI for capturing, compiling, and governing knowledge workspaces",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@c4a/agent-graph": "0.2.3",
24
- "@c4a/context": "0.6.1-beta.6",
24
+ "@c4a/context": "0.6.2",
25
25
  "commander": "^11.0.0",
26
26
  "fast-xml-parser": "^5.10.1",
27
27
  "handlebars": "^4.7.8",
package/plugins/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.1-beta.6
1
+ 0.6.2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "context",
3
3
  "description": "Maintain a project-local knowledge workspace through init and next-step agent guidance.",
4
- "version": "0.6.1-beta.6",
4
+ "version": "0.6.2",
5
5
  "author": {
6
6
  "name": "c4a"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context",
3
- "version": "0.6.1-beta.6",
3
+ "version": "0.6.2",
4
4
  "description": "Maintain a project-local knowledge workspace through init and next-step agent guidance.",
5
5
  "author": {
6
6
  "name": "c4a"
@@ -18,7 +18,7 @@
18
18
  "skills": "./skills/",
19
19
  "interface": {
20
20
  "displayName": "C4A Context",
21
- "shortDescription": "Initialize and advance a local, source-linked project knowledge workspace.\nv0.6.1-beta.6",
21
+ "shortDescription": "Initialize and advance a local, source-linked project knowledge workspace.\nv0.6.2",
22
22
  "longDescription": "Create a Context workspace and use agent-guided next steps to register sources, run extraction, review candidates, build package outputs, and verify health without silently mutating source repositories.",
23
23
  "developerName": "c4a",
24
24
  "category": "Productivity",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "context",
3
3
  "displayName": "C4A Context",
4
- "version": "0.6.1-beta.6",
4
+ "version": "0.6.2",
5
5
  "description": "Maintain a project-local knowledge workspace through init and next-step agent guidance.",
6
6
  "author": {
7
7
  "name": "Context4AI",
@@ -2,7 +2,7 @@
2
2
  "schema": "agent-graph.bundle.v1",
3
3
  "provider": {
4
4
  "id": "c4a/context",
5
- "version": "0.6.1-beta.6"
5
+ "version": "0.6.2"
6
6
  },
7
7
  "providerManifest": "provider.yaml",
8
8
  "graphs": [
@@ -143,12 +143,12 @@
143
143
  {
144
144
  "id": "context.sdk.package-outputs",
145
145
  "path": "resources/manuals/guides/package-outputs.md",
146
- "digest": "sha256:bddba5a43edd230583dc286f74992e28a29bda73382799fa0ca0bf1a23014ec5"
146
+ "digest": "sha256:df6236373c23ffde93283b0999450250d90fa1e961185f83b9060a6ba56400fc"
147
147
  },
148
148
  {
149
149
  "id": "context.sdk.package-templates",
150
150
  "path": "resources/manuals/reference/package-templates.md",
151
- "digest": "sha256:ea34fa9a683915c8508d95423e3d87111349fc927accad4761ecfa3bd3204db1"
151
+ "digest": "sha256:32d5fd550304d76fe011aadce4abcb0321f656c710cbeb91d964b463316561d5"
152
152
  },
153
153
  {
154
154
  "id": "context.sdk.project-api",
@@ -451,7 +451,7 @@
451
451
  },
452
452
  {
453
453
  "path": "provider.yaml",
454
- "digest": "sha256:ad1b825734418814f1ac3673d329070228b6b8004cd821c39a3224c6d30935dd"
454
+ "digest": "sha256:0edd1fb11947dbf99179fc715b1a9182a4ed8ffe2007ff1859c09eb2aba609d5"
455
455
  },
456
456
  {
457
457
  "path": "resources/diagnostics/projection-stale.md",
@@ -503,11 +503,11 @@
503
503
  },
504
504
  {
505
505
  "path": "resources/manuals/guides/package-outputs.md",
506
- "digest": "sha256:bddba5a43edd230583dc286f74992e28a29bda73382799fa0ca0bf1a23014ec5"
506
+ "digest": "sha256:df6236373c23ffde93283b0999450250d90fa1e961185f83b9060a6ba56400fc"
507
507
  },
508
508
  {
509
509
  "path": "resources/manuals/reference/package-templates.md",
510
- "digest": "sha256:ea34fa9a683915c8508d95423e3d87111349fc927accad4761ecfa3bd3204db1"
510
+ "digest": "sha256:32d5fd550304d76fe011aadce4abcb0321f656c710cbeb91d964b463316561d5"
511
511
  },
512
512
  {
513
513
  "path": "resources/manuals/reference/project-api.md",
@@ -633,5 +633,5 @@
633
633
  "graphDependencies": {
634
634
  "workspace": []
635
635
  },
636
- "digest": "sha256:9496e5137e372e4711605465046811bf322c53603bc7b8c5fbfa07df0862d0eb"
636
+ "digest": "sha256:f9d3b6ea8d0b93df323af7557c9729ecb328a260c5389ed8869c21e1290726d3"
637
637
  }
@@ -1,6 +1,6 @@
1
1
  schema: agent-graph.provider.v1
2
2
  id: c4a/context
3
- version: 0.6.1-beta.6
3
+ version: 0.6.2
4
4
  name: Context workflow
5
5
  description: Internal work contract for Context knowledge workspaces.
6
6
  graphs:
@@ -84,7 +84,11 @@ carries the structure-first query discipline: start from OKF directory indexes,
84
84
  inspect page `sources` / `context:section` source_ref metadata, cite
85
85
  page/section evidence, and report explicit gaps when the package does not cover
86
86
  a requested fact. It does not treat direct grep over bundled OKF root
87
- directories as the primary discovery path. Its final template-author section
87
+ directories as the primary discovery path. When indexes do not narrow the
88
+ scope, or a candidate page is too large to read directly, its bundled
89
+ `scripts/search.mjs` provides deterministic BM25 ranking over mechanically
90
+ bounded Markdown chunks. Search results are leads; page bodies and typed edge
91
+ records remain the evidence. Its final template-author section
88
92
  requires package authors to replace or edit the generic routing when the
89
93
  package needs project-specific terminology, entry points, known limits, or
90
94
  task workflows. Authors may explicitly accept the generic default when it is
@@ -102,10 +106,12 @@ as `wikis/`, `guides/`, `rules/`, or `feats/`; when selected, `context build`
102
106
  copies them into the package and generates root-aware directory indexes for them
103
107
  as needed. Selected OKF roots always have an index; smaller child directories
104
108
  are folded into their nearest generated ancestor index by default. These roots
105
- contain Markdown with OKF fields and C4A extension fields at the top level, plus
106
- `context:section` source_ref span comments. C4A extension fields such as `sources`,
107
- `visibility`, and `code_symbols` are not nested under `context`, and page
108
- frontmatter does not contain `source_refs`. The package root is an agent
109
+ contain consumer-oriented Markdown with reader-facing frontmatter and no Context
110
+ lifecycle comments. Node identity, source metadata, code symbol lists,
111
+ relationship records, generated-child records, and candidate fingerprints are
112
+ kept out of each page. `context-build-inventory.json` maps distributed paths to
113
+ approved knowledge paths and exposes package-visible structure; exact Section
114
+ evidence remains in the mapped `knowledge/` page. The package root is an agent
109
115
  package; the OKF-compatible interchange surface is the selected OKF root
110
116
  subtrees under `dist/<package-name>/`. The required template entry and final
111
117
  output path are both `wikis/index.md`.
@@ -157,7 +157,9 @@ src/package-templates/
157
157
  │ │ └── index.md
158
158
  │ └── skills/
159
159
  │ └── knowledge-query/
160
- └── SKILL.md
160
+ ├── SKILL.md
161
+ │ └── scripts/
162
+ │ └── search.mjs
161
163
  └── llms/
162
164
  └── llms.txt
163
165
  ```
@@ -181,6 +183,10 @@ The default kb template includes:
181
183
  default entry OKF root is `wikis/`; packages that select additional internal
182
184
  collections expose
183
185
  `guides/`, `rules/`, or `feats/` indexes when those roots are selected.
186
+ - `skills/knowledge-query/scripts/search.mjs`, a dependency-free BM25 fallback
187
+ for exact terms, mixed keyword queries, and large Markdown indexes. It chunks
188
+ mechanically, returns inspectable paths and line ranges, and never replaces
189
+ source-backed relationship evidence.
184
190
  - `wikis/index.md`, the editable OKF bundle entry page for the generated
185
191
  `dist/<package-name>/wikis/` directory.
186
192
 
@@ -237,14 +243,15 @@ explicitly accept the unchanged default through the package-template Review
237
243
  Route. Do not add a package-name Skill by default; add one only when the user
238
244
  wants project-specific behavior beyond knowledge lookup.
239
245
 
240
- ## C4A OKF Profile
246
+ ## Context OKF Profiles
241
247
 
242
- Approved Markdown and kb package OKF output are an OKF superset:
248
+ Approved Markdown under `knowledge/` is the production source of truth:
243
249
 
244
250
  - top-level YAML frontmatter uses OKF fields such as `type`, `title`,
245
251
  `description`, `tags`, `timestamp`, and `resource`;
246
- - C4A extension metadata such as `sources`, `visibility`, and `code_symbols`
247
- also lives at the top level;
252
+ - Context production metadata such as `sources`, `node_type`, `visibility`,
253
+ `code_symbols`, relationship records, and `candidate_fingerprint` also lives
254
+ at the top level;
248
255
  - do not nest C4A extension metadata under `context`; fields such as
249
256
  `context.sources` and `context.code_symbols` are not part of the 0.6 profile;
250
257
  - section provenance lives in `<!-- context:section ... source_ref="..." -->`
@@ -253,6 +260,15 @@ Approved Markdown and kb package OKF output are an OKF superset:
253
260
  section source refs when needed;
254
261
  - do not add `context` or `schema` fields.
255
262
 
263
+ Package knowledge pages under `dist/<package-name>/` use a consumer projection.
264
+ They retain reader-facing fields such as `title`, `type`, `description`, `tags`,
265
+ `timestamp`, and custom non-lifecycle fields. Node identity, `resource`,
266
+ `sources`, Section evidence comments, and build-only fields are omitted from the
267
+ page. `context-build-inventory.json` records the distributed path, approved
268
+ knowledge path, node identity, source summary, and package-visible structure.
269
+ Maintainers return to the mapped `knowledge/` page for exact `sources` and
270
+ `source_ref` attribution. `knowledge/` is never rewritten by this projection.
271
+
256
272
  Accepted section `source_ref` forms:
257
273
 
258
274
  ```text
@@ -262,7 +278,7 @@ src-N#span:<heading-hint> L<start>-<end>@<span-hash>
262
278
 
263
279
  The code symbol form includes the source-relative file so same-name symbols in
264
280
  different files resolve to one exact symbol-index row. Consumers should still
265
- treat the complete `source_ref` as opaque. Codegraph pages keep
281
+ treat the complete `source_ref` as opaque. Production codegraph pages keep
266
282
  `candidate_fingerprint` at the top level and do not duplicate this evidence in
267
283
  `code_origin`.
268
284
 
@@ -280,7 +296,7 @@ The OKF-compatible surface is the selected `wikis/`, `guides/`, `rules/`, and
280
296
 
281
297
  1. Selects approved Markdown from `knowledge/`.
282
298
  2. Renders all files from `template.path`.
283
- 3. Copies selected approved Markdown into the package output.
299
+ 3. Projects selected approved Markdown into consumer-oriented package pages.
284
300
  4. For `llmsPackage`, appends selected knowledge to `llms.txt` when the template
285
301
  does not already use `{{knowledge}}` or `{{approvedKnowledge}}`.
286
302
  5. Writes deterministic package inventory such as
@@ -288,7 +304,9 @@ The OKF-compatible surface is the selected `wikis/`, `guides/`, `rules/`, and
288
304
  6. Writes output under `dist/<package-name>/`.
289
305
 
290
306
  `context-build-inventory.json` records what was selected and why. Each selected
291
- file includes `selected_by` entries such as `{ "kind": "collection" }`,
307
+ file includes `selected_by` entries such as `{ "kind": "collection" }` and a
308
+ `production_metadata` object for selected page-level production fields. Child
309
+ and relationship records use the inventory's canonical structure projection,
292
310
  `{ "kind": "okf_root" }`, `{ "kind": "include" }`, or
293
311
  `{ "kind": "default" }`. The inventory also exposes package-visible typed
294
312
  edges under `structure.edge_records`; these records are filtered to edges whose