@nurix/etna 0.20.2 → 0.20.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/data/catalog/rules/testing.md +20 -14
  2. package/data/harness-index.json +1 -1
  3. package/data/harnesses/code/CLAUDE.md +15 -8
  4. package/data/harnesses/code/agents/bookkeeper.md +1 -1
  5. package/data/harnesses/code/agents/issue-bridge.md +16 -0
  6. package/data/harnesses/code/agents/maintenance.md +36 -3
  7. package/data/harnesses/code/docs/README.md +1 -1
  8. package/data/harnesses/code/docs/history/backlog.md +1 -1
  9. package/data/harnesses/code/docs/structure.md +2 -2
  10. package/data/harnesses/code/harness.json +12 -2
  11. package/data/harnesses/code/hooks/awareness.mjs +75 -14
  12. package/data/harnesses/code/hooks/compliance.mjs +26 -18
  13. package/data/harnesses/code/hooks/lib/exempt.mjs +7 -5
  14. package/data/harnesses/code/hooks/lib/frozen.mjs +9 -6
  15. package/data/harnesses/code/hooks/lib/ledger.mjs +26 -4
  16. package/data/harnesses/code/hooks/lib/ownership.mjs +73 -2
  17. package/data/harnesses/code/hooks/lib/plans.mjs +2 -2
  18. package/data/harnesses/code/hooks/lib/repo.mjs +22 -0
  19. package/data/harnesses/code/hooks/lib/state.mjs +38 -2
  20. package/data/harnesses/code/hooks/lib/sweep.mjs +37 -15
  21. package/data/harnesses/code/rules/testing.md +20 -14
  22. package/data/harnesses/code/skills/boundary/SKILL.md +2 -2
  23. package/data/harnesses/code/skills/codegraph/SKILL.md +57 -0
  24. package/data/harnesses/code/skills/documentation/SKILL.md +12 -5
  25. package/data/harnesses/code/skills/documentation/references/frontmatter.md +29 -4
  26. package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +18 -1
  27. package/data/harnesses/code/skills/documentation/templates/feature.md +1 -0
  28. package/data/harnesses/code/skills/documentation/templates/plan.md +3 -1
  29. package/data/harnesses/code/skills/documentation/templates/ux-behavior.md +1 -1
  30. package/data/harnesses/code/skills/issue-bridge/SKILL.md +55 -0
  31. package/data/harnesses/code/skills/issue-bridge/references/trackers/github.md +37 -0
  32. package/data/harnesses/code/skills/issue-bridge/references/trackers/jira.md +40 -0
  33. package/data/harnesses/code/skills/issue-bridge/references/trackers/linear.md +37 -0
  34. package/data/harnesses/code/skills/testing/SKILL.md +24 -8
  35. package/data/harnesses/delivery/agents/maintenance.md +36 -3
  36. package/data/harnesses/delivery/harness.json +4 -2
  37. package/data/harnesses/delivery/skills/documentation/SKILL.md +12 -5
  38. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +29 -4
  39. package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +18 -1
  40. package/data/harnesses/delivery/skills/documentation/templates/feature.md +1 -0
  41. package/data/harnesses/delivery/skills/documentation/templates/plan.md +3 -1
  42. package/data/harnesses/delivery/skills/documentation/templates/ux-behavior.md +1 -1
  43. package/data/harnesses/discover/harness.json +2 -0
  44. package/data/harnesses/discussion/harness.json +2 -0
  45. package/data/harnesses/etna/agents/maintenance.md +36 -3
  46. package/data/harnesses/etna/harness.json +4 -2
  47. package/data/harnesses/etna/rules/testing.md +20 -14
  48. package/data/harnesses/etna/skills/boundary/SKILL.md +2 -2
  49. package/data/harnesses/etna/skills/documentation/SKILL.md +12 -5
  50. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +29 -4
  51. package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +18 -1
  52. package/data/harnesses/etna/skills/documentation/templates/feature.md +1 -0
  53. package/data/harnesses/etna/skills/documentation/templates/plan.md +3 -1
  54. package/data/harnesses/etna/skills/documentation/templates/ux-behavior.md +1 -1
  55. package/data/harnesses/hr/harness.json +2 -0
  56. package/data/harnesses/kb-agi/harness.json +2 -0
  57. package/lib/install/plan.mjs +22 -1
  58. package/package.json +2 -2
@@ -9,10 +9,10 @@
9
9
  | Regime | During the work | Proven |
10
10
  | --- | --- | --- |
11
11
  | **Plan-driven build** | No new test files. Code only — the loop stays fast | At the verification gate, before `Status: Complete` |
12
- | **Bug fix** — a defect in shipped behavior | The regression test ships with the fix | Immediately — it fails before the change, passes after |
13
- | **Ad-hoc / non-plan change** | The test ships with the change **when it alters promised behavior** — layout, copy, and config tweaks owe none | Immediately, same discipline as a bug fix |
12
+ | **Bug fix** — a defect in shipped behavior | Fix it, drive it, then write its regression test — in the same unit of work | Before the unit ends — the pin is written once, against the fixed code |
13
+ | **Ad-hoc / non-plan change** | Make the change, drive it, then write its test **when it alters promised behavior** — layout, copy, and config tweaks owe none | Before the unit ends, same discipline as a bug fix |
14
14
 
15
- - **A bug fix cannot defer** — "fails before, passes after" is provable afterward only by reverting to the pre-fix ref, a cost nobody pays; capture the property at fix time or lose it.
15
+ - **A bug fix cannot defer past its own unit of work — but its pin comes after the fix is driven, never beside the first attempt.** A test written while the fix is still moving is rewritten on every iteration, and written by the fix's author beside the fix it proves only that the two agree. Write it once, against the fixed code; where the defect was subtle, run it once against the pre-fix code (stash the fix) so the pin is shown to bite — that is one command, not an iteration.
16
16
  - **Ad-hoc work cannot defer — there is no ledger to defer into.** A non-plan change that alters no promised behavior — a pure refactor, a rename — owes no test.
17
17
 
18
18
  ## During the loop
@@ -21,18 +21,21 @@ Rules for the plan regime between the plan gate and the verification gate:
21
21
 
22
22
  - **No new test files** — obligations wait in the plan's ledger (written at the plan gate by the `testing` skill).
23
23
  - **Existing tests broken by the plan's intended behavior change are updated to the new contract before any mid-plan commit** — the shared branch never carries a red suite, and an update is never a weakening (§ Discipline).
24
- - **A defect in the plan's own in-flux code is the loop iterating** — no test, no ledger row. **A pre-existing bug in shipped behavior is the bug-fix regime even mid-plan**: fix it with its regression test now — deferring it to the gate loses "fails before" — or send it to the backlog via Out-of-Scope Discovery. Never fix silently.
24
+ - **A defect in the plan's own in-flux code is the loop iterating** — no test, no ledger row. **A pre-existing bug in shipped behavior is the bug-fix regime even mid-plan**: fix it now and pin it at the build pass's pin step, with the unit's other pins — or send it to the backlog via Out-of-Scope Discovery. Never fix silently.
25
25
  - **The ledger is amendable while the plan is open** — the gate discharges whatever it holds at gate time.
26
26
  - **A mid-plan commit is a checkpoint, not a verification claim.**
27
27
 
