ckb/wiki/decisions/0002-software-module-design.md
Michał Kopeć 0c06cb64ab Restore point before wiki reset
Commit all in-flight work — ckb-module and ckb-reset skills, the
.agents/modules/ scaffold, OPENSPEC docs, decision records D-0001 and
D-0002, graph edges and workload summaries — so the reset that follows
is fully recoverable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:56:41 +02:00

113 lines
5.7 KiB
Markdown

---
type: decision
tldr: The `software` module keeps code as gitignored plain clones in `src/`, runs OpenSpec at both KB-root and per-repo level with a hybrid vendor/depend split, and links the two spec levels with `implements`/`implemented_by`.
status: accepted
decided_on: 2026-09-20
decided_by: Michał Kopeć
affects: /wiki/decisions/0001-opt-in-file-based-kb-modules.md, /wiki/index.md
confidence: 0.85
quality: 0.8
last_updated: 2026-09-20
freshness_window_days: 365
retention: high
---
# D-0002 — Design of the opt-in `software` module
**Status:** Accepted · **Decided:** 2026-09-20 · **Deciders:** Michał Kopeć
## Context
Some knowledge bases document software the user is actively building. In that
case the source code lives in `src/`, usually as one or more *independent* git
repositories with their own remotes — a git repo inside a git repo. The user
also wants OpenSpec-driven iterative development available in that mode.
This is the first concrete module under
[[D-0001]] / [D-0001](/wiki/decisions/0001-opt-in-file-based-kb-modules.md),
and four sub-questions had to be settled: how code is hosted, where specs live,
whether OpenSpec's own workflow instructions are vendored or depended on, and
how two spec levels avoid becoming two sources of truth.
## Decision
**Code hosting.** `src/<repo>/` holds plain clones, gitignored (`src/*`, as
`libs/*` already is). No submodules. Because the code may be absent from a
fresh clone, each repo also gets a durable `type: repository` entity page in
`wiki/` recording its remote URL, default branch, language, build command,
`src/` path, and owner — that page, not the clone, is the durable artifact.
**`src/` is not a cascade layer.** It is primary evidence, like `raw/archive/`:
`ckb-retrieve` may open and cite it when verifying a claim, but it never answers
"what is entity X", and `ckb-ingest` does not treat code as inbox material.
**Spec location — both levels.** OpenSpec runs at the KB root (cross-cutting
capabilities spanning multiple `src/` repos) *and* inside each `src/<repo>/`
(implementation specs that travel with the code in its own repo).
**Vendoring — hybrid.** The KB-root spec layer is served by a module-owned
skill, because a KB-root `openspec/` is not a normal OpenSpec repo install (no
code beneath it, no single repo it governs) and the module must own instructions
for it regardless. The per-`src`-repo layer delegates to OpenSpec's own native
install and instructions, and the module reports plainly when OpenSpec is
missing rather than substituting its own workflow. The module additionally owns
the bridge in both directions: an archived OpenSpec change becomes a
`wiki/decisions/NNNN-*.md` record, and current specs sync into `type: spec`
entity pages.
**Drift rule.** KB-level specs state *what* and *why* across repos; `src`-level
specs state *how* a given repo implements it. The two are linked by
`implements:` / `implemented_by:` frontmatter, which becomes graph edges.
`ckb-lint` gains checks for KB-level specs with no implementer and `src`-level
specs whose parent was archived or superseded.
## Rationale
Gitignored clones avoid embedded-repo warnings and keep code out of KB history,
while each repo keeps pushing to its own origin; submodules would pin commits
that go stale against daily work in `src/`. Specs at both levels reflect a real
distinction — cross-repo contracts genuinely differ from per-repo implementation
— and the hybrid vendoring split follows from that same distinction rather than
splitting the difference: only the level OpenSpec doesn't natively serve is
owned locally. The `implements`/`implemented_by` link exists specifically so the
two-level arrangement produces a lint signal when the levels disagree, instead
of two silently divergent truths.
## Consequences
- `.gitignore` gains `src/*` rules.
- New frontmatter types `repository`, `component`, `spec`, and optional `repo:`,
`commit:`, `spec_id:`, `implements:`, `implemented_by:` fields — a
`kb_schema_version` bump to `1.5`, additive only.
- Module skills needed: a code-mapping skill (`src/<repo>` → entity pages, with
a recorded commit hash so staleness is detectable) and a KB-root OpenSpec +
bridge skill.
- `ckb-sync-changes` must never `git add` under `src/`, and should report each
`src/` repo's dirty/ahead state separately.
- `ckb-retrieve` gains code as a verification source; `ckb-lint` gains the src
and spec-drift checks; OKF and Starlight exports exclude `src/`.
- The module is unusable at the `src/` level until OpenSpec is installed
separately — it is not on PATH as of this decision.
## Alternatives considered
- **Git submodules for `src/`** — code travels with the KB and is pinned to a
commit, which is genuinely attractive for "what did the wiki describe at that
point". Rejected for submodule friction on every sync and pins going stale.
- **Specs only inside each `src/` repo** — OpenSpec's native case, nothing to
own locally, but no home for contracts spanning several repos.
- **Specs only at KB root** — one place to look, but specs stop travelling with
the code they govern and fall out of the repo's own PR flow.
- **Vendoring OpenSpec's workflow wholesale** — self-contained, works with
nothing installed, tailorable to KB conventions. Rejected: it means
maintaining a fork of an external workflow, and `ckb-upgrade` would have two
upstreams to track.
- **Depending on OpenSpec at both levels** — nothing to maintain, but leaves the
KB-root layer with no instructions at all, since OpenSpec doesn't serve that
case.
## Sources
Chat conversation, 2026-09-20 — design evaluation of a source-code/software KB
mode, including the user's explicit choices on mechanism, code hosting, spec
location, and vendoring. See `workload/2026-09-20_summary.md`.