feat(g2): knowledge-plane-vault renderer + vault/ skeleton#32
Conversation
…PLAN §G2 Scope: renderer `knowledge-plane-vault.ts` que, cuando `integrations.knowledge_plane.enabled: true`, emite vault/ skeleton (vault/config.md + vault/raw/.gitkeep + vault/wiki/.gitkeep). Decisiones ratificadas vs MASTER_PLAN original: - Naming: `vault/config.md` (no `vault/schema.md`) — regla G1 gana. - Renderer: `knowledge-plane-vault.ts` (no `knowledge-plane-obsidian.ts`) — nombre tool-agnostic. - Tests: perfiles sintéticos inline; sin 4º profile canónico; snapshots se mantienen en 54. - ARCHITECTURE §1.1: 2–3 frases inline; sin nueva subsección. Fase siguiente: Fase 1 — test pair RED-first. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ests knowledge-plane-vault.test.ts (15 tests, todos fallando): - opt-in gate: [] cuando enabled false/ausente; 3 archivos cuando true - paths: vault/config.md, vault/raw/.gitkeep, vault/wiki/.gitkeep - NOT vault/schema.md (naming invariant G1) - .gitkeep content = "\n" - vault/config.md: 5 secciones ##, mención Obsidian Web Clipper, referencia explícita a adapter - trailing \n en todos los archivos - determinismo byte-identical index.test.ts (+3 tests, 2 fallando): - knowledgePlaneRenderers exportado y congelado - knowledgePlaneRenderers incluido en allRenderers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renderer knowledge-plane-vault.ts: - enabled true → vault/config.md + vault/raw/.gitkeep + vault/wiki/.gitkeep - enabled false/absent → [] (opt-in gate, no throw) - Template cargado vía loadTemplate (no string inline) - Determinismo byte-identical templates/vault/config.md.hbs: - 5 secciones: ## Propósito / Estructura / Convenciones raw / Convenciones wiki / Ingestor recomendado - Obsidian Web Clipper como reference adapter (no contrato base) generator/renderers/index.ts: - knowledgePlaneRenderers: grupo congelado (6ª aplicación patrón renderer-group) - allRenderers += knowledgePlaneRenderers Suite: 538 passed (517 base + 21 nuevos), 0 regresiones. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ARCHITECTURE §1.1: actualiza referencia "no implementado" → renderer entregado en G2 (knowledge-plane-vault.ts, opt-in gate, Obsidian Web Clipper reference adapter). ROADMAP: fila g2 ⏳ → ✅ con entregables y conteo de tests (539 total). HANDOFF §1: snapshot actual apunta a g2 ✅ PR pendiente + g3 como siguiente rama. HANDOFF §9: g2 encabeza carry-overs con entregables + decisión naming ratificada; g1 movido abajo como cerrado. Suite: 539 passed (538 prev + 1 test branch-coverage gap cerrado). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
profileIntegrationsNoKP duplicaba el meta-shape literal que makeProfile ya encapsula. Introduce makeProfileWithAnswers como base compartida; makeProfile la delega. Si el type Profile añade campos obligatorios, el cambio se propaga desde un solo punto. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Determinismo test: usa dos instancias reference-inequal (makeProfile(true) × 2) en lugar de reutilizar profileEnabled — el test anterior era una tautología; ahora ejercita paths distintos en memoria. 2. knowledge-plane.md: añade punto 4 sobre noEscape:true global del template-loader — aviso forward-looking para G3/G4 si añaden interpolación de datos del profile en templates de vault. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an opt-in “knowledge plane vault” renderer to the generator, producing a minimal vault/ skeleton (config + raw/wiki directories) when integrations.knowledge_plane.enabled is set to true, and emitting nothing otherwise. This extends the existing renderer-group composition pattern with a new knowledgePlaneRenderers group.
Changes:
- Introduces
knowledge-plane-vaultrenderer gated onintegrations.knowledge_plane.enabledto emitvault/config.mdplus.gitkeepfiles forraw/andwiki/. - Adds a new Handlebars template
templates/vault/config.md.hbsdocumenting vault purpose/structure/conventions and Obsidian Web Clipper as a reference ingestor. - Extends renderer-group composition (
knowledgePlaneRenderers) and adds targeted Vitest coverage for gating, paths, and template content.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/vault/config.md.hbs | New vault config skeleton template with conventions + reference ingestor section. |
| generator/renderers/knowledge-plane-vault.ts | New opt-in renderer emitting vault/ skeleton files. |
| generator/renderers/knowledge-plane-vault.test.ts | New unit tests for gate behavior, emitted paths, content checks, determinism. |
| generator/renderers/index.ts | Adds knowledgePlaneRenderers group and includes it in allRenderers. |
| generator/renderers/index.test.ts | Tests for export/frozen-ness/inclusion of the new renderer group. |
| docs/ARCHITECTURE.md | Updates architecture doc to reflect G2 renderer delivery and behavior. |
| ROADMAP.md | Marks G2 as done and summarizes delivered artifacts. |
| MASTER_PLAN.md | Updates G2 scope/output/files/tests criteria to match implemented renderer/template. |
| HANDOFF.md | Updates current branch snapshot and carry-over status for G2/G1. |
| .claude/rules/knowledge-plane.md | Updates knowledge-plane editing rules (includes new guidance about noEscape). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| y escapar explícitamente con `{{{{raw}}}}` o sanitizar antes de inyectar. | ||
|
|
||
| 5. **Opt-in gate**: el renderer sólo emite archivos cuando | ||
| `answers["integrations.knowledge_plane.enabled"] === true`. Con `false` (default), |
There was a problem hiding this comment.
The opt-in gate expression here uses answers["integrations.knowledge_plane.enabled"], but profiles are expanded from dotted keys into a nested object by buildProfile (so the runtime shape is answers.integrations.knowledge_plane.enabled). As written, this guidance will lead to incorrect implementations; update it to reference the nested access pattern (or a dedicated getNested(answers, "integrations.knowledge_plane.enabled") helper if you prefer dotted-path access).
| `answers["integrations.knowledge_plane.enabled"] === true`. Con `false` (default), | |
| `answers.integrations.knowledge_plane.enabled === true`. Con `false` (default), |
| globalmente. Los templates de vault que añadan `{{answers.X}}` renderizarán sin HTML-escaping. | ||
| En G2 `config.md.hbs` no tiene interpolaciones — riesgo cero hoy. Si G3/G4 añade | ||
| interpolación de datos del profile, revisar si el campo puede contener input arbitrario | ||
| y escapar explícitamente con `{{{{raw}}}}` o sanitizar antes de inyectar. |
There was a problem hiding this comment.
The suggestion to “escapar explícitamente con {{{{raw}}}}” is inaccurate: Handlebars raw blocks prevent evaluation of template code but do not HTML-escape interpolated values, and there is no escape helper registered today. Since loadTemplate compiles with noEscape: true, the actionable options are to (a) introduce an escape/sanitization helper and use it for any interpolations, or (b) compile these vault templates with escaping enabled (separate loader or option override) if you want safe-by-default {{...}} behavior.
| y escapar explícitamente con `{{{{raw}}}}` o sanitizar antes de inyectar. | |
| y usar una mitigación real: sanitizar/escapar el valor antes de inyectarlo (o mediante | |
| un helper de escape registrado), o compilar esos templates con escaping habilitado si | |
| se quiere que `{{...}}` sea seguro por defecto. |
Summary
knowledge-plane-vault.ts: opt-in gate —integrations.knowledge_plane.enabled: trueemitevault/config.md+vault/raw/.gitkeep+vault/wiki/.gitkeep;false/ausente retorna[]sin error.templates/vault/config.md.hbs: 5 secciones (Propósito / Estructura / Convenciones raw / Convenciones wiki / Ingestor recomendado). Obsidian Web Clipper documentado como reference adapter, no contrato base.knowledgePlaneRenderersengenerator/renderers/index.ts(6ª aplicación patrónrenderer-group).run.tsno tocado.Decisiones ratificadas vs MASTER_PLAN original:
vault/config.md(novault/schema.md) — regla G1 gana sobre literal antiguo.knowledge-plane-vault.ts(noknowledge-plane-obsidian.ts) — nombre tool-agnostic.Test plan
knowledge-plane-vault.test.ts: opt-in gate (4), paths emitidos (4),.gitkeepcontent (2),vault/config.mdcontenido (7), invariantes estructurales (2).index.test.ts:knowledgePlaneRenderersexportado, congelado, incluido enallRenderers.ALL_RENDERERS_EXPECTED_PATHSno modificado — canonical profiles tienenenabled: false, renderer retorna[]para todos ellos. ✅ verificado.knowledge-plane-vault.ts: 93% statements, 86% branches, 100% functions. Criterio ≥85% cumplido.simplify+pre-commit-reviewpasados; advisory findings aplicados (determinismo test + notanoEscape:trueenknowledge-plane.md).🤖 Generated with Claude Code