28
28
  ## The gate
29
29
 
30
- **A discrete, user-triggered step.** When implementation is complete, report it and offer the gate — never run it unbidden, and never flip `Status: Complete` without it. An explicit user acceptance of finished plan work — "ship it", "commit", "looks good" — counts as the trigger; open the gate without asking again. A plan with outstanding obligations stays open, whatever the code does. The procedure — checklist, drive-then-pin ladder, row discharge, what earns a durable test — is the `testing` skill (gate mode).
30
+ **The tail of every build pass, never a separate ask.** When the unit's code is written the gate runs — drive the real surface, fix what driving finds, pin, discharge — and the session does not stop to ask whether it should. What the user decides is the freeze and the commit: "ship it", "commit", "looks good" close a plan whose gate has already run; they never open one. Never flip `Status: Complete` without the gate. A plan with outstanding obligations stays open, whatever the code does.
31
+
32
+ - **Inside the build pass the order is fixed — code → drive → fix → pin.** Tests written while the code is still moving are rewritten on every iteration, and written by the code's author beside the code they pass by construction; a judged drive is what finds the defects (below). Pinning is the last step and happens once, against code the drive has already shown to be right. The procedure — checklist, drive-then-pin ladder, row discharge, what earns a durable test — is the `testing` skill (gate mode).
31
33
 
32
34
  - **Precondition: the ledger exists.** A plan with no Test Obligations section is blocked at the gate — run the `testing` skill (plan-gate mode) on it first; an empty ledger passes vacuously and the gap surfaces only after the file is frozen.
33
- - **The verdict is never delegated** (the root policy file § Delegation), and where browser work is main-session-only (its § Runtime Notes), the driving is too. Fan-out may prepare fixtures or draft test bodies; the driving and the verdict stay inline.
35
+ - **The verdict is never delegated** (the root policy file § Delegation), and where browser work is main-session-only (its § Runtime Notes), the driving is too. **The pins are written inline, by the agent that drove the surface** — the drive is what tells it which behaviors earned a test and what each one must assert, and a sub-agent briefed from the ledger alone holds neither. Nothing in the gate is dispatched: the checklist, the driving, the pinning, the cold-shell suite run and every discharge stay with one agent, so the state of the gate is never somewhere nobody is looking.
34
36
  - **The gate needs no stronger tier than the session default** — a standard-tier session suffices whatever tier built the plan; the plan and its ledger carry all the state the gate needs, so gating in a fresh session loses nothing.
35
- - **Browser driving is the gate's final rung.** Playwright / Chrome CDP drives run once, at the end, after suites and cheap oracles are green — never interleaved mid-loop; they are the most expensive oracle in time and tokens.
37
+ - **On a rendered surface, browser driving LEADS the gate — it is not its final rung.** The order inverted deliberately: the defects that reach users through an interface are geometric and compositional, and a simulated DOM computes no layout, so a suite that is entirely green says nothing about whether anything is where it should be. **Reach the browser Chrome-CDP-first and Playwright second** — CDP drives a real browser interactively and needs no script written in advance, which is what discovery requires; Playwright is the fallback where CDP is unavailable and the tool of record for whatever must run unattended afterwards. Cheap oracles run in the same pass and are what the drive's findings get pinned into; they are no longer a gate to pass before looking. A surface with nothing rendered — a CLI, a service, a library — drives its own real binary or wire instead, and this clause does not apply.
38
+ - **A judged drive discovers; a scripted assertion guards.** Only the first finds a defect nobody has seen — a script asserting a control's value passes over a control drawn on top of its own label. Scripts are written after a judged drive names the class of defect, never generated ahead of one, and **a red script is never regenerated** — regeneration re-derives the assertion from the surface as it currently is, which turns a defect into the asserted truth with everything green.
36
39
  - **Report what happened, including failures.** A gate that reports green while a suite is red is worse than no gate; state the failing test and its output.
37
40
  - **Abandonment does not erase debt.** Before `Status: Abandoned` freezes a plan whose code was committed, convert its undischarged rows into backlog items; uncommitted code owes nothing.
38
41
 
@@ -40,13 +43,15 @@ Rules for the plan regime between the plan gate and the verification gate:
40
43
 
41
44
  Framework choice is **never** ad hoc and never the user's problem mid-task: detect the stack, use its row; if the repo already has a runner, that runner wins — **never** introduce a second framework beside it.
42
45
 
43
- | Stack | Unit / integration | Component | E2E | HTTP mocking | Don't use |
44
- | --- | --- | --- | --- | --- | --- |
45
- | Node + Vite / React (web) | `vitest` | `@testing-library/react` (+ `@testing-library/user-event`, `happy-dom`) | `@playwright/test` | `msw` | `jest`, `mocha`, `jasmine`, `cypress`, `enzyme` |
46
- | Express APIs | `vitest` | — | `supertest` against the app instance | `msw` (outbound calls) | `jest`, `chai-http` |
47
- | React Native / Expo | `jest` via the `jest-expo` preset | `@testing-library/react-native` | `maestro` | `msw` | `detox`, `enzyme` |
48
- | Cloudflare Workers | `vitest` + `@cloudflare/vitest-pool-workers` | — | `@playwright/test` against `wrangler dev` | `msw` | `jest` |
49
- | Rust | `cargo test` (built-in) | — | — | — | — |
46
+ | Stack | Unit / integration | Component | Rendered (7b) | Judged drive | E2E | HTTP mocking | Don't use |
47
+ | --- | --- | --- | --- | --- | --- | --- | --- |
48
+ | Node + Vite / React (web) | `vitest` | `@testing-library/react` (+ `@testing-library/user-event`, `happy-dom`) | `vitest` browser mode, Playwright provider | Chrome CDP, else `@playwright/test` headed | `@playwright/test` | `msw` | `jest`, `mocha`, `jasmine`, `cypress`, `enzyme` |
49
+ | Express APIs | `vitest` | — | — (nothing rendered) | the real wire — `curl`/HTTP against the running app | `supertest` against the app instance | `msw` (outbound calls) | `jest`, `chai-http` |
50
+ | React Native / Expo | `jest` via the `jest-expo` preset | `@testing-library/react-native` | `maestro` on a device/simulator | the simulator, watched | `maestro` | `msw` | `detox`, `enzyme` |
51
+ | Cloudflare Workers | `vitest` + `@cloudflare/vitest-pool-workers` | — | — (nothing rendered) | the real wire against `wrangler dev` | `@playwright/test` against `wrangler dev` | `msw` | `jest` |
52
+ | Rust | `cargo test` (built-in) | — | the app window, driven by the OS layer where one exists | the running binary, watched | — | — | — |
53
+
54
+ **The two new columns are the inversion made concrete.** *Rendered (7b)* is the unattended real-engine runner — where geometry pins live, and `—` where a stack renders nothing. *Judged drive* is what a person or an agent looks at when a change is finished, and it leads the gate on any stack that renders: Chrome CDP first because it drives a real browser with no script written in advance, Playwright headed where CDP is unavailable. A stack whose judged drive is `—` has no interface to look at, not permission to skip looking.
50
55
 
51
56
  Test packages install at `latest` — outside the approved-packages pin set. Fake data comes from `@ngneat/falso` — **never** `@faker-js/faker` / `chance`.
52
57
 
@@ -55,6 +60,7 @@ Test packages install at `latest` — outside the approved-packages pin set. Fak
55
60
  - **Suite, not scripts.** Tests live in the canonical test tree — `tests/` mirroring `src/`, or the convention the repo already uses — named `<subject>.test.ts`; shared fixtures, factories, and helpers in `tests/helpers/` (or the suite's existing shared home).
56
61
  - **Wire the canonical command.** `"test"` in `package.json` runs the whole unit suite (`vitest run`); e2e under `"test:e2e"`. A repo where `pnpm test` / `npm test` doesn't run the suite is misconfigured — fix the wiring, **never** route around it.
57
62
  - **Unit and E2E trees stay separate.** Vitest/Jest suites in `tests/`; Playwright/Maestro suites in `e2e/` with their own config — **never** mixed into the unit runner's glob.
63
+ - **The real-renderer stratum is a third tree** — `tests/rendered/` under the unit runner's *browser mode*, its own config, kept to geometry regressions that shipped and the composition assertions a component library cannot make alone. It is not a second component suite; anything a simulated DOM can prove stays in `tests/component/`.
58
64
  - **No test doubles for what you own.** Prefer real instances — in-memory SQLite for drizzle, the actual Express app via `supertest` — over mocks; mock **only** true externals (network via `msw`, time via the runner's fake timers).
59
65
  - **Determinism.** No real network, no real time, no shared mutable state between tests; every test **must** pass alone, in any order, **and from a cold shell** — never against a hand-started dev server (Workers: `@cloudflare/vitest-pool-workers`; Express: `supertest` against the app instance).
60
66
 
@@ -63,13 +63,13 @@ The packs are a floor, not a fence: report any contract that passes the ships-gr
63
63
 
64
64
  **The doc cross-check is free and you are the only one who can make it.** You already hold the touch list; resolving those paths against the ownership index and comparing the result to the plan's **Doc Obligations** rows costs one lookup. The plan's author wrote that ledger, so it is the one gate artifact nobody independently checked — a `None` that contradicts your touch list is the failure this section exists to catch. Report the gap; never edit the ledger yourself.
65
65
 
66
- **BLOCK** = any CRITICAL. HIGH findings yield **PASS WITH AMENDMENTS** — fold the amendments into the plan before coding. Order amendments sequencing-first: many violations dissolve by reordering steps (expand-then-contract, migrate-before-code) rather than changing what ships — prefer that fix, drawn from the entry's safe-change sequence.
66
+ **BLOCK** = any CRITICAL. HIGH findings yield **PASS WITH AMENDMENTS** — the invoking session folds the amendments into the plan in the same pass, before the plan is shown as finished. Order amendments sequencing-first: many violations dissolve by reordering steps (expand-then-contract, migrate-before-code) rather than changing what ships — prefer that fix, drawn from the entry's safe-change sequence.
67
67
 
68
68
  6. **Record the verdict in the plan's `Gates:` line.** Rewrite only your own segment, to exactly `Boundary: passed YYYY-MM-DD` (PASS, or PASS WITH AMENDMENTS once the amendments are folded) or `Boundary: blocked YYYY-MM-DD` (BLOCK). The compliance hook greps exactly this segment — implementation edits inside the plan's scope stay blocked while it reads `Boundary: pending` (the other gates are enforced by section presence, not segment text). A plan with no `Gates:` line predates the format; add the line rather than skipping the write-back.
69
69
 
70
70
  ## Rules
71
71
 
72
- - **Read-only, one exception.** You never edit the plan's content, the code, or any doc — the user folds your amendments into the plan. The single write you own is the plan's `Gates:` line (step 6), your segment only.
72
+ - **Read-only, one exception.** You never edit the plan's content, the code, or any doc — the invoking session folds your amendments into the plan in the same pass, then writes the segment to `passed`; a plan is not finished until it does. The single write you own is the plan's `Gates:` line (step 6), your segment only.
73
73
  - **Verify in source.** Never flag from plan text alone — read both sides of every finding and cite them: code as `file:line`, doctrine as the doc path.
74
74
  - **No other side, no violation.** An intersection with no traced consumer and no doctrine behind it isn't a violation — it's a **new edge**: report it in its own section with the hardening its mechanism prescribes (version the cache key now, make the enum append-only now), so the fragile edge is born safe.
75
75
  - **A clean report is valid.** Zero violations means say so — the coverage table is the evidence it was checked, not skipped. Don't pad findings.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: codegraph
3
+ requires-tool: codegraph
4
+ description: Query the codegraph index before reading source. An LLM-first codebase index (symbols, call references, git history, co-change coupling, ownership) answering whole questions in one call. Use it to localize, scope, and assess blast radius on this repository; use grep/read for string literals, mechanism, and data flow — the skill states which is which. Applies to any task that starts with "where is", "who calls", "what changed", "who owns", "what breaks", or "is this tested".
5
+ ---
6
+
7
+ # codegraph — the index-first method
8
+
9
+ **If the tool is absent** (`codegraph --version` fails): do not stall. Read `.claude/state/decisions.tsv` for `tool.codegraph`.
10
+
11
+ - **`declined`** — fall back to the cold method (grep, targeted reads, `git log`) **silently**. Do not mention the tool, do not re-offer. The user has answered.
12
+ - **undecided** (no file, no key, or anything unrecognised) — fall back to the cold method *and* make the offer **once**: this repository would answer "where is / who calls / what changed / who owns" from an index instead of a grep sweep; install with `npm install -g @nurix/codegraph`, then `codegraph index`. **Ask, never act** — a global npm install modifies the machine, and indexing writes to `~/.codegraph`. Record the answer with `recordDecision` either way, so the question is asked at most once per repo per machine.
13
+ - **`accepted` but the binary is gone** — treat as undecided; a failed or removed install is not a standing yes.
14
+
15
+ **A failed install is `absent`, not an error to retry.** Global installs fail on machines without permission; say so once, fall back, and move on.
16
+
17
+ **An explicit invocation overrides a stored decline.** If the user asks for this skill by name, honour it and re-offer — "stop asking" must never become "never usable".
18
+
19
+ **If the repository is not indexed** (a query answers `UNAVAILABLE: this repository has not been indexed yet`), that is the tool degrading correctly, not a failure: offer `codegraph index` under the same ask-first rule. The SessionStart probe deliberately does **not** claim index freshness — it can only see the binary — so this is where index state is actually established.
20
+
21
+ Everything below assumes the tool is present and the repository indexed.
22
+
23
+ The `codegraph` CLI is on PATH and defaults to the git root of the working directory — inside this repository, no flags are needed. The index is prebuilt; `codegraph projects` shows freshness (a `[STALE]` marker means HEAD moved since indexing — refresh with `codegraph index --commits 30000`, ~40s). Every answer states its own confidence per section (`CERTAIN` / `INFERRED` / `UNRESOLVED`), announces anything the token budget dropped, and says what an empty section means. Trust those labels.
24
+
25
+ ## The method order
26
+
27
+ Localize through the index **before** opening any file, in this order; then read only the files it points at.
28
+
29
+ 1. **`codegraph find <fragment>`** — symbols and file paths by name fragment. The entry point when you only have issue vocabulary. Symbol names only — it will never match string literals, dict keys, or SQL fragments (grep for those, without shame).
30
+ 2. **`codegraph where-defined <symbol>`** / **`codegraph outline <file>`** — pin the definition; map a big file. `outline` turns a 100+ declaration file into a navigable, line-numbered list — use it instead of reading god files blind. On a large file add `--budget 0` (see traps).
31
+ 3. **`codegraph who-calls <symbol>`** / **`codegraph impact <target>`** — callers, and blast radius (static reach + historical co-change reach, reported separately on purpose: they disagree, and the disagreement is information).
32
+ 4. **`codegraph churn --days N --path <dir>`** · **`coupling --path <file>`** · **`owners <path>`** · **`tests-covering <file>`** — the history layer: what's hot, what changes together (including *hidden coupling* — co-change with no static reference, the one fact reading code cannot reveal), who knows this area and how recently, which test file historically guards this file.
33
+ 5. **`codegraph god-objects --minSymbols 30`** / **`hotspots`** / **`overview`** — repo-scale orientation and risk.
34
+
35
+ Then read, with `sed -n` ranges at the lines the index gave you. The index does discovery; reading does diagnosis. Add `--json` when a wrapper needs structure.
36
+
37
+ There is also **`codegraph blame <file> [--line N]`** — the commits behind a file or one specific line, answered by git at query time; **`codegraph refs <name>`** — the data-reference layer: where a name is used as a dict/object key, attribute/field, import, or type annotation, with read/write direction, and a cross-language flag when the same name spans Python and TypeScript files (this answers "who reads `x_axis_sort`" / "who writes `chart.query_context`" in one call — the questions that used to need grep); and **`codegraph drift`** — near-duplicate function bodies crossed with co-change history: similar code whose files never change together is an unfinished refactor waiting to disagree. `who-calls` additionally tabulates which keyword arguments each call site passes, so "which call sites omit this option" is one query.
38
+
39
+ ## The boundary — what the index cannot answer (fall back immediately, don't retry)
40
+
41
+ - **Free-text string literals** (SQL templates, prose, format strings) — grep. Identifier-shaped keys and fields ARE indexed (`refs <name>`); anything longer or with spaces is not.
42
+ - **Framework reflection** (Marshmallow `@post_load`, signal handlers, `appbuilder.add_api(Cls)` registration) — invisible to call edges. Bare decorator *application* (`@has_access_api`) IS indexed as a reference; what the decorator does and when it runs is not.
43
+ - **Data flow and mechanism** ("does this value reach that function", "what order do these run in") — always reading work.
44
+
45
+ Indexed symbol forms include statement declarations, `const X = () => {}`, named function expressions inside wrapper calls (`typedMemo(function DataTable() {})`), TS/JS class fields, and Python class-body fields (`is_dttm = Column(...)`); nested members render as `Parent › member` in `outline`.
46
+
47
+ ## Traps (each cost a prior agent real time)
48
+
49
+ - **Bare-name collision.** Call references match by name, not resolved binding. When a name has several definitions, `who-calls` lists every candidate and says so in its subject line — read that section before trusting the call sites, and pass `--scope <path-fragment>` (also on `find`, `where-defined`, `impact`) to narrow to a package.
50
+ - **`codegraph functions` lists the CLI's own functions**, not the repository's. For repo functions use `find`. An explicit `--limit` lifts the default token budget, so a full `outline` needs no `--budget 0` incantation (an explicit `--budget` still wins).
51
+ - **Churn windows.** `churn --days 180` returning nothing does not mean quiet history — widen the window. Directory-scope churn ranks by raw commit count and buries small-but-critical files; for specific files use `owners`/`coupling` per file.
52
+ - **`tests-covering` is co-change evidence, not executed coverage** — it names the right test file to open; it cannot say the specific scenario is tested.
53
+ - **Coupling on a busy file has a noise tail** — partners at <15% shared commits are usually PR-cohabitation, not real coupling. Verify a partner with a read before adding it to a touch-list.
54
+
55
+ ## Division of truth in this repository
56
+
57
+ `docs/` is the source of truth for **intent** — what a feature is for, its invariants, decisions, vocabulary. codegraph is the source of truth for **facts** — where things are, who calls what, what changed together, who owns what. Never copy live facts (caller counts, churn numbers) into docs as if permanent; never ask the index for intent.
@@ -122,11 +122,18 @@ The two guarantees are complementary and both break on mixing: a reader holding
122
122
 
123
123
  **Frontmatter is compulsory on every document this skill authors** — `type:` (the genre) on every
124
124
  doc, plus the genre's own keys beside it; a document without its frontmatter fails the skill's
125
- contract and is not done. A feature doc carries the full ownership set — `owns:` (required),
126
- `module:` (optional), `keywords:` (required), `status:` (required), optional `last-reviewed:`. An
127
- acceptance-criteria doc (`docs/acceptance/`) carries `type:` and `status:`. The single sanctioned
128
- exception is a genre the placement map explicitly marks frontmatter-less (the behavioral checklists
129
- in `docs/tests/`). Deriving ownership frontmatter from code and keeping it accurate is [`references/frontmatter.md`](references/frontmatter.md) — every feature-doc create or update, and the `maintenance` agent's baseline pass, route there.
125
+ contract and is not done. **There is no frontmatter-less genre.** A feature or UX doc carries the
126
+ full set — `owns:` (required), `module:` (optional), `keywords:` (required), `status:` (required),
127
+ `applies:` (the architecture docs it obeys; omitted when none), optional `last-reviewed:`. A
128
+ behavioral checklist (`docs/tests/`) carries `type: checklist` and `verifies:` — the doc whose
129
+ promises it proves. An acceptance-criteria doc (`docs/acceptance/`) carries `type:` and `status:`.
130
+
131
+ **The frontmatter is where the docs tree's edges live**, and a doc that declares none is a node
132
+ nothing can reach: no change implicates it, so it rots without the rot being detectable. Deriving
133
+ every edge — `owns:` from code, `verifies:` and `applies:` from the docs they answer to — is
134
+ [`references/frontmatter.md`](references/frontmatter.md), and it carries the rule the whole graph
135
+ rests on: **declare once at the consuming end, generate every inverse.** Every doc create or
136
+ update, and the `maintenance` agent's baseline pass, route there.
130
137
 
131
138
  ---
132
139
 
@@ -1,8 +1,16 @@
1
- # Frontmatter Derivation — feature-doc ownership
1
+ # Frontmatter Derivation — the doc graph
2
2
 
3
- Load when: creating a feature doc, updating one whose documented scope moved, or running a baseline/reconcile pass over many docs.
3
+ Load when: creating a doc that declares an edge (a feature doc, a UX doc, a behavioral checklist), updating one whose scope moved, or running a baseline/reconcile pass over many docs.
4
4
 
5
- When creating or updating a feature doc, derive its **`owns:` frontmatter** — the code-path globs it is canonical for — from the source the doc describes. Code ownership lives in each feature doc's `owns:` frontmatter (the SessionStart hook unions them into the injected ownership index); there is no hand-maintained ownership map.
5
+ **A docs tree is a graph, and every edge in it is declared in frontmatter.** Two kinds of edge exist: **doc → code** (`owns:`), and **doc → doc** (`verifies:`, `applies:`). The SessionStart hook reads them all and injects the generated indexes; there is no hand-maintained map of either kind.
6
+
7
+ ## The one rule that keeps the graph honest
8
+
9
+ **An edge is declared once, at the consuming end. Every inverse is generated, never authored.**
10
+
11
+ A parent that hand-lists its children is a second thing to forget, and the moment the two directions can disagree nothing says which is right — you have doubled the staleness surface rather than halving it. So a checklist names the feature it verifies; the feature never lists its checklists. A feature names the architecture doc it obeys; the architecture doc never lists its consumers. Both inverses are derived on demand and injected, exactly as the ownership index already is.
12
+
13
+ The consuming end is also the end that **knows**. A checklist author knows what they are verifying; an architecture doc has no idea who will obey it next year.
6
14
 
7
15
  ## When to run
8
16
 
@@ -34,7 +42,21 @@ The single bounded-context label this feature belongs to, or omit it for a cross
34
42
 
35
43
  `keywords:` are the discovery terms topic→doc lookup rides. `status:` is `active`, `draft`, or `deprecated` — it steers the model toward live docs and away from draft/deprecated ones.
36
44
 
37
- A doc's dependencies on other docs are expressed inline in its prose (links); cross-cutting contracts are diagnosed by the `boundary` skill from source, not persisted.
45
+ ## The doc → doc edges
46
+
47
+ A prose link is not an edge. It states that one doc mentions another; it never states **why**, so nothing can be derived from it — not who consumes a doctrine, not what to re-read before an edit, not what falls stale when a surface moves. A tree can carry hundreds of prose links and still have no graph. These two keys carry the relationships that matter; everything else stays prose.
48
+
49
+ **`verifies:`** — on a behavioral checklist (`docs/tests/{feature}.md`), the feature or UX doc(s) whose promises it proves. One value is the norm; several when a checklist spans a capability that two docs decide. A checklist carrying no `verifies:` is an orphan by construction: nothing implicates it when its subject changes, so it rots silently and the rot is undetectable.
50
+
51
+ **`applies:`** — on a feature or UX doc, the architecture docs it obeys. Not "docs I read" and not "docs I mention" — **obligation**: a doctrine this surface is bound by, such that a change to the doctrine implicates this doc. The narrow reading is the load-bearing one; a key that collects everything consulted degrades into a bibliography and stops meaning anything. A feature bound by nothing cross-cutting omits the key.
52
+
53
+ Cross-cutting *contracts* remain diagnosed by the `boundary` skill from source, never persisted — `applies:` records which doctrine a surface answers to, not which code it touches.
54
+
55
+ ## What is not frontmatter, deliberately
56
+
57
+ **`Pinned:` stays a section-level line inside a checklist**, naming the suite tests that guard that section. It is already typed and already resolved mechanically by the `maintenance` agent. Hoisting it into frontmatter would flatten per-section detail into a doc-level list and duplicate what the sections already say — the exact double-declaration the one rule above forbids.
58
+
59
+ That edge has a property the others lack, and it is worth naming: **a `Pinned:` reference terminates.** A test file exists or it does not, so the edge is falsifiable by a resolver sweep with no judgement. An `owns:` glob is only falsifiable at the dangling end — a glob that resolves says nothing about whether the doc still describes what the code does. Terminal edges get resolver sweeps; non-terminal edges need a human or an agent to read both ends. Do not build a checker that pretends otherwise.
38
60
 
39
61
  ## Rules
40
62
 
@@ -42,3 +64,6 @@ A doc's dependencies on other docs are expressed inline in its prose (links); cr
42
64
  - Use glob patterns for directories, explicit paths for individual files. At `active`, never list paths that don't exist in the codebase; a `draft`'s projected paths are confirmed at `active`.
43
65
  - When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec owns its own globs — don't duplicate a path across siblings.
44
66
  - For baseline/reconcile with many docs, use parallel sub-agents to read source and propose `owns:` globs.
67
+ - **Never author an inverse.** No doc lists its verifiers, its consumers, or its dependents — those are generated. A hand-written "consumed by" table is a defect to delete, not a convention to follow.
68
+ - **Every edge value is a repo-relative doc path** (`docs/architecture/common/security.md`), never a bare filename and never a display title — the resolver is a path lookup, and a title changes without the file moving.
69
+ - **A dangling edge is a block, not a warning.** `verifies:` or `applies:` naming a doc that does not exist is a typo or a deletion; either way the graph is lying. Resolve at authoring time.
@@ -1,6 +1,23 @@
1
1
  # Behavioral Checklist (docs/tests/{feature}.md)
2
2
 
3
- Truth document. Use for: **how to verify one feature's promised behavior by driving the real product** — the browser, the CLI binary, HTTP against the running service. One file per feature, named for the feature doc that owns the code (`docs/features/auth.md` → `docs/tests/auth.md`). No frontmatter; a checklist owns no code.
3
+ Truth document. Use for: **how to verify one feature's promised behavior by driving the real product** — the browser, the CLI binary, HTTP against the running service. One file per feature, named for the feature doc that owns the code (`docs/features/auth.md` → `docs/tests/auth.md`).
4
+
5
+ **Frontmatter is two keys, and `verifies:` is the load-bearing one:**
6
+
7
+ ```yaml
8
+ ---
9
+ type: checklist # required tooling key — genre stamp
10
+ verifies: [docs/features/auth.md] # required — the doc(s) whose promises this proves
11
+ ---
12
+ ```
13
+
14
+ A checklist owns no code, so it carries no `owns:`. What it carries instead is the edge back to
15
+ its subject. **The filename convention is not the edge** — a same-named file is a coincidence a
16
+ resolver cannot trust, it breaks the moment a checklist spans two docs or a feature is renamed, and
17
+ it leaves nothing to implicate this file when its subject changes. Without `verifies:` a checklist
18
+ is unreachable: no change reaches it, so it goes stale and the staleness is undetectable. Several
19
+ values are correct where one checklist proves promises two docs decide; the inverse — which
20
+ checklists cover a feature — is generated, never listed in the feature doc.
4
21
 
5
22
  **This is the driving script, and it is the source the suite is drawn from.** At the verification gate it does double duty: rung 1 drives the real surface *against these steps*, and rung 2 pins the durable subset *of these assertions* as suite tests. Writing it is therefore not a report written afterwards — it is authored or updated **before** the driving, so the gate has something to execute and the tests have something to be derived from. Which assertions earn a permanent test is decided by the `testing` skill (gate mode) § What earns a suite test, and each section records the answer on its `Pinned:` line.
6
23
 
@@ -12,6 +12,7 @@ owns: ["src/feature/**", "src/other/file.ts"] # required — code-path globs t
12
12
  module: billing # optional — single bounded-context label; omit if cross-cutting
13
13
  keywords: [invoice, pdf] # required — discovery terms
14
14
  status: active # required — active | draft | deprecated
15
+ applies: [docs/architecture/common/security.md] # optional — architecture docs this surface is BOUND by (obligation, not a bibliography); omit when none
15
16
  last-reviewed: YYYY-MM-DD # optional tooling key — stamped on substantive review/update; the maintenance agent ranks audit priority by it (metadata, never narrated in the body)
16
17
  type: feature # required tooling key — genre stamp (generator-written or authored; enum = the template names), read by tooling (UI grouping, protected-file mapping); preserve on edits, never narrate
17
18
  ---
@@ -1,9 +1,11 @@
1
1
  # Plan (docs/history/plans/YYYY-MM-DD-feature-name.md)
2
2
 
3
- Record. Use for: every implementation plan. Plans are created here directly with `Status: Draft`; after approval the plan gates (`boundary`, then `testing` plan-gate mode) run against the still-`Draft` file, the status flips to `Status: In Progress` at the first implementation step, and the file freezes at `Status: Complete` or `Status: Abandoned`. Once frozen, never edit — write a new dated plan if scope changes. The plan records the journey; the truth it implemented lives on in the feature doc and any AD it touched.
3
+ Record. Use for: every implementation plan. Plans are created here directly with `Status: Draft`; the plan gates (`boundary`, then `testing` plan-gate mode) run in the same pass that writes the plan, against the still-`Draft` file — a plan is not finished, and is not shown as finished, until its `Gates:` line carries every verdict, so what the user approves is the gated plan. The status flips to `Status: In Progress` at the first implementation step, and the file freezes at `Status: Complete` or `Status: Abandoned`. Once frozen, never edit — write a new dated plan if scope changes. The plan records the journey; the truth it implemented lives on in the feature doc and any AD it touched.
4
4
 
5
5
  The `boundary` skill parses the **Proposed Changes** sections to check boundary impact before execution, and the `testing` skill (plan-gate mode) writes a **Test Obligations** section into the plan at the same gate. Keep that structure stable — section headings and bullet shape are load-bearing for the parsers, and the Test Obligations table is the ledger the verification gate discharges before the plan may reach `Status: Complete`.
6
6
 
7
+ **Both ledgers are read by a wall, so their cells obey a table's grammar.** A literal pipe inside a cell is written `\|` — the parser splits on unescaped pipes and unescapes what survives, so an escaped one is safe, and an unescaped one silently adds a column and shifts every later cell left. Prefer rephrasing (`` `install` or `update` ``) over escaping where the sentence allows it: the cell then reads the same to a person and to the wall.
8
+
7
9
  **Doc Obligations is the one ledger the plan's author writes.** Deriving tests from behavior is judgment, which is why `testing` owns that section and it is marked never-hand-author; resolving Proposed Changes' file paths to the feature docs that own them is a **lookup** against the ownership index already injected at session start. Different work, different rule — fill it yourself, while the touch list is fresh.
8
10
 
9
11
  The **`Gates:`** line carries one machine-read segment. The compliance hook greps **`Boundary:`** — implementation edits inside the plan's scope are blocked while it reads `Boundary: pending`; the `boundary` skill rewrites it to `Boundary: passed YYYY-MM-DD` or `Boundary: blocked YYYY-MM-DD`. The other two gates are enforced by **section presence**: a plan with no `## Test Obligations` or no `## Doc Obligations` section blocks the same edits — the sections are the artifacts, and the gate derives from them, not from a claim about them. Never hand-edit the line to skip a gate.
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Truth document.** States what a person sees and can do on a surface, and what the surface promises never to do. Present tense, like every truth document.
4
4
 
5
- **`type: ux`.**
5
+ **`type: ux`**, plus `applies:` — the architecture docs this surface is bound by (the state vocabulary, the routing doctrine, the information architecture it answers to). Same key and same narrow reading as a feature doc's: obligation, not a reading list.
6
6
 
7
7
  **Why this genre exists.** A feature doc (LLD) states what a feature is, how its data flows, and which contracts it honours — all of which stay plausibly true through a rewrite of the surface. Nothing else in the repo states what a person *observes*. So a change to the wire lands, the interface absorbs it, and the absorption reads as maintenance: no test fails, no lint fires, no document is contradicted. This document is the thing a silent change contradicts.
8
8
 
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: issue-bridge
3
+ description: The bridge between a traditional issue tracker (GitHub Issues, Jira, Linear, …) and the AI-first SDLC. Two modes — **triage** (inbound — a tracker item is routed through the ownership index to its owning feature docs, localized with codegraph, and lands as a confidence-graded triage dossier ready for a fix plan) and **file** (outbound — a verified harness finding becomes a tracker-native issue with checkable evidence, and the created ID is written back into the originating row). Tracker access goes through a connector (see the per-tracker packs under references/trackers/); tracker writes are always approval-gated per run. Use on "triage issue #N / PROJ-123 / ENG-123", "triage the new issues", "file this finding as a ticket", "/issue-bridge".
4
+ ---
5
+
6
+ # issue-bridge — the tracker bridge method
7
+
8
+ **If no connector is reachable** (no MCP server, no CLI, no API credentials — the pack for your tracker lists the probes): do not stall — accept pasted issue text, name the fields you are missing (labels, comments, linked items), and run triage on what you have. Degraded output is acceptable; silent degradation is not.
9
+
10
+ You bridge two systems of record. Neither is asked to change:
11
+
12
+ - **The tracker owns** intake, priority, assignment, status, discussion. You never relocate those.
13
+ - **The AI layer owns** intent (feature docs say *why* — invariants, vocabulary, scope), location (the ownership index and codegraph say *what and where*), and history (git-derived).
14
+ - **The bridge rule: inbound enrich, outbound evidence.** An inbound item gains location, owning docs, and blast radius. An outbound item carries citations a human can verify without trusting you.
15
+
16
+ ## Connectors
17
+
18
+ Tracker access is **this skill's own knowledge**, not a harness-declared tool. It was briefly modelled as a "connector" sub-kind of the tools class; that was wrong, and the probes are the proof — the tools class means one deterministic, versioned executable, while a tracker is an MCP entry *or* one of several unrelated CLIs *or* an env var, varying per repo and per team. So the access method lives in `references/trackers/<tracker>.md`, probed in preference order at the moment of use. It is **credentialed and side-effectful**, which is why every tracker write is approval-gated. Each tracker's pack under [`references/trackers/`](references/trackers/) lists its access options in preference order (MCP server → CLI → raw API), the probe for each, auth setup, and the exact calls for read / search / create / comment. Read the pack for your tracker before the first tracker call. More than one tracker in play → one pack each; the method below is identical across all of them.
19
+
20
+ ## Tool tier
21
+
22
+ Read the codegraph status from the session context (`Tool:` line). **Present-fresh** → localize every question through the index (`find`, `where-defined`, `who-calls`, `refs`, `impact`, `blame`, `tests-covering`) before reading source. **Present-stale** → use it, note the gap. **Absent** → Glob/Grep/read, announced. Never run `codegraph index` unless you verify HEAD moved. One carve-out: **syntax-level detail — decorator lists and their order, full function bodies, statement sequence — is not in the index's query surface**; go straight to source for that class, whatever the tier. (The 0.2.0 decorator mis-attribution defect is fixed in 0.2.1 — `who-calls` and `impact` now attribute decorator references to the decorated declaration; the catalog pins `min-version: 0.2.1` accordingly.)
23
+
24
+ ## Mode selection
25
+
26
+ **Triage** when given issue references, a tracker query, or pasted issue text. **File** when given a harness finding to externalize — a backlog row, a drift or bookkeeping finding, an audit or critic result, a changelog discovery. Ambiguous → ask one question, don't guess.
27
+
28
+ ## Triage — tracker item in, dossier out
29
+
30
+ 1. **Fetch** through the connector (per the pack). No access → pasted-text mode, missing fields named.
31
+ 2. **Classify.** Bug / feature request / question / docs-gap. Questions get owning-doc pointers and a direct answer, not a dossier.
32
+ 3. **Route.** Match the issue's vocabulary against the ownership index and feature docs' `keywords:`. Read the owning doc(s) **fully** — intent and invariants first, code second. No owning doc → say so; the absence is itself a finding.
33
+ 4. **Localize.** Names from the issue go through codegraph; every location claim carries `file:line`.
34
+ 5. **Diagnose.** Root-cause hypothesis, confidence-graded — `certain` / `inferred` / `unresolved` — and never present inferred as certain. Blast radius via `impact`/`coupling`; test surface via `tests-covering`.
35
+ 6. **Dedup.** Search the tracker for siblings and priors (per the pack); check codegraph `drift` for the same-bug-in-a-clone class.
36
+ 7. **Write the dossier** to `docs/operations/triage/YYYY-MM-DD-<tracker>-<id>-<slug>.md` and return the verdict summary.
37
+ 8. **Posting back** (comment, label, assign, transition) is **approval-gated per run**: show exactly what would be posted, post only on an explicit yes in this session. A standing repo ruling (e.g. "never post to this upstream") overrides any approval.
38
+
39
+ ## The dossier
40
+
41
+ Frontmatter: `tracker`, `issue` (id + URL), `date`, `confidence`, `type: triage`. Sections, in order: **Verdict** (1–3 sentences) · Classification · Owning docs (paths) · Root cause (cited, graded) · Blast radius · Suggested fix plan (feeds the plan → PR loop; you never implement) · Test surface · Duplicates & related · **Prior-thread corrections** (claims already on the tracker thread — bot answers, maintainer comments — that your evidence shows to be wrong, each with the citation that refutes it) · Open questions. A dossier is a dated working artifact — it never claims `owns:` globs and never masquerades as a feature doc.
42
+
43
+ ## File — harness finding in, tracker issue out
44
+
45
+ 1. **Verify first.** Reproduce the finding against source before externalizing it. A claim that doesn't reproduce is reported back, never filed.
46
+ 2. **Compose tracker-idiomatic** (per the pack): imperative title; body: one plain-language context paragraph (no harness jargon), evidence (`file:line`, commit hashes), expected vs actual, acceptance criteria; link the owning feature doc by path.
47
+ 3. **Show the draft(s).** Create only on explicit approval, through the connector. Batch discipline: many findings → one draft list, one approval, then individual creation; report every created ID.
48
+ 4. **Close the loop.** Write the created issue's ID/URL back into the originating row — a backlog row gains the link, a bookkeeping row resolves.
49
+
50
+ ## Boundaries
51
+
52
+ - Never edit source code. The dossier ends at the fix *plan*; implementation belongs to the plan → verification → PR loop.
53
+ - Nothing is created, edited, or commented in the tracker without explicit approval in the current run.
54
+ - Repo writes are `docs/operations/triage/**` plus the loop-closing edits to `docs/history/backlog.md` / `docs/operations/bookkeeping.md`. Nothing else.
55
+ - Announce degraded modes; never silently downgrade evidence quality.
@@ -0,0 +1,37 @@
1
+ # GitHub — connector pack
2
+
3
+ Access options in preference order. Probe each in order; use the first that answers. Research of record: `discussions/code-analysis-tools/research-tracker-connectors/01-github.md` (2026-08-19).
4
+
5
+ ## Option 1 — the `gh` CLI (default)
6
+
7
+ Probe: `gh auth status` (exit 0 = authenticated; `gh --version` alone only proves the binary).
8
+ Setup if absent: `gh auth login` (browser flow) or `gh auth login --with-token` with a PAT (scopes: repo, read:org). CI: `GH_TOKEN` env.
9
+
10
+ - Read: `gh issue view <n|url> --comments --json title,body,labels,comments,state,url,author,assignees,milestone`
11
+ - Sweep: `gh issue list --search '<query>' --state all --json number,title,labels`
12
+ - Dedup: `gh search issues '<key phrases>' --repo OWNER/REPO`
13
+ - Create (approval-gated): `gh issue create --title <t> --body-file <f> --label <l>`
14
+ - Comment (approval-gated): `gh issue comment <n> --body-file <f>`
15
+ - Another repo: add `-R OWNER/REPO` to any of these.
16
+
17
+ ## Option 2 — the official GitHub MCP server
18
+
19
+ `github/github-mcp-server` (GitHub-official, 32k★). Probe: a `github` entry in `.mcp.json` / MCP tools visible in-session.
20
+ Setup: `claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header "Authorization: Bearer <PAT>"` (hosted), or local Docker `ghcr.io/github/github-mcp-server` with OAuth.
21
+ Tool names (issues toolset, loaded by default): `issue_read` (get/get_comments/get_sub_issues/get_labels) · `list_issues` · `search_issues` · `issue_write` (create/update — the write gate applies) · `add_issue_comment` · labels via the `labels` toolset (`GITHUB_TOOLSETS` env to add).
22
+
23
+ ## Option 3 — raw API fallback
24
+
25
+ Headers: `Authorization: Bearer <PAT>` · `Accept: application/vnd.github+json`.
26
+ - Read: `GET https://api.github.com/repos/OWNER/REPO/issues/N`
27
+ - Search: `GET https://api.github.com/search/issues?q=<query>` (q ≤256 chars, ≤5 boolean ops, ~10 req/min)
28
+ - Create: `POST /repos/OWNER/REPO/issues` `{"title","body","labels":[]}` · Comment: `POST .../issues/N/comments` `{"body"}`
29
+ - Labels: POST appends, PUT replaces — never PUT unless replacement is the stated intent.
30
+
31
+ ## Composing for GitHub
32
+
33
+ Markdown body, native. Reference related issues/PRs by bare `#number` so GitHub auto-links. Labels from the owning doc's `module:` where the repo's label taxonomy allows — **read `gh label list` first; never invent labels** (real taxonomies differ: apache/superset uses `#bug:*`, not `bug`).
34
+
35
+ ## Ecosystem notes (2026-08-19)
36
+
37
+ No incumbent GitHub-issues skill/plugin exists in anthropics/skills, the official plugin marketplace, or awesome-claude-code — this pack has no upstream to defer to. The reverse direction exists as `anthropics/claude-code-action` (@claude mentions inside issues trigger CI sessions); do not confuse the two.
@@ -0,0 +1,40 @@
1
+ # Jira — connector pack
2
+
3
+ Access options in preference order. Probe each in order; use the first that answers. Research of record: `discussions/code-analysis-tools/research-tracker-connectors/02-jira.md` (2026-08-19).
4
+
5
+ ## Option 1 — the official Atlassian Remote MCP Server (Cloud only)
6
+
7
+ Probe: an `atlassian` entry in `.mcp.json` / Atlassian MCP tools visible in-session.
8
+ Setup: `claude mcp add --transport http atlassian https://mcp.atlassian.com/v1/mcp/authv2`, then `/mcp` in-session for the OAuth 2.1 flow. **Cloud only — no Data Center.** Rate limits: 500–1,000 calls/hr by plan.
9
+ **Tool names are unpublished by Atlassian** — introspect the live tool list from your session (ToolSearch / the MCP tool listing) before planning calls; expect find/create/update/comment/transition capabilities per Atlassian's own examples.
10
+
11
+ ## Option 2 — community MCP: `sooperset/mcp-atlassian` (Cloud + Server/DC)
12
+
13
+ The maintained community standard (5.8k★, MIT). Probe: an `mcp-atlassian` entry in `.mcp.json`.
14
+ Setup: `uvx mcp-atlassian` with env `JIRA_URL`, `JIRA_USERNAME`, `JIRA_API_TOKEN` (Cloud; token from id.atlassian.com) or `JIRA_PERSONAL_TOKEN` (Server/DC v8.14+).
15
+ Confirmed tool names: `jira_get_issue` · `jira_search` (JQL) · `jira_create_issue` · `jira_add_comment` · `jira_transition_issue` · `jira_update_issue` · `jira_get_transitions` · `jira_batch_create_issues`.
16
+
17
+ ## Option 3 — CLIs
18
+
19
+ **acli** (Atlassian-official). Probe: `acli --version` + an authenticated site. **Namespace is `workitem`, not `issue`.**
20
+ `acli jira workitem view KEY-1 --json` · `workitem search --jql "..." --json [--paginate]` · `workitem create --summary --project --type` · `workitem comment create --key KEY-1 --body "..."`.
21
+
22
+ **jira-cli** (ankitpokhrel, 5.9k★, MIT). Probe: `jira me`. Setup: `jira init` (Cloud: email + `JIRA_API_TOKEN`; DC: PAT + `JIRA_AUTH_TYPE=bearer`).
23
+ `jira issue view ISSUE-1 --comments 5` · `jira issue list -q "<JQL>"` · `jira issue create -tBug -s"..." -b"..." --no-input` · `jira issue comment add ISSUE-1 "..."`.
24
+
25
+ ## Option 4 — REST fallback (Cloud v3, v2 for plain text)
26
+
27
+ Basic auth `email:API_token`. Base `https://<domain>.atlassian.net/rest/api/3/`.
28
+ - Read: `GET /rest/api/3/issue/{KEY}`
29
+ - **JQL search: `GET /rest/api/3/search/jql`** — the old `/rest/api/3/search` is deprecated and being removed; do not use it.
30
+ - Create: `POST /rest/api/3/issue` — **`description` must be ADF** (`{"type":"doc","version":1,"content":[…]}`).
31
+ - Comment: `POST /rest/api/3/issue/{KEY}/comment` — body must be ADF.
32
+ - **ADF inconvenient → v2**: `/rest/api/2/issue` + `/rest/api/2/issue/{KEY}/comment` take plain-string bodies; v2 JQL endpoint is `/rest/api/2/search`.
33
+
34
+ ## Composing for Jira
35
+
36
+ Map to the project's real issue types (`Bug`/`Story`/`Task` — list them, don't assume). Set `components` from the owning doc's `module:` where components exist. Atlassian renamed "issue" → "work item" in UI/acli — expect both vocabularies. Leave estimates, sprints, and epic links to humans unless instructed.
37
+
38
+ ## Ecosystem notes (2026-08-19)
39
+
40
+ No official Anthropic Jira skill. Community skills exist at small adoption (JIRA-Assistant-Skills 42★, two atlassian-skills repos, an acli wrapper) — nothing to defer to; this pack is self-sufficient.
@@ -0,0 +1,37 @@
1
+ # Linear — connector pack
2
+
3
+ Access options in preference order. Probe each in order; use the first that answers. Research of record: `discussions/code-analysis-tools/research-tracker-connectors/03-linear.md` (2026-08-19).
4
+
5
+ ## Option 1 — the official Linear MCP server
6
+
7
+ Probe: a `linear`/`linear-server` entry in `.mcp.json` / Linear MCP tools visible in-session.
8
+ Setup: `claude mcp add --transport http linear-server https://mcp.linear.app/mcp`, then `/mcp` for OAuth 2.1. A **read-only endpoint exists**: `https://mcp.linear.app/mcp/readonly` — prefer it for triage-only sessions. Direct bearer also works (`Authorization: Bearer <token>` — OAuth token or a Linear personal API key; a Read-only API key gives enforced read-only).
9
+ **Tool names are unpublished by Linear** — introspect the live tool list before planning calls; expect find/create/update tools over issues, projects, comments.
10
+
11
+ ## Option 2 — community MCP servers
12
+
13
+ `tacticlaunch/mcp-linear` (146★, MIT — the exhaustive option, 150+ `linear_*` tools, TOOLS.md published) or `prime-radiant-inc/streamlinear` (89★, MIT — the token-efficient option: one dispatch tool `action: search|get|update|comment|create|graphql|help`, ~500 schema tokens; auth `LINEAR_API_TOKEN`).
14
+
15
+ ## Option 3 — CLI
16
+
17
+ `@schpet/linear-cli` (binary `linear`, 911★, actively maintained; Linear's own npm CLIs are abandoned — do not use `@linear/cli`). Probe: `linear --version`. Install: `brew install schpet/tap/linear`. Branch-aware issue detection, list/start/create, PR text generation.
18
+
19
+ ## Option 4 — GraphQL fallback
20
+
21
+ Endpoint `https://api.linear.app/graphql`. **Auth header for a personal API key is `Authorization: <API_KEY>` — no `Bearer` prefix** (Bearer is only for OAuth tokens). Introspection-verified surface:
22
+ - Read: `{ issue(id: "ENG-123") { id title description state { name } labels { nodes { name } } comments { nodes { body } } } }`
23
+ - Search: `{ issues(first: 25, filter: {title: {contains: "…"}}) { edges { node { id identifier title } } pageInfo { hasNextPage endCursor } } }` (Relay cursors; also `issueSearch`/`searchIssues`)
24
+ - Create (approval-gated): `mutation { issueCreate(input: {title: "…", teamId: "<uuid>", description: "…", labelIds: […]}) { success issue { id identifier url } } }`
25
+ - Comment (approval-gated): `mutation { commentCreate(input: {issueId: "<uuid>", body: "…"}) { success comment { id } } }`
26
+ Rate limits: API key 2,500 req/hr + complexity budget (single request cap 10,000 points — keep `first:` small on nested connections); watch `X-RateLimit-*`/`X-Complexity` headers.
27
+
28
+ ## Composing for Linear — including Linear's own agent rules
29
+
30
+ Linear publishes **Agent Interaction Guidelines** (linear.app/developers/aig); this pack adopts the two that bind writers even outside formal Agent Sessions:
31
+ - **You are a `delegate`, never an `assignee`** — humans keep ownership of issues you touch.
32
+ - **Never move work to a terminal state** — done/canceled transitions belong to humans (the same rule the linear-use community plugin hard-codes). Starting work maps to the team's lowest-position "started" state, and only when instructed.
33
+ Body is native markdown. Pick team and project explicitly — never guess a team. Priority conservatively (default: none). Cycles and estimates stay human.
34
+
35
+ ## Ecosystem notes (2026-08-19)
36
+
37
+ The strongest community skill (`wrsmith108/linear-claude-skill`, 121★) itself recommends the official MCP server — aligned with this pack's ordering. No official Anthropic Linear skill exists.