the-grimoire-cli 0.3.2
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.
- package/.agents/AGENTS.md +112 -0
- package/.agents/NAVIGATOR.md +168 -0
- package/.agents/VERSION +4 -0
- package/.agents/agents/INDEX.md +7 -0
- package/.agents/agents/verifier.md +50 -0
- package/.agents/commands/INDEX.md +11 -0
- package/.agents/commands/checkpoint.md +15 -0
- package/.agents/commands/grimoire.md +14 -0
- package/.agents/commands/onboard.md +56 -0
- package/.agents/commands/present.md +23 -0
- package/.agents/commands/verify.md +20 -0
- package/.agents/grimoire.manifest +18 -0
- package/.agents/rules/00-always.md +42 -0
- package/.agents/rules/05-code-quality.md +28 -0
- package/.agents/rules/10-working-process.md +31 -0
- package/.agents/rules/15-skills.md +27 -0
- package/.agents/rules/20-modes.md +41 -0
- package/.agents/rules/25-surgical-changes.md +29 -0
- package/.agents/rules/30-verification.md +36 -0
- package/.agents/rules/35-context-economy.md +41 -0
- package/.agents/rules/40-handoff.md +25 -0
- package/.agents/rules/45-presentation.md +35 -0
- package/.agents/rules/50-security.md +30 -0
- package/.agents/rules/60-commit-style.md +14 -0
- package/.agents/rules/INDEX.md +18 -0
- package/.agents/skills/INDEX.md +8 -0
- package/.agents/skills/README.md +6 -0
- package/.agents/skills/catalog.md +106 -0
- package/.agents/skills/find-skills/SKILL.md +142 -0
- package/.agents/stack/INDEX.md +9 -0
- package/.agents/stack/README.md +66 -0
- package/.agents/stack/desktop.md +36 -0
- package/.agents/stack/library.md +16 -0
- package/.agents/stack/web-app.md +32 -0
- package/.agents/standards/INDEX.md +23 -0
- package/.agents/standards/accessibility.md +50 -0
- package/.agents/standards/architecture.md +39 -0
- package/.agents/standards/attribution.md +39 -0
- package/.agents/standards/clean-code.md +121 -0
- package/.agents/standards/codex.md +69 -0
- package/.agents/standards/error-codes.md +41 -0
- package/.agents/standards/general.md +46 -0
- package/.agents/standards/guardrail-tests.md +40 -0
- package/.agents/standards/knowledge-management.md +35 -0
- package/.agents/standards/launch-security-checklist.md +45 -0
- package/.agents/standards/observability.md +35 -0
- package/.agents/standards/release-versioning.md +53 -0
- package/.agents/standards/requirements.md +75 -0
- package/.agents/standards/security-scanners.md +42 -0
- package/.agents/standards/testing-strategy.md +61 -0
- package/.agents/standards/typescript.md +19 -0
- package/.agents/standards/writing.md +58 -0
- package/.agents/tooling.json +19 -0
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/bin/grimoire.mjs +598 -0
- package/package.json +32 -0
- package/templates/CLAUDE.md +7 -0
- package/templates/ci/ci.yml +49 -0
- package/templates/ci/sast.yml +44 -0
- package/templates/codex/INDEX.md +18 -0
- package/templates/codex/README.md +28 -0
- package/templates/codex/decisions/0000-template.md +36 -0
- package/templates/codex/decisions/INDEX.md +11 -0
- package/templates/codex/decisions/README.md +25 -0
- package/templates/codex/domain/INDEX.md +14 -0
- package/templates/codex/domain/README.md +10 -0
- package/templates/codex/evidence/0000-extraction-template.md +36 -0
- package/templates/codex/evidence/INDEX.md +11 -0
- package/templates/codex/evidence/README.md +15 -0
- package/templates/codex/reference/INDEX.md +11 -0
- package/templates/codex/reference/README.md +15 -0
- package/templates/codex/reference/confirmed-values.md +18 -0
- package/templates/codex/requirements/INDEX.md +11 -0
- package/templates/codex/requirements/README.md +22 -0
- package/templates/codex/requirements/addons/0000-template.md +35 -0
- package/templates/codex/requirements/base.md +36 -0
- package/templates/codex/requirements/changes/0000-template.md +39 -0
- package/templates/codex/resources/INDEX.md +11 -0
- package/templates/codex/resources/README.md +17 -0
- package/templates/codex/resources/manifest.md +11 -0
- package/templates/codex/runbooks/INDEX.md +9 -0
- package/templates/codex/runbooks/README.md +8 -0
- package/templates/codex/runbooks/incident-runbook-template.md +58 -0
- package/templates/gitignore-snippet.txt +12 -0
- package/templates/journal/backlog/README.md +18 -0
- package/templates/journal/backlog/done/.gitkeep +0 -0
- package/templates/journal/memory/MEMORY.md +15 -0
- package/templates/journal/session/.gitkeep +0 -0
- package/templates/journal/session/archive/.gitkeep +1 -0
- package/templates/journal/session/artifacts/.gitkeep +1 -0
- package/templates/journal/session/current.md +12 -0
- package/templates/lint/README.md +25 -0
- package/templates/lint/eslint.config.mjs +33 -0
- package/templates/lint/tsconfig.base.json +11 -0
- package/templates/local/AGENTS.local.md +33 -0
- package/templates/local/README.md +55 -0
- package/templates/local/commands/.gitkeep +0 -0
- package/templates/local/rules/.gitkeep +0 -0
- package/templates/local/skills/.gitkeep +0 -0
- package/templates/local/stack/.gitkeep +0 -0
- package/templates/local/standards/.gitkeep +0 -0
- package/templates/tests/guardrail.invariants.test.ts +59 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# QUEUE — backlog
|
|
2
|
+
|
|
3
|
+
One work item per file: `backlog/<id>.md`. Frontmatter:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
---
|
|
7
|
+
id: <kebab-id>
|
|
8
|
+
status: open # open | active | blocked | done
|
|
9
|
+
priority: normal # normal | hotfix
|
|
10
|
+
---
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- **Hotfix is a priority flag, not a separate tree.** A hotfix item carries a cleanup checklist
|
|
14
|
+
(tests to backfill, env flag to remove, ADR if implied).
|
|
15
|
+
- Done → move the file to `backlog/done/` with close-out evidence (ADR link, test reproducer,
|
|
16
|
+
sign-off) inside it.
|
|
17
|
+
|
|
18
|
+
Routing (chat → item) is defined in `rules/40-handoff.md`.
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# KNOWLEDGE index
|
|
2
|
+
|
|
3
|
+
One fact per file in `memory/`. Each file has frontmatter (`name` / `description` /
|
|
4
|
+
`type: lesson | field-report | decision-note | reference`) and links to related cards with
|
|
5
|
+
`[[name]]`. This index holds one line per memory — never the content itself.
|
|
6
|
+
|
|
7
|
+
Architecture-level decisions graduate to `codex/decisions/`.
|
|
8
|
+
|
|
9
|
+
## Promotion & pruning
|
|
10
|
+
|
|
11
|
+
Promote a fact into `memory/` only if **all three** hold: non-obvious, project-specific, and worth
|
|
12
|
+
keeping past this week. Session scratch stays in `session/` (gitignored). Prune periodically: drop
|
|
13
|
+
cards whose underlying state has shifted or that a written ADR now supersedes.
|
|
14
|
+
|
|
15
|
+
<!-- - [Title](file.md) — one-line hook -->
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# NOW — current session (template)
|
|
2
|
+
|
|
3
|
+
> Rewrite this file **in place** every turn. Do not append. Local/gitignored — about *this run* only.
|
|
4
|
+
> Before a context boundary, copy to `session/archive/<YYYY-MM-DD-HHmm>.md` (or run `/checkpoint`).
|
|
5
|
+
|
|
6
|
+
- **mode:** NORMAL <!-- NORMAL | HOTFIX -->
|
|
7
|
+
- **focus:** <!-- the one thing in flight -->
|
|
8
|
+
- **last-done:**
|
|
9
|
+
- **next-step:**
|
|
10
|
+
- **blockers:**
|
|
11
|
+
- **open-questions:**
|
|
12
|
+
- **files-touched:**
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Clean-code lint preset
|
|
2
|
+
|
|
3
|
+
Mechanical enforcement of `standards/clean-code.md`. **Copy into your project** and extend — do not
|
|
4
|
+
edit in place (the project owns its lint config).
|
|
5
|
+
|
|
6
|
+
## Use
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm i -D eslint @eslint/js typescript-eslint
|
|
10
|
+
cp templates/lint/eslint.config.mjs ./eslint.config.mjs
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Extend the tsconfig from your `tsconfig.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{ "extends": "./tsconfig.base.json" }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Severities
|
|
20
|
+
|
|
21
|
+
`warn` for size/complexity limits (guidance while a codebase stabilizes); `error` for safety rules
|
|
22
|
+
(`any`, floating promises, non-null assertions, console). Tighten `warn`→`error` per project once
|
|
23
|
+
clean. Any rule can be overridden in your own config block — it wins.
|
|
24
|
+
|
|
25
|
+
`tsconfig.base.json` is intentionally comment-free so tooling can parse it as plain JSON.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Grimoire clean-code ESLint preset (flat config). Copy to your project root as eslint.config.mjs
|
|
2
|
+
// (or import + extend it). Install peers: `npm i -D eslint @eslint/js typescript-eslint`.
|
|
3
|
+
// Encodes standards/clean-code.md limits. Override any rule in your own config block — yours wins.
|
|
4
|
+
import js from "@eslint/js";
|
|
5
|
+
import tseslint from "typescript-eslint";
|
|
6
|
+
|
|
7
|
+
export default tseslint.config(
|
|
8
|
+
js.configs.recommended,
|
|
9
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
10
|
+
{
|
|
11
|
+
languageOptions: {
|
|
12
|
+
parserOptions: { projectService: true },
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
// --- complexity / size limits (warn: guide, do not block early) ---
|
|
16
|
+
complexity: ["warn", 10],
|
|
17
|
+
"max-depth": ["warn", 3],
|
|
18
|
+
"max-params": ["warn", 4],
|
|
19
|
+
"max-lines-per-function": ["warn", { max: 50, skipBlankLines: true, skipComments: true }],
|
|
20
|
+
"max-lines": ["warn", { max: 300, skipBlankLines: true, skipComments: true }],
|
|
21
|
+
"no-nested-ternary": "warn",
|
|
22
|
+
|
|
23
|
+
// --- safety (error: never ship) ---
|
|
24
|
+
"no-console": ["error", { allow: ["warn", "error"] }],
|
|
25
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
26
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
27
|
+
"@typescript-eslint/no-floating-promises": "error",
|
|
28
|
+
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
|
29
|
+
"@typescript-eslint/explicit-module-boundary-types": "error",
|
|
30
|
+
"@typescript-eslint/prefer-readonly": "error",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"strict": true,
|
|
4
|
+
"noUncheckedIndexedAccess": true,
|
|
5
|
+
"exactOptionalPropertyTypes": true,
|
|
6
|
+
"noImplicitOverride": true,
|
|
7
|
+
"noFallthroughCasesInSwitch": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"verbatimModuleSyntax": true
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Local overrides — this project (loads LAST, wins)
|
|
2
|
+
|
|
3
|
+
`grimoire sync` never touches anything under `local/`. See `local/README.md` for the full protocol.
|
|
4
|
+
**Do not edit the managed base** (`.agents/rules|standards|stack|agents|skills|commands`,
|
|
5
|
+
`AGENTS.md`, `tooling.json`) — put every change here.
|
|
6
|
+
|
|
7
|
+
## Project profile
|
|
8
|
+
|
|
9
|
+
- **Active stack profile:** <!-- web-app | desktop | library -->
|
|
10
|
+
- **Testing policy:** <!-- tdd-mandatory | test-ready-deferred | none -->
|
|
11
|
+
- **Verify command (if non-default):**
|
|
12
|
+
- **Presentation mode:** off <!-- off | on — render human-facing deliverables as HTML (rules/45-presentation.md) -->
|
|
13
|
+
|
|
14
|
+
## Project facts
|
|
15
|
+
|
|
16
|
+
<!-- This section is the new home for everything that used to live in a long CLAUDE.md: the system
|
|
17
|
+
model, doc map, domain glossary pointers, access/auth model, environment/build gotchas, confirmed
|
|
18
|
+
values, error-code catalog location, IPC/channel tables. CLAUDE.md becomes a thin pointer; the
|
|
19
|
+
durable project context moves HERE (it loads last and wins, and `grimoire sync` never touches it).
|
|
20
|
+
Large domain contracts (IPC tables, confirmed-value sheets) belong in `local/reference/`.
|
|
21
|
+
Onboarding an existing repo? See commands/onboard.md and move the old CLAUDE.md body into here. -->
|
|
22
|
+
|
|
23
|
+
## Override declarations
|
|
24
|
+
|
|
25
|
+
<!-- List any base rule/standard/stack default you are overriding, and where the override lives.
|
|
26
|
+
e.g. "rules/10 plan-before-code relaxed for spikes — see local/rules/local-10-spikes.md"
|
|
27
|
+
e.g. "ADRs live in docs/core/adr/ + docs/adr-index.md, not the seeded docs/adr/" -->
|
|
28
|
+
|
|
29
|
+
## Added (project-only)
|
|
30
|
+
|
|
31
|
+
<!-- Point to project-only rules/skills/commands you added under local/<area>/.
|
|
32
|
+
Project rules go in local/rules/ with a `local-` prefix (see local/README.md → naming).
|
|
33
|
+
Big domain reference docs go in local/reference/. -->
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# local/ — your project's customization layer
|
|
2
|
+
|
|
3
|
+
Everything under `local/` (at the repo root) belongs to **this project**. `grimoire sync` **never touches it**.
|
|
4
|
+
This is where ALL per-repo customization lives.
|
|
5
|
+
|
|
6
|
+
## The one hard rule
|
|
7
|
+
|
|
8
|
+
**Never edit the managed base in a consuming project.** These paths are overwritten on every
|
|
9
|
+
`grimoire sync` (they are the "generals" shipped by the template):
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
.agents/AGENTS.md rules/ standards/ stack/ agents/ skills/ commands/ tooling.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If you edit them, your change is lost on the next sync. Put the change in `local/` instead.
|
|
16
|
+
|
|
17
|
+
## Two ways to customize
|
|
18
|
+
|
|
19
|
+
1. **Override** a base behavior — restate it in `local/`. Because `local/` loads **last**, it wins.
|
|
20
|
+
- A base rule → add the corrected rule in `local/rules/` (or note it in `AGENTS.local.md`).
|
|
21
|
+
- A base standard/stack default → put the project version in `local/standards/` or `local/stack/`.
|
|
22
|
+
2. **Add** something the base doesn't have — a project-only rule, skill, command, or standard goes
|
|
23
|
+
straight into the matching `local/<area>/`.
|
|
24
|
+
|
|
25
|
+
## Layout
|
|
26
|
+
|
|
27
|
+
| Path | Holds |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `AGENTS.local.md` | entry: active stack profile, testing policy, project facts, override declarations |
|
|
30
|
+
| `rules/` | project-only always-on rules (named `local-*.md`) |
|
|
31
|
+
| `standards/` | project-only coding standards / per-language additions |
|
|
32
|
+
| `stack/` | project-only stack notes or profile overrides |
|
|
33
|
+
| `skills/` | project-only skills — each `<name>/SKILL.md` is mirrored to `.claude/skills/` by init/sync |
|
|
34
|
+
| `commands/` | project-only slash commands |
|
|
35
|
+
| `reference/` | project domain reference docs (big runtime contract, IPC tables, confirmed values) — indexed by `grimoire index` |
|
|
36
|
+
| `tooling.json` | project-only plugins / MCP servers (Linear, Sentry, Supabase, Figma, …) — `grimoire bootstrap` merges them additively with the base |
|
|
37
|
+
|
|
38
|
+
## Naming `local/rules/` — avoid number collisions with the base
|
|
39
|
+
|
|
40
|
+
The base ships numbered rules `00–60` (`rules/00-always.md`, `rules/30-verification.md`, …). A
|
|
41
|
+
project rule named `30-security.md` under `local/rules/` reads as "rule 30" too — ambiguous with the
|
|
42
|
+
base's `30-verification.md`. **Prefix every project rule with `local-`** so the number space never
|
|
43
|
+
clashes and the source is obvious at a glance:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
local/rules/local-10-design-system.md ✅ unambiguous, clearly project-owned
|
|
47
|
+
local/rules/30-security.md ❌ collides with base rules/30-verification.md
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Keep the original topic number after the prefix if it helps (`local-30-security.md`) — the `local-`
|
|
51
|
+
makes it distinct regardless. Reference them from `AGENTS.local.md` so the load order is explicit.
|
|
52
|
+
|
|
53
|
+
## Precedence
|
|
54
|
+
|
|
55
|
+
base loads first → `local/` loads last → **`local/` wins**. See the load order in `.agents/AGENTS.md`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Guardrail test — structural invariants (standards/guardrail-tests.md).
|
|
2
|
+
// Copy into the project's test dir and adapt the scanners. Runs under the existing `verify` gate
|
|
3
|
+
// (Vitest shown; the pattern is runner-agnostic). Fail CLOSED: a scan that returns nothing because
|
|
4
|
+
// it could not read its source is a failure, not a pass.
|
|
5
|
+
import { describe, it, expect } from "vitest";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
|
|
9
|
+
const SRC = path.resolve(__dirname, "..", "src");
|
|
10
|
+
|
|
11
|
+
function walk(dir: string, ext = ".ts"): string[] {
|
|
12
|
+
const out: string[] = [];
|
|
13
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
14
|
+
const p = path.join(dir, e.name);
|
|
15
|
+
if (e.isDirectory()) out.push(...walk(p, ext));
|
|
16
|
+
else if (e.name.endsWith(ext)) out.push(p);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function scan(re: RegExp): Set<string> {
|
|
22
|
+
const hits = new Set<string>();
|
|
23
|
+
for (const f of walk(SRC)) {
|
|
24
|
+
const text = fs.readFileSync(f, "utf8");
|
|
25
|
+
for (const m of text.matchAll(re)) hits.add(m[1]);
|
|
26
|
+
}
|
|
27
|
+
return hits;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function diff(a: Set<string>, b: Set<string>): string[] {
|
|
31
|
+
return [...a].filter((x) => !b.has(x)).sort();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("guardrail: IPC channels are allow-listed", () => {
|
|
35
|
+
// EXAMPLE — replace with the project's real registry/allow-list source of truth.
|
|
36
|
+
const ALLOW_LIST: string[] = require("../src/ipc/allow-list").CHANNELS; // declared truth
|
|
37
|
+
const used = scan(/ipcMain\.handle\(\s*["']([^"']+)["']/g); // live call sites
|
|
38
|
+
|
|
39
|
+
it("every registered channel is declared (fail closed on undeclared)", () => {
|
|
40
|
+
expect(used.size).toBeGreaterThan(0); // scanner found something — not a silent empty
|
|
41
|
+
expect(diff(used, new Set(ALLOW_LIST))).toEqual([]); // used but undeclared
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("no stale allow-list entries", () => {
|
|
45
|
+
expect(diff(new Set(ALLOW_LIST), used)).toEqual([]); // declared but unused
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("guardrail: thrown error codes exist in the catalog", () => {
|
|
50
|
+
// EXAMPLE — replace catalog source + throw pattern with the project's.
|
|
51
|
+
const catalog = fs.readFileSync(path.resolve(__dirname, "../.agents/standards/error-codes.md"), "utf8");
|
|
52
|
+
const declared = new Set([...catalog.matchAll(/`([A-Z]+_[A-Z0-9_]+)`/g)].map((m) => m[1]));
|
|
53
|
+
const thrown = scan(/AppError\(\s*["']([A-Z]+_[A-Z0-9_]+)["']/g);
|
|
54
|
+
|
|
55
|
+
it("every thrown code is catalogued", () => {
|
|
56
|
+
expect(declared.size).toBeGreaterThan(0); // catalog readable — fail closed, not a silent skip
|
|
57
|
+
expect(diff(thrown, declared)).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
});
|