diff --git a/CHANGELOG.md b/CHANGELOG.md index f498fd9..9da06ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ The project follows Semantic Versioning after the first release. ### Changed +- Architecture Decision Records 0001–0007 now include Context, Decision, and + Consequences plus verified APA 7th-edition references to official Language + Server Protocol 3.18, JSON-RPC 2.0, NIST FIPS 180-4, PlantUML language and + security, RFC 3986/8259, and GitHub protected-branch catalog records. - Hourly development now routes an open same-repository pull request into an RCA-driven exact-head remediation session, verifies candidate actions against live review and Check evidence, publishes only a normal fast-forward repair diff --git a/docs/adr/0001-source-authority.md b/docs/adr/0001-source-authority.md index 4c96d2a..ecb33bc 100644 --- a/docs/adr/0001-source-authority.md +++ b/docs/adr/0001-source-authority.md @@ -2,5 +2,58 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -Diagram source remains the system of record. Derived renderings, diagnostics, symbols, model proposals, and previews bind to an exact SHA-256 source revision and cannot silently replace the caller's source. Hosts own save/commit/persistence. This enables offline/manual operation and deterministic stale-proposal rejection. +## Context + +DiagramWeave is a source-first editor platform for PlantUML and later text +diagram languages. Hosts may cache editor buffers, previews, diagnostics, +outlines, and model suggestions, but those surfaces are derived. If a derived +view, hidden editor store, or generated artifact silently replaced the caller's +text, manual offline editing would no longer be the system of record. + +PlantUML's own language documentation treats the textual description as the +input that produces a diagram (PlantUML, n.d.-a, n.d.-b). DiagramWeave therefore +needs a revision identifier that binds every derived result to one exact source +string. Core already computes that identifier as a lowercase SHA-256 digest of +the UTF-8 source. SHA-256 is specified by the Secure Hash Standard: any change +to the message produces, with very high probability, a different digest +(National Institute of Standards and Technology, 2015). + +## Decision + +Diagram source remains the system of record. Derived renderings, diagnostics, +symbols, model proposals, and previews bind to an exact SHA-256 source revision +and cannot silently replace the caller's source. Hosts own save, commit, and +persistence. This enables offline and manual operation and deterministic +stale-proposal rejection. + +The foundation introduces no DiagramWeave-owned database. A host may persist +files, but it must write the exact accepted source rather than a reconstructed +or rendered substitute. + +## Consequences + +- Core `hashSource` remains the only revision algorithm for proposals, renderer + artifacts, and CLI reports. +- A proposal, preview, or render whose base digest does not match the current + source fails closed (`revision_conflict`); it is never patched onto newer + text. +- Studio, naruon, IDE adapters, and other CWL hosts can embed Core without + taking file I/O, network, or persistence into the trust kernel. +- Manual editing, validation, and local render stay usable without an account, + network connection, or LLM. +- A later persistence design must keep source files authoritative and use + descriptive two-word-or-longer `snake_case` object names. + +## References — APA 7th edition + +National Institute of Standards and Technology. (2015). *Secure Hash Standard +(SHS)* (FIPS PUB 180-4). U.S. Department of Commerce. +https://doi.org/10.6028/NIST.FIPS.180-4 + +PlantUML. (n.d.-a). *PlantUML*. Retrieved August 24, 2026, from +https://plantuml.com/ + +PlantUML. (n.d.-b). *PlantUML Language Reference Guide*. Retrieved August 24, +2026, from https://plantuml.com/guide diff --git a/docs/adr/0002-model-proposals.md b/docs/adr/0002-model-proposals.md index 8b61f6e..9b84bda 100644 --- a/docs/adr/0002-model-proposals.md +++ b/docs/adr/0002-model-proposals.md @@ -2,5 +2,52 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -Generated edits remain proposals until the host chooses to apply them. Core validates proposal shape, exact source revision, requested/effective ranges, and visible scope expansion. Manual editing works independently from any provider. This keeps source changes reviewable and avoids hidden mutation paths. +## Context + +Model output, included diagram content, comments, and labels are untrusted data. +A generated edit that wrote files, committed, or silently mutated the buffer +would violate source authority (ADR-0001) and make manual editing depend on a +provider. + +The product contract is that AI proposes and the host decides. Core therefore +needs a reviewable value type, not a mutation API. Assistant content arrives as +JSON text that must be parsed strictly before any range math. JSON is specified +as a text-based interchange format with a closed set of structural rules (Bray, +2017). The proposal then binds to the exact SHA-256 digest of the source from +which it was produced (National Institute of Standards and Technology, 2015). + +## Decision + +Generated edits remain proposals until the host chooses to apply them. Core +validates proposal shape, exact source revision, requested and effective +ranges, and visible scope expansion. Manual editing works independently from +any provider. This keeps source changes reviewable and avoids hidden mutation +paths. + +`previewEditProposal` and `applyEditProposal` return new strings. They do not +save, commit, push, render, or execute. An effective range outside the +requested range requires an explicit expansion reason and host approval. + +## Consequences + +- Studio, naruon, IDE adapters, and CLI hosts display a diff and invoke Core + separately; receiving a proposal does not change a document. +- Stale proposals fail with `revision_conflict`. Expanded edits fail with + `scope_expansion_required` unless `allowScopeExpansion` is explicit. +- Provider adapters may only emit Core-validated `EditProposal` values. They + cannot add a second apply path. +- Manual editing, local render, and editor intelligence remain complete + without an LLM. +- Future apply-on-save or auto-commit behavior would require a new ADR and + would break this decision. + +## References — APA 7th edition + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) data interchange +format* (RFC 8259). RFC Editor. https://doi.org/10.17487/RFC8259 + +National Institute of Standards and Technology. (2015). *Secure Hash Standard +(SHS)* (FIPS PUB 180-4). U.S. Department of Commerce. +https://doi.org/10.6028/NIST.FIPS.180-4 diff --git a/docs/adr/0003-renderer-isolation.md b/docs/adr/0003-renderer-isolation.md index 5cc455a..b4f87ce 100644 --- a/docs/adr/0003-renderer-isolation.md +++ b/docs/adr/0003-renderer-isolation.md @@ -2,5 +2,66 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -The foundation renderer receives source through stdin, invokes host-supplied Java/PlantUML without a shell, uses an empty child environment and PlantUML SANDBOX, suppresses source metadata, and bounds source, output, diagnostics, and execution time. It does not download dependencies, follow includes, or fetch resources. Raw child output remains inside the renderer boundary; reusable callers receive validated artifacts and fixed safe diagnostics. +## Context + +PlantUML can include local files and remote URLs, embed source in generated +PNG or SVG metadata, and emit unstructured stderr. Those capabilities are +unsafe as a default reusable boundary for Studio, CLI, naruon, and other CWL +hosts. + +PlantUML documents a `SANDBOX` security profile in which the process cannot +access local files or URLs and allowlists are ignored (PlantUML, n.d.-c). The +official command-line record documents stdin `-pipe` transfer, `-nometadata` +suppression of encoded source in generated files, and `-stdrpt:1` standard +error reports (PlantUML, n.d.-a). Those published controls are the basis for a +local, host-supplied Java/JAR renderer that never downloads dependencies. + +Raw child output remains untrusted. Callers need validated SVG or PNG bytes and +fixed safe diagnostics, not stderr, labels, or source excerpts. Diagnostic +ranges reuse the Language Server Protocol line/character shape so CLI and +editor hosts share one record (Microsoft, n.d.). + +## Decision + +The foundation renderer receives source through stdin, invokes host-supplied +Java/PlantUML without a shell, uses an empty child environment and PlantUML +`SANDBOX`, suppresses source metadata, and bounds source, output, diagnostics, +and execution time. It does not download dependencies, follow includes, or +fetch resources. Raw child output remains inside the renderer boundary; +reusable callers receive validated artifacts and fixed safe diagnostics. + +A later include-capable mode is a separate explicit policy, not a relaxation of +this package's `SANDBOX` contract. PlantUML's newer command-line redesign is +documented as beta on the same official page and is not treated as the current +renderer contract (PlantUML, n.d.-a). + +## Consequences + +- The package requires absolute Java and JAR paths from the host. It does not + bundle, discover, or download PlantUML, Graphviz, or fonts. +- Generated artifacts are immutable and tied to the Core SHA-256 source + revision. SVG remains untrusted active content; hosts must not inject it + through `innerHTML`. +- Public errors never include raw stderr, raw PlantUML labels, source + excerpts, executable paths, or environment values. +- Studio, CLI, naruon, and the Language Server depend on the package contract + rather than spawning Java themselves. +- Operating-system cgroup, job-object, or container quotas remain a host + responsibility for hostile or high-volume diagrams. + +## References — APA 7th edition + +Microsoft. (n.d.). *Language Server Protocol specification, version 3.18*. +Retrieved August 24, 2026, from +https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/ + +PlantUML. (n.d.-a). *Command line*. Retrieved August 24, 2026, from +https://plantuml.com/command-line + +PlantUML. (n.d.-b). *PlantUML*. Retrieved August 24, 2026, from +https://plantuml.com/ + +PlantUML. (n.d.-c). *Deploy PlantUML safely*. Retrieved August 24, 2026, from +https://plantuml.com/security diff --git a/docs/adr/0004-authoritative-symbol-tree.md b/docs/adr/0004-authoritative-symbol-tree.md index 44e0821..78b1459 100644 --- a/docs/adr/0004-authoritative-symbol-tree.md +++ b/docs/adr/0004-authoritative-symbol-tree.md @@ -2,5 +2,67 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -Document symbols, flat compatibility symbols, completion context, folding, hover, definition, and compatible later navigation features derive from one bounded conservative structural tree over the latest accepted source snapshot. Hierarchy is created only when complete explicit syntax proves ownership. Ambiguous PlantUML syntax fails by omission. This prevents feature-specific parsers from disagreeing about declarations and ranges. +## Context + +Editor intelligence needs outlines, completion context, folding, hover, +definition, and references that agree about the same declarations and ranges. +Separate feature parsers would drift, especially around PlantUML's implicit +participants, relation endpoints, includes, macros, and quoted labels. + +The Language Server Protocol defines document symbols as constructs inside one +text document, with a display name, kind, full `range`, and narrower +`selectionRange`, and it uses UTF-16 positions unless another encoding is +negotiated (Microsoft, n.d.). PlantUML's official class-diagram and +sequence-diagram records define explicit package, class, participant, and +related declaration syntax, including aliases and quoted display names +(PlantUML, n.d.-a, n.d.-c). Those records do not authorize inferring symbols +from relations, includes, or renderer output. + +PlantUML outlines must therefore fail by omission rather than invent implicit, +malformed, included, or macro-generated symbols. + +## Decision + +Document symbols, flat compatibility symbols, completion context, folding, +hover, definition, and compatible later navigation features derive from one +bounded conservative structural tree over the latest accepted source snapshot. +Hierarchy is created only when complete explicit syntax proves ownership. +Ambiguous PlantUML syntax fails by omission. This prevents feature-specific +parsers from disagreeing about declarations and ranges. + +Hierarchy requires one unmatched unquoted package or namespace declaration +brace closed in stack order by a standalone brace with identical indentation. +Exact boolean `hierarchicalDocumentSymbolSupport: true` selects +`DocumentSymbol[]`; every other capability state derives frozen +`SymbolInformation[]` from the same tree. + +## Consequences + +- Features walk the same frozen tree iteratively. A second PlantUML scanner is + not introduced for compatibility, folding, hover, definition, or references. +- Quoted, commented, incomplete, crossed, or malformed structure remains flat + or omitted. Duplicate or ambiguous identifiers do not produce a guessed + target. +- UTF-16 code-unit offsets are preserved through multilingual text and emoji; + comment masking must not shift later ranges. +- Studio, IDE adapters, `dweave-lsp`, naruon, and other CWL hosts reuse the + same session results. +- A future full PlantUML semantic AST, include expansion, or workspace index + would be a new ADR, not an implicit widening of this tree. + +## References — APA 7th edition + +Microsoft. (n.d.). *Language Server Protocol specification, version 3.18*. +Retrieved August 24, 2026, from +https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/ + +PlantUML. (n.d.-a). *Class diagram*. Retrieved August 24, 2026, from +https://plantuml.com/class-diagram + +PlantUML. (n.d.-b). *PlantUML Language Reference Guide*. Retrieved August 24, +2026, from https://plantuml.com/guide + +PlantUML. (n.d.-c). *Sequence diagram*. Retrieved August 24, 2026, from +https://plantuml.com/sequence-diagram diff --git a/docs/adr/0005-transport-neutral-lsp.md b/docs/adr/0005-transport-neutral-lsp.md index 55e09f3..69f13e2 100644 --- a/docs/adr/0005-transport-neutral-lsp.md +++ b/docs/adr/0005-transport-neutral-lsp.md @@ -2,5 +2,64 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -The reusable Language Server package owns lifecycle, snapshots, diagnostics, capabilities, symbols, completion, folding, hover, and navigation semantics. The stdio package owns only bounded JSON-RPC framing, serialization, process lifecycle, and stable transport error mapping. Studio, IDE adapters, naruon, and future transports reuse the same session instead of duplicating feature logic. +## Context + +DiagramWeave must expose the same editor intelligence to Studio, IDE adapters, +the `dweave-lsp` process, naruon, and other CWL hosts. Duplicating lifecycle, +snapshot, diagnostic, symbol, completion, folding, hover, or navigation logic +in each transport would create incompatible UTF-16 ranges and capability +behavior. + +The Language Server Protocol specifies those feature semantics independently +of a particular byte transport and uses JSON-RPC messages with UTF-16 positions +by default (Microsoft, n.d.). JSON-RPC 2.0 is transport-agnostic: the same +request, notification, and error objects can move over stdio, sockets, or +in-process calls (JSON-RPC Working Group, 2013). Message bodies are JSON +(Bray, 2017). Document identifiers are URIs (Berners-Lee et al., 2005); +DiagramWeave treats a local file URI as an identifier and does not dereference +it. + +## Decision + +The reusable Language Server package owns lifecycle, snapshots, diagnostics, +capabilities, symbols, completion, folding, hover, and navigation semantics. +The stdio package owns only bounded JSON-RPC framing, serialization, process +lifecycle, and stable transport error mapping. Studio, IDE adapters, naruon, +and future transports reuse the same session instead of duplicating feature +logic. + +Source arrives as full-document snapshots. The session never opens, watches, +or reads workspace files. Invalid completion and other parameter failures map +to JSON-RPC `-32602` Invalid params at the transport edge. + +## Consequences + +- Embedding hosts call the transport-neutral session API directly. Process + hosts use `dweave-lsp` without a second feature implementation. +- Framing rejects malformed, oversized, duplicated, unsupported, or non-ASCII + headers. Feature packages never parse Content-Length themselves. +- Capability negotiation stays in the session. Hostile getters and proxies + fail closed to the safe presentation (for example, flat symbols). +- naruon remains a composition hub: it embeds the Language Server package and + may optionally spawn stdio, without moving feature semantics into the + transport. +- A later WebSocket, HTTP, or in-process host adapter must wrap this session + rather than reimplement diagnostics or navigation. + +## References — APA 7th edition + +Berners-Lee, T., Fielding, R., & Masinter, L. (2005). *Uniform resource +identifier (URI): Generic syntax* (RFC 3986). RFC Editor. +https://doi.org/10.17487/RFC3986 + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) data interchange +format* (RFC 8259). RFC Editor. https://doi.org/10.17487/RFC8259 + +JSON-RPC Working Group. (2013). *JSON-RPC 2.0 specification*. +https://www.jsonrpc.org/specification + +Microsoft. (n.d.). *Language Server Protocol specification, version 3.18*. +Retrieved August 24, 2026, from +https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/ diff --git a/docs/adr/0006-provider-neutral-orchestrator.md b/docs/adr/0006-provider-neutral-orchestrator.md index 9b911d5..7794d3a 100644 --- a/docs/adr/0006-provider-neutral-orchestrator.md +++ b/docs/adr/0006-provider-neutral-orchestrator.md @@ -2,5 +2,61 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 -DiagramWeave Core and local editing/rendering/editor intelligence do not depend on an LLM. Remote generated-edit capability is isolated behind the Contextual Orchestrator adapter with explicit endpoint, model, token, request bounds, timeout, and strict proposal parsing. Other provider strategies can be added through equivalent adapters without changing Core mutation/revision semantics. +## Context + +Manual editing, local render, CLI validation, and Language Server intelligence +must remain complete without an account, network connection, or LLM. Baking a +provider client into Core would make those workflows depend on remote +credentials and would couple revision semantics to one vendor API. + +Generated edits are already untrusted proposals (ADR-0002). The remaining +question is how a host optionally obtains a proposal. Contextual Orchestrator +exposes an OpenAI-compatible `POST /v1/chat/completions` boundary; DiagramWeave +depends on that published request/response shape, not on a particular worker +model. Assistant content must be one JSON object that Core can validate (Bray, +2017). The adapter hashes the exact source with SHA-256 before the request so +the returned proposal names the revision it was built from (National Institute +of Standards and Technology, 2015). + +This repository does not use an OpenAPI description for that boundary. The +adapter contract is the explicit endpoint, model, token, timeout, and JSON +proposal parse implemented in the package. + +## Decision + +DiagramWeave Core and local editing, rendering, and editor intelligence do not +depend on an LLM. Remote generated-edit capability is isolated behind the +Contextual Orchestrator adapter with explicit endpoint, model, token, request +bounds, timeout, and strict proposal parsing. Other provider strategies can be +added through equivalent adapters without changing Core mutation and revision +semantics. + +The adapter permits remote HTTPS and loopback-only HTTP. It does not read +process environment variables, persist tokens, log source or prompts, or apply +the returned edit. + +## Consequences + +- Studio, naruon, and other CWL hosts may omit the adapter entirely and still + edit, validate, render, and navigate source. +- naruon composes Core, renderer, CLI, Language Server, and optionally this + adapter as independently reusable packages. It does not become the only way + to call DiagramWeave. +- A new provider is a new adapter with the same Core-validated `EditProposal` + output. It must not introduce a hidden mutation path or a second revision + algorithm. +- Provider error bodies are not read, preventing secret or prompt reflection + into user-visible errors. +- Changing Core so that local packages require an LLM, or calling a provider + directly from Core, would require a new ADR. + +## References — APA 7th edition + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) data interchange +format* (RFC 8259). RFC Editor. https://doi.org/10.17487/RFC8259 + +National Institute of Standards and Technology. (2015). *Secure Hash Standard +(SHS)* (FIPS PUB 180-4). U.S. Department of Commerce. +https://doi.org/10.6028/NIST.FIPS.180-4 diff --git a/docs/adr/0007-automation-authority.md b/docs/adr/0007-automation-authority.md index c6b88e1..cdc0179 100644 --- a/docs/adr/0007-automation-authority.md +++ b/docs/adr/0007-automation-authority.md @@ -2,11 +2,14 @@ **Status:** Accepted **Date:** 2026-08-09 +**Updated:** 2026-08-24 ## Context Protected `main` already contains an hourly product-development workflow with two materially different actors. The OpenCode/model subprocess receives the bounded product prompt and NVIDIA model credential while GitHub repository tokens and OIDC request credentials are explicitly removed from that process. A later trusted workflow step, running under narrowly scoped GitHub job permissions, may turn a verified working-tree result into an ordinary branch and pull request. Treating those two actors as one “autonomous development” authority obscures the actual credential and review boundary. +GitHub's protected-branch record distinguishes the act of opening or updating a pull request from the checks and reviews required before anyone may integrate into a protected branch (GitHub, n.d.). DiagramWeave adopts that split: publication of a review candidate is not approval, merge, or release. + ## Decision The model-assisted development process may inspect the checked-out revision, produce a revision-bound working-tree proposal, and emit review evidence such as `PR_MESSAGE.md`; it has no repository publication, approval, merge, tag, package-publish, or release credential. @@ -21,3 +24,8 @@ Neither the model process nor the trusted publisher may manufacture independent - Model-controlled content cannot directly decide that its own change is publishable; deterministic verification and the trusted handoff boundary mediate publication. - A successfully opened PR is only a review candidate, never merge or release evidence. - Future changes that give the model process repository credentials, permit unverified publication, or combine publisher and counted-review authority require a new ADR and security/threat-model review. + +## References — APA 7th edition + +GitHub. (n.d.). *About protected branches*. Retrieved August 24, 2026, from +https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches diff --git a/docs/adr/README.md b/docs/adr/README.md index 89650ec..763afba 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -2,6 +2,10 @@ The status inside each ADR is authoritative. `Accepted` means the decision governs architecture; it does not imply a future host or active-PR feature is already implemented. +Each governing ADR records Context, Decision, and Consequences and keeps a +verified APA 7th-edition bibliography. Citations use a DOI or the publisher's +official catalog URL and omit records that could not be opened. + | ADR | Decision | Status | |---|---|---| | [0001](0001-source-authority.md) | Source text and exact revision are authoritative | Accepted |