markharness

0036: knowledge intent-from-strictdoc generates a Knowledge Intent from a StrictDoc JSON export

Status

Accepted (decided 2026-09-29; implemented).

Context

0023 defines source: external Requirements, and 0030 adds the external-side identifier source_key (the StrictDoc MID is recommended). The CLI offers no way to register the requirements of an existing StrictDoc project as those Requirements; the only route is writing one knowledge reconcile Intent entry per requirement by hand (issue #88; 358 requirements in a real project). import accepts only native and junit, never writes knowledge, and always emits a CanonicalSnapshot.

strictdoc export --formats=json writes the whole project to a single out/json/index.json (verified with strictdoc 0.30.1). Sections and requirements nest under DOCUMENTS[] via NODES; a requirement node has _NODE_TYPE: "REQUIREMENT" and a MID. The following facts drive the design.

Decision

1. knowledge intent-from-strictdoc only prints an Intent YAML to stdout and writes nothing

markharness knowledge intent-from-strictdoc --input out/json/index.json \
  [--sdoc-root <dir>]... [-d <dir>] | markharness knowledge reconcile -

Writing to knowledge stays with the existing knowledge reconcile, which provides atomic writes, --check and id-based idempotency without reimplementation. It is not import --source strictdoc, so import keeps its property of always emitting a CanonicalSnapshot.

2. The only input is a StrictDoc JSON export file

markharness does not run strictdoc and does not parse requirement bodies (design principle P5: the Core does not know external formats). The user runs strictdoc export and passes the output file via --input.

3. What is imported and which fields are generated

Walk DOCUMENTS[].NODES recursively and import only nodes with _NODE_TYPE == "REQUIREMENT" (SECTION is only descended into; custom grammar types are out of scope). Each requirement yields a Requirement with:

Field Value
id sd-<full MID> (a MID is lowercase hex, a valid slug)
source external
source_key the MID (as recommended by 0030)
source_locator §4
source_revision current
axis []

A MID must be lowercase hex of one or more digits (the length is not checked). Because the Intent is assembled by formatting, any other value must not reach id (a slug) or the YAML.

4. source_locator is resolved through an index of requirement MIDs

The JSON has no source path and Markdown documents have no document MID, so the requirement’s own MID is used to find its file. Scan *.sdoc, *.md and *.markdown under --sdoc-root (repeatable; default: the project root) and index the lines that declare a MID:

If exactly one file declares the requirement’s MID, its path is the source_locator. It is relative to the project root with / separators (the same base knowledge reconcile uses when it runs git hash-object at the project root). Each --sdoc-root must be inside the project root.

This scan does not interpret StrictDoc. It does not read the syntax of requirements or the node structure; it only recognizes lines that declare a MID and the boundaries of the literal regions above.

5. Any inconsistency rejects the whole run

If any of the following holds, print diagnostics, exit non-zero, and emit no Intent at all:

6. Preconditions the user must satisfy

Invariants

Consequences

Alternatives considered and rejected