Skip to content

✨ Pharaoh + sphinx-needs agile traceability with sphinx-codelinks#5

Open
ubmarco wants to merge 9 commits into
mainfrom
pharaoh-sphinx-needs-traceability
Open

✨ Pharaoh + sphinx-needs agile traceability with sphinx-codelinks#5
ubmarco wants to merge 9 commits into
mainfrom
pharaoh-sphinx-needs-traceability

Conversation

@ubmarco

@ubmarco ubmarco commented Jun 6, 2026

Copy link
Copy Markdown
Member

What

Sets up sphinx-needs in the docs and a traceability model that pairs
agile terminology with the tool-error reasoning of ISO 26262-8 §11
("Confidence in the use of software tools"), wired to the source and test
trees via sphinx-codelinks and governed by Pharaoh.

Model

flowchart LR
    test["test (TEST_)"]
    check["check (CHECK_)"]
    rest["restriction (REST_)"]
    err["err (ERR_)"]
    feat["feat (FEAT_)"]
    story["story (STORY_)"]
    impl["impl (IMPL_)"]

    test -->|verifies| feat
    test -.->|prevents| err
    check -->|detects| err
    rest -->|avoids| err
    err -->|affects| feat
    feat -->|realizes| story
    impl -->|links| feat
Loading

Agile spine: a story is realized by feats.
Tool-error layer (ISO 26262-8 §11): each feat can exhibit errs; every
error is treated by prevention or mitigation.

Treatment Type Link Meaning
Prevention test prevents → err proves the error cannot occur structurally
Mitigation check detects → err runtime/CI check confirms it didn't occur
Mitigation restriction avoids → err usage constraint removes the precondition

A test also verifies → feat (it tests the feature); prevents is the
optional extra when a test structurally rules out an error. impl
(links → feat) is the orthogonal code→feature trace. Lifecycle
open → in_progress → implemented.

Type Prefix Authored in
story STORY_ RST
feat FEAT_ RST
err ERR_ RST
check CHECK_ RST
restriction REST_ RST
impl IMPL_ one-line need in src/ (sphinx-codelinks)
test TEST_ one-line need in tests/ (sphinx-codelinks)

Documentation

New docs/source/specs/ section — approach (the ISO 26262-8 §11 method
plus the node/link diagram), stories, features, errors, mitigations, and
traceability (live needtables + the two src-trace directives).

sphinx-codelinks (ubCode-compatible)

Configured under the [codelinks] table in docs/ubproject.toml, so ubCode
reads the same config. Two one-line-need projects: impl in src/, test in
tests/. Forward need → code via :source_doc:; reverse code → need via
the impl/test needs. The incoming rule ("every feat has an impl", "every err
has a treatment") is not yet schema-validatable —
sphinx-needs#1590.

Pharaoh

.pharaoh/project/ tailoring (artefact catalog, id scheme, lifecycle, per-type
checklists) + pharaoh.toml (advisory mode, reverse-eng gates, required-link
chains). Vendored Copilot agents under .github/ (first commit).

Verification

  • sphinx-build -nW --keep-goingbuild succeeded, 0 warnings
  • needs.json: 24 needs (2 story / 4 feat / 5 err / 4 impl / 7 test /
    1 check / 1 restriction); all links resolve; every error treated
  • pytest -m "not bazel": 106 passed
  • ruff + taplo clean; tailoring validates against the Pharaoh schemas

Commits

  1. 🔧 Add Pharaoh Copilot agent definitions — vendored .github/ files.
  2. ✨ NEW: sphinx-needs agile traceability via sphinx-codelinks — initial setup.
  3. ♻️ Restructure needs: agile spine + ISO 26262-8 §11 tool-error model.
  4. ✨ Tests verify features; move trace diagram to Approach.

ubmarco added 9 commits June 6, 2026 16:19
Vendor the Pharaoh plugin's GitHub Copilot agents and prompts so the
@pharaoh.* agents are available in VS Code Copilot Chat. Added by
pharaoh:setup:

- .github/agents/pharaoh.*.agent.md (73)
- .github/prompts/pharaoh.*.prompt.md (7)
- .github/copilot-instructions.md
Set up sphinx-needs and a lightweight, agile traceability model (aligned
with useblocks/ubconnect rather than a heavyweight V-model), wired to the
source and test trees with sphinx-codelinks and governed by Pharaoh.

Need types (declared in docs/ubproject.toml):
- feat      user-observable capability (RST)
- comp_req  testable obligation, :satisfies: a feat (RST)
- err       failure condition, handled in a feat via
            :tested_in: / :checked_in: / :mitigated_in: (RST)
- impl      one-line sphinx-codelinks need in src/, :links: a feat
- test      one-line need in tests/, :verifies: a comp_req and/or
            :detects: an err (ISO 26262-8 Part 8 fault detection)

Lifecycle open -> in_progress -> implemented, enforced via the status
field schema enum.

sphinx-codelinks is configured entirely under the [codelinks] table in
ubproject.toml (so ubCode consumes the same config), with two
one-line-need projects scanning src/ and tests/. Forward need->code trace
via :source_doc:; reverse code->need trace via the impl/test needs. The
incoming "every feat has an impl / every comp_req has a test" rule is not
yet schema-validatable (sphinx-needs#1590); documented in the new
docs/source/specs/ section, which also carries a Mermaid diagram of the
node/link structure.

Pharaoh tailoring (.pharaoh/project/) declares the artefact catalog, id
scheme, lifecycle state machine, and per-type review checklists.
pharaoh.toml sets advisory mode, reverse-eng gates, and required-link
chains.

Tooling: sphinx-needs>=8.1, sphinx-codelinks, and sphinxcontrib-mermaid
added to the docs dependency group (sphinx-needs moved out of dev so the
docs build is self-contained).

Verified: docs build clean under `sphinx-build -nW --keep-going`;
needs.json has 24 needs (4 feat / 4 comp_req / 4 err / 4 impl / 8 test)
with all links resolving; test suite unchanged (106 passed); ruff and
taplo clean.
Rework the need/link model per review feedback.

- Add `story` at the top; `feat` now :realizes: a story.
- Replace the err->feat handling links (tested_in/checked_in/mitigated_in)
  with a single `err :affects: feat`, and move treatment to dedicated types:
  - `test`        :prevents: an err (structural prevention; one-line in tests/)
  - `check`       :detects:  an err (runtime/CI mitigation; RST)
  - `restriction` :avoids:   an err (usage-constraint mitigation; RST)
- Drop `comp_req` (not part of the agile spine); keep `impl` (code trace).

An error is treated by EITHER prevention (a test proves it cannot occur) OR
mitigation for errors that can occur (a check detects it at runtime/CI, or a
restriction removes its precondition — e.g. long paths -> enable long-path
support or avoid Windows).

Document the approach (ISO 26262-8 §11 mapping: err = tool impact;
test/check/restriction = prevention/detection measures) in a new
docs/source/specs/approach.rst, and update the Mermaid diagram + traceability
tables. Tailoring, pharaoh.toml chains, id scheme, and per-type checklists
updated to match; test one-line needs re-pointed from `verifies comp_req` to
`prevents err`.

Verified: sphinx-build -nW clean; needs.json has 20 needs (2 story / 4 feat /
5 err / 4 impl / 3 test / 1 check / 1 restriction), all links resolve, every
error treated; 106 tests pass; ruff + taplo clean; tailoring validates against
the Pharaoh schemas.
Per review:
- A `test` now :verifies: the feature it exercises (mandatory) and may also
  :prevents: an error (optional). Re-add the four feature-verifying test
  needs; the three error-guarding tests now carry both links.
- Move the Mermaid node/link diagram from traceability.rst into approach.rst
  (with the new test -> feat edge).

ubproject.toml: add the `verifies` link; the tests codelinks project's
one-line fields become [title, id, verifies, prevents(optional), type, status].
pharaoh.toml: chain "test -> err" -> "test -> feat". artefact-catalog: test
required_links [verifies], optional_links [prevents]. Checklists updated.

Verified: sphinx-build -nW clean; 24 needs (2 story / 4 feat / 5 err / 4 impl /
7 test / 1 check / 1 restriction); all links resolve; 7 tests verify a feature
(3 also prevent an error); every error treated; 106 tests pass; ruff + taplo
clean; tailoring schema-valid.
Style each node in the approach.rst Mermaid diagram with its need type's
declared color from ubproject.toml (story/feat/err/check/restriction/impl/test),
so the diagram is visually consistent with how needs render elsewhere. Also
normalize the `test` type color from the named `#DarkTurquoise` to the
equivalent hex `#00CED1` so the declared color and the diagram fill are
identical.
Wrap the check and restriction nodes in a Mermaid subgraph labelled
"Mitigation" (dashed frame) in approach.rst, so the diagram visually
separates the two mitigation treatments from prevention (test). Add a
sentence noting the grouping.
Wrap the test and impl nodes (both authored in code as sphinx-codelinks
one-line needs — test in tests/, impl in src/) in a Mermaid subgraph
labelled "Codelinks" (blue dashed frame) in approach.rst, and note the
grouping in the prose.
Each err body named the need that treats it in prose (e.g. "Prevented
structurally by TEST_COLLISION_001"), duplicating a link that already
lives as an outgoing field on the other need: test :prevents:, check
:detects:, restriction :avoids:. The model is outgoing-only, so those
already surface on the err as its incoming "prevented by" / "detected
by" / "avoided by" backlink — the prose reference added nothing.

Drop the redundant references. For the prevention cases the trailing
sentence goes entirely (the guard behaviour is already stated, and the
section heading says "Prevented by a test"); for the check and
restriction cases keep the rationale for why the error is mitigated
rather than prevented, just without naming the treating need.
CHECK_MOUNTCOUNT_001's body ended with "Status is in_progress until the
CI job is wired up", restating the :status: in_progress field in prose.
The status field and the traceability tables already carry the
lifecycle, so the sentence was pure duplication.

Generalises the round-before link-in-body cleanup to non-link fields:
no structured field (status here, as with the link fields earlier)
should be re-encoded in a need's body text. An index sweep of all 24
needs' content confirmed this was the only remaining case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant