feat(nkb): pattern dependency graph with broken-link check#18
Conversation
|
This PR needs an issue link. Add |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4cbc18cf9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
This PR needs an issue link. Add |
|
This PR needs an issue link. Add |
|
This PR needs an issue link. Add |
1 similar comment
|
This PR needs an issue link. Add |
Adds `scripts/nkb-graph.mjs` — emits a Mermaid graph of pattern→dependency edges parsed from a `## Depends-on` section in each `workflow-patterns/*.md` doc. The `--check` mode exits non-zero when any pattern references a slug with no matching `.md` file in the scanned directory, so CI can fail-closed on dangling references the same way round-1 #5 fails-closed on missing `## Sources` sections. Fixtures `fixtures/graph/{ok,broken}/` drive `tests/graph.bats` (10 cases): the ok fixture is a three-pattern chain (webhook-dedup-key → http-retry- idempotency → error-monitoring-fanout); the broken fixture adds a dangling edge to `nonexistent-upstream`. The broken-link test is the central-promise check — it asserts both the non-zero exit and that the offending edge is named in the failure output. `--format json` is supported both with and without `--check` so downstream tooling (dashboards, lint jobs) can ingest the report without re-parsing mermaid. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
This PR needs an issue link. Add |
1 similar comment
|
This PR needs an issue link. Add |
|
This PR needs an issue link. Add |
|
This PR needs an issue link. Add |
## Summary Adds `scripts/nkb-graph.mjs` — emits a Mermaid graph of pattern→dependency edges parsed from a `## Depends-on` section in each `workflow-patterns/*.md` doc. The `--check` flag exits non-zero when any pattern references a slug with no matching `.md` file in the scanned directory. This is the **structural** half of the citation-graph convention started in round-1 PR #5 (`feat(nkb): citation lint + Sources backfill on pattern docs`): PR #5 made every doc cite its external sources via `## Sources`; this PR makes every doc declare its internal cross-pattern dependencies via `## Depends-on`, and proves they all resolve. Both lints share the same fail-closed posture so CI can wire either as a required check. The schema is minimal — `## Depends-on` is followed by a bullet list of slugs, one per line, where each slug is the basename of a sibling `.md` in the same directory. A pattern with no dependencies either omits the section entirely or leaves it empty. The existing `voice-agent-elevenlabs- patterns.md` doc parses cleanly under this schema with zero edges, so the new convention is strictly additive — no backfill required on `main`. ### Fixtures `fixtures/graph/{ok,broken}/` follows the same convention as the dedupe fixture set (#15) and the stats fixture (#17): - `ok/` — three-pattern chain (`webhook-dedup-key → http-retry-idempotency → error-monitoring-fanout`). All edges resolve. - `broken/` — same chain plus a dangling edge to `nonexistent-upstream`. This is the negative-path fixture for `--check`. ### Proof Mermaid render of the ok fixture: ``` $ node scripts/nkb-graph.mjs --dir fixtures/graph/ok \`\`\`mermaid graph LR error_monitoring_fanout["error-monitoring-fanout"] http_retry_idempotency["http-retry-idempotency"] webhook_dedup_key["webhook-dedup-key"] http_retry_idempotency --> error_monitoring_fanout webhook_dedup_key --> http_retry_idempotency \`\`\` ``` Fail-closed broken-link check: ``` $ node scripts/nkb-graph.mjs --dir fixtures/graph/broken --check nkb-graph check: 1 broken link(s): - webhook-dedup-key → nonexistent-upstream (no such pattern) $ echo $? 1 ``` Real `workflow-patterns/` directory on `main` (additive, doesn't regress): ``` $ node scripts/nkb-graph.mjs --check nkb-graph check: ok — 1 pattern(s), 0 edge(s), 0 broken ``` `tests/graph.bats` (10 cases, all green locally): ``` $ bats tests/graph.bats 1..10 ok 1 graph: mermaid output lists every pattern in the ok fixture as a node ok 2 graph: edges in mermaid mirror Depends-on declarations ok 3 graph --check: ok fixture passes with exit 0 ok 4 graph --check: broken fixture fails with exit 1 and names the missing slug ok 5 graph --check --format json: ok fixture reports ok:true, broken:[] ok 6 graph --check --format json: broken fixture reports the from/to edge ok 7 graph: --format json (no --check) dumps every pattern with its deps list ok 8 graph: pattern with no Depends-on section produces zero edges from it ok 9 graph: missing --dir target exits non-zero with stderr message ok 10 graph: mermaid output marks missing dep edges with dotted-arrow annotation ``` The broken-link check (#4) is the central-promise test: it asserts both the non-zero exit and that the offending edge (`webhook-dedup-key → nonexistent-upstream`) is named verbatim in the failure output. ### Round-1 / round-2 dependencies Sits next to the other `scripts/nkb-*.mjs` round-2 deliverables — submit (#13), JSON-LD export (#14), dedupe (#15), sandbox runner (#16), adoption stats (#17) — and will slot under the unified `scripts/nkb.mjs` dispatcher established by round-1 #3 once that lands on `main`. Until then it is invokable standalone as `node scripts/nkb-graph.mjs`. Citing round-1 #5 specifically because that PR establishes the precedent of a fail-closed CI lint over `workflow-patterns/*.md`; this PR extends that pattern along the internal-link axis. ## Test plan - [x] `bats tests/graph.bats` — all 10 outcome tests pass - [x] `node scripts/nkb-graph.mjs --check` against real `workflow-patterns/` exits 0 - [x] `node scripts/nkb-graph.mjs --dir fixtures/graph/broken --check` exits 1 and names the bad edge - [ ] Reviewer confirms `## Depends-on` schema is acceptable to bolt onto existing pattern docs - [ ] Reviewer decides whether to wire `--check` into `.github/workflows/lint.yml` alongside the round-1 #5 citation lint Co-authored-by: Cody Arnold <cody@wranngle.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary Adds `scripts/nkb-graph.mjs` — emits a Mermaid graph of pattern→dependency edges parsed from a `## Depends-on` section in each `workflow-patterns/*.md` doc. The `--check` flag exits non-zero when any pattern references a slug with no matching `.md` file in the scanned directory. This is the **structural** half of the citation-graph convention started in round-1 PR #5 (`feat(nkb): citation lint + Sources backfill on pattern docs`): PR #5 made every doc cite its external sources via `## Sources`; this PR makes every doc declare its internal cross-pattern dependencies via `## Depends-on`, and proves they all resolve. Both lints share the same fail-closed posture so CI can wire either as a required check. The schema is minimal — `## Depends-on` is followed by a bullet list of slugs, one per line, where each slug is the basename of a sibling `.md` in the same directory. A pattern with no dependencies either omits the section entirely or leaves it empty. The existing `voice-agent-elevenlabs- patterns.md` doc parses cleanly under this schema with zero edges, so the new convention is strictly additive — no backfill required on `main`. ### Fixtures `fixtures/graph/{ok,broken}/` follows the same convention as the dedupe fixture set (#15) and the stats fixture (#17): - `ok/` — three-pattern chain (`webhook-dedup-key → http-retry-idempotency → error-monitoring-fanout`). All edges resolve. - `broken/` — same chain plus a dangling edge to `nonexistent-upstream`. This is the negative-path fixture for `--check`. ### Proof Mermaid render of the ok fixture: ``` $ node scripts/nkb-graph.mjs --dir fixtures/graph/ok \`\`\`mermaid graph LR error_monitoring_fanout["error-monitoring-fanout"] http_retry_idempotency["http-retry-idempotency"] webhook_dedup_key["webhook-dedup-key"] http_retry_idempotency --> error_monitoring_fanout webhook_dedup_key --> http_retry_idempotency \`\`\` ``` Fail-closed broken-link check: ``` $ node scripts/nkb-graph.mjs --dir fixtures/graph/broken --check nkb-graph check: 1 broken link(s): - webhook-dedup-key → nonexistent-upstream (no such pattern) $ echo $? 1 ``` Real `workflow-patterns/` directory on `main` (additive, doesn't regress): ``` $ node scripts/nkb-graph.mjs --check nkb-graph check: ok — 1 pattern(s), 0 edge(s), 0 broken ``` `tests/graph.bats` (10 cases, all green locally): ``` $ bats tests/graph.bats 1..10 ok 1 graph: mermaid output lists every pattern in the ok fixture as a node ok 2 graph: edges in mermaid mirror Depends-on declarations ok 3 graph --check: ok fixture passes with exit 0 ok 4 graph --check: broken fixture fails with exit 1 and names the missing slug ok 5 graph --check --format json: ok fixture reports ok:true, broken:[] ok 6 graph --check --format json: broken fixture reports the from/to edge ok 7 graph: --format json (no --check) dumps every pattern with its deps list ok 8 graph: pattern with no Depends-on section produces zero edges from it ok 9 graph: missing --dir target exits non-zero with stderr message ok 10 graph: mermaid output marks missing dep edges with dotted-arrow annotation ``` The broken-link check (#4) is the central-promise test: it asserts both the non-zero exit and that the offending edge (`webhook-dedup-key → nonexistent-upstream`) is named verbatim in the failure output. ### Round-1 / round-2 dependencies Sits next to the other `scripts/nkb-*.mjs` round-2 deliverables — submit (#13), JSON-LD export (#14), dedupe (#15), sandbox runner (#16), adoption stats (#17) — and will slot under the unified `scripts/nkb.mjs` dispatcher established by round-1 #3 once that lands on `main`. Until then it is invokable standalone as `node scripts/nkb-graph.mjs`. Citing round-1 #5 specifically because that PR establishes the precedent of a fail-closed CI lint over `workflow-patterns/*.md`; this PR extends that pattern along the internal-link axis. ## Test plan - [x] `bats tests/graph.bats` — all 10 outcome tests pass - [x] `node scripts/nkb-graph.mjs --check` against real `workflow-patterns/` exits 0 - [x] `node scripts/nkb-graph.mjs --dir fixtures/graph/broken --check` exits 1 and names the bad edge - [ ] Reviewer confirms `## Depends-on` schema is acceptable to bolt onto existing pattern docs - [ ] Reviewer decides whether to wire `--check` into `.github/workflows/lint.yml` alongside the round-1 #5 citation lint Co-authored-by: Cody Arnold <cody@wranngle.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Adds
scripts/nkb-graph.mjs— emits a Mermaid graph of pattern→dependencyedges parsed from a
## Depends-onsection in eachworkflow-patterns/*.mddoc. The
--checkflag exits non-zero when any pattern references a slugwith no matching
.mdfile in the scanned directory.This is the structural half of the citation-graph convention started in
round-1 PR #5 (
feat(nkb): citation lint + Sources backfill on pattern docs):PR #5 made every doc cite its external sources via
## Sources; this PRmakes every doc declare its internal cross-pattern dependencies via
## Depends-on, and proves they all resolve. Both lints share the samefail-closed posture so CI can wire either as a required check.
The schema is minimal —
## Depends-onis followed by a bullet list ofslugs, one per line, where each slug is the basename of a sibling
.mdin the same directory. A pattern with no dependencies either omits the
section entirely or leaves it empty. The existing
voice-agent-elevenlabs- patterns.mddoc parses cleanly under this schema with zero edges, so thenew convention is strictly additive — no backfill required on
main.Fixtures
fixtures/graph/{ok,broken}/follows the same convention as the dedupefixture set (#15) and the stats fixture (#17):
ok/— three-pattern chain (webhook-dedup-key → http-retry-idempotency → error-monitoring-fanout). All edges resolve.broken/— same chain plus a dangling edge tononexistent-upstream.This is the negative-path fixture for
--check.Proof
Mermaid render of the ok fixture:
Fail-closed broken-link check:
Real
workflow-patterns/directory onmain(additive, doesn't regress):tests/graph.bats(10 cases, all green locally):The broken-link check (#4) is the central-promise test: it asserts both
the non-zero exit and that the offending edge (
webhook-dedup-key → nonexistent-upstream) is named verbatim in the failure output.Round-1 / round-2 dependencies
Sits next to the other
scripts/nkb-*.mjsround-2 deliverables — submit(#13), JSON-LD export (#14), dedupe (#15), sandbox runner (#16), adoption
stats (#17) — and will slot under the unified
scripts/nkb.mjsdispatcherestablished by round-1 #3 once that lands on
main. Until then it isinvokable standalone as
node scripts/nkb-graph.mjs. Citing round-1 #5specifically because that PR establishes the precedent of a fail-closed
CI lint over
workflow-patterns/*.md; this PR extends that patternalong the internal-link axis.
Test plan
bats tests/graph.bats— all 10 outcome tests passnode scripts/nkb-graph.mjs --checkagainst realworkflow-patterns/exits 0node scripts/nkb-graph.mjs --dir fixtures/graph/broken --checkexits 1 and names the bad edge## Depends-onschema is acceptable to bolt onto existing pattern docs--checkinto.github/workflows/lint.ymlalongside the round-1 feat(n8n_knowledge_base): citation lint + Sources backfill on pattern docs #5 citation lint