kataster 0.0.0-stage → 0.2.1
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/.claude/agents/acceptance-tester.md +53 -0
- package/.claude/agents/code-reviewer.md +56 -0
- package/.claude/agents/domain-architect.md +40 -0
- package/.claude/agents/lead-dev.md +50 -0
- package/.claude/agents/product-owner.md +39 -0
- package/.claude/agents/repo-analyst.md +78 -0
- package/.claude/agents/requirements-engineer.md +44 -0
- package/.claude/agents/ux-designer.md +64 -0
- package/.claude/hooks/bash-guard.ts +92 -0
- package/.claude/hooks/code-check.ts +37 -0
- package/.claude/hooks/path-guard.ts +34 -0
- package/.claude/hooks/path-rules.ts +66 -0
- package/.claude/hooks/project-check.ts +108 -0
- package/.claude/hooks/protect-files.ts +55 -0
- package/.claude/hooks/session-start.ts +213 -0
- package/.claude/hooks/stop-gate.ts +56 -0
- package/.claude/hooks/validate-docs.ts +58 -0
- package/.claude/lib/architecture.ts +736 -0
- package/.claude/lib/backlog-github.ts +454 -0
- package/.claude/lib/backlog-jira.ts +347 -0
- package/.claude/lib/backlog-sync.ts +42 -0
- package/.claude/lib/backlog.ts +396 -0
- package/.claude/lib/bazel.ts +212 -0
- package/.claude/lib/config.ts +122 -0
- package/.claude/lib/discovery.ts +821 -0
- package/.claude/lib/engineering.ts +406 -0
- package/.claude/lib/nx.ts +129 -0
- package/.claude/lib/repo.ts +1194 -0
- package/.claude/lib/toolgraph.ts +74 -0
- package/.claude/lib/turbo.ts +166 -0
- package/.claude/package-lock.json +427 -0
- package/.claude/package.json +21 -0
- package/.claude/settings.json +82 -0
- package/.claude/skills/adopt/SKILL.md +283 -0
- package/.claude/skills/adopt/scripts/boundary-check.ts +156 -0
- package/.claude/skills/adopt/scripts/package-doc.ts +71 -0
- package/.claude/skills/adopt/scripts/repo-map.ts +123 -0
- package/.claude/skills/adopt/scripts/rule-doc.ts +80 -0
- package/.claude/skills/architect/ADR-FORMAT.md +97 -0
- package/.claude/skills/architect/SKILL.md +64 -0
- package/.claude/skills/architect/TECH-STACK.md +21 -0
- package/.claude/skills/backlog/SKILL.md +198 -0
- package/.claude/skills/backlog/scripts/backlog-pull.ts +45 -0
- package/.claude/skills/backlog/scripts/backlog-push.ts +38 -0
- package/.claude/skills/backlog/scripts/backlog-status.ts +32 -0
- package/.claude/skills/backlog/scripts/jira-import.ts +40 -0
- package/.claude/skills/backlog/scripts/jira-plan.ts +26 -0
- package/.claude/skills/backlog/scripts/jira-record.ts +41 -0
- package/.claude/skills/bootstrap/SKILL.md +119 -0
- package/.claude/skills/codebase-design/DEEPENING.md +37 -0
- package/.claude/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/.claude/skills/codebase-design/SKILL.md +114 -0
- package/.claude/skills/domain-model/CONTEXT-FORMAT.md +47 -0
- package/.claude/skills/domain-model/SKILL.md +64 -0
- package/.claude/skills/domain-model/templates/data-model.md +29 -0
- package/.claude/skills/engineering-conventions/SKILL.md +31 -0
- package/.claude/skills/event-storming/SKILL.md +44 -0
- package/.claude/skills/event-storming/schema/events.schema.json +124 -0
- package/.claude/skills/event-storming/scripts/render-event-storming.ts +11 -0
- package/.claude/skills/event-storming/scripts/validate-events.ts +11 -0
- package/.claude/skills/event-storming/templates/events.example.yaml +91 -0
- package/.claude/skills/feature/SKILL.md +86 -0
- package/.claude/skills/feature/scripts/intake.ts +356 -0
- package/.claude/skills/grill-me/SKILL.md +7 -0
- package/.claude/skills/grill-with-docs/SKILL.md +7 -0
- package/.claude/skills/grilling/SKILL.md +30 -0
- package/.claude/skills/groom-backlog/SKILL.md +93 -0
- package/.claude/skills/groom-backlog/scripts/backlog-health.ts +238 -0
- package/.claude/skills/implement/SKILL.md +129 -0
- package/.claude/skills/implement/scripts/affected.ts +245 -0
- package/.claude/skills/implement/scripts/check-commands.ts +37 -0
- package/.claude/skills/implement/scripts/check-language.ts +15 -0
- package/.claude/skills/implement/scripts/check-scenarios.ts +59 -0
- package/.claude/skills/implement/scripts/next-story.ts +23 -0
- package/.claude/skills/implement/scripts/story-context.ts +135 -0
- package/.claude/skills/implement/scripts/story-status.ts +47 -0
- package/.claude/skills/implement/scripts/verify.ts +92 -0
- package/.claude/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/.claude/skills/improve-codebase-architecture/SKILL.md +71 -0
- package/.claude/skills/retro/SKILL.md +53 -0
- package/.claude/skills/review-stories/SKILL.md +31 -0
- package/.claude/skills/shape/SKILL.md +193 -0
- package/.claude/skills/tdd/SKILL.md +38 -0
- package/.claude/skills/tdd/mocking.md +59 -0
- package/.claude/skills/tdd/tests.md +77 -0
- package/.claude/skills/user-stories/SKILL.md +138 -0
- package/.claude/skills/user-stories/schema/story.schema.json +39 -0
- package/.claude/skills/user-stories/scripts/render-backlog.ts +4 -0
- package/.claude/skills/user-stories/scripts/validate-stories.ts +13 -0
- package/.claude/skills/user-stories/templates/story-template.md +38 -0
- package/.claude/skills/ux-design/SKILL.md +107 -0
- package/.claude/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/.claude/skills/writing-for-agents/SKILL.md +81 -0
- package/.claude/tsconfig.json +15 -0
- package/.opencode/agents/acceptance-tester.md +64 -0
- package/.opencode/agents/code-reviewer.md +69 -0
- package/.opencode/agents/domain-architect.md +59 -0
- package/.opencode/agents/lead-dev.md +67 -0
- package/.opencode/agents/product-owner.md +59 -0
- package/.opencode/agents/repo-analyst.md +86 -0
- package/.opencode/agents/requirements-engineer.md +58 -0
- package/.opencode/agents/ux-designer.md +83 -0
- package/.opencode/commands/adopt.md +7 -0
- package/.opencode/commands/backlog-sync.md +7 -0
- package/.opencode/commands/bootstrap.md +7 -0
- package/.opencode/commands/event-storming.md +7 -0
- package/.opencode/commands/feature.md +7 -0
- package/.opencode/commands/grill-me.md +7 -0
- package/.opencode/commands/grill-with-docs.md +7 -0
- package/.opencode/commands/groom-backlog.md +7 -0
- package/.opencode/commands/implement.md +7 -0
- package/.opencode/commands/improve-codebase-architecture.md +7 -0
- package/.opencode/commands/retro.md +7 -0
- package/.opencode/commands/review-stories.md +7 -0
- package/.opencode/commands/shape.md +7 -0
- package/.opencode/opencode.jsonc +15 -0
- package/.opencode/plugins/kataster/index.ts +283 -0
- package/AGENTS.md +21 -0
- package/CHANGELOG.md +91 -0
- package/LICENSE +21 -0
- package/README.md +331 -2
- package/bin/kataster.mjs +7 -0
- package/extras/skills/shadcn/SKILL.md +277 -0
- package/extras/skills/shadcn/agents/openai.yml +5 -0
- package/extras/skills/shadcn/assets/shadcn-small.png +0 -0
- package/extras/skills/shadcn/assets/shadcn.png +0 -0
- package/extras/skills/shadcn/cli.md +290 -0
- package/extras/skills/shadcn/customization.md +209 -0
- package/extras/skills/shadcn/evals/evals.json +77 -0
- package/extras/skills/shadcn/mcp.md +105 -0
- package/extras/skills/shadcn/registry.md +277 -0
- package/extras/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/extras/skills/shadcn/rules/chat.md +250 -0
- package/extras/skills/shadcn/rules/composition.md +213 -0
- package/extras/skills/shadcn/rules/forms.md +192 -0
- package/extras/skills/shadcn/rules/icons.md +101 -0
- package/extras/skills/shadcn/rules/styling.md +185 -0
- package/guide/README.md +9 -0
- package/guide/brownfield.md +242 -0
- package/guide/concepts.md +109 -0
- package/guide/greenfield.md +84 -0
- package/guide/install.md +144 -0
- package/guide/release.md +92 -0
- package/package.json +56 -4
- package/src/cli.mjs +302 -0
- package/src/detect.mjs +237 -0
- package/src/install.mjs +427 -0
- package/src/repo.mjs +129 -0
- package/src/util.mjs +110 -0
- package/templates/CONTEXT.md +21 -0
- package/templates/conventions.md +63 -0
- package/templates/docs/adr/README.md +7 -0
- package/templates/docs/architecture/data-model.md +31 -0
- package/templates/docs/domain/context-map.md +21 -0
- package/templates/docs/domain/events.yaml +23 -0
- package/templates/docs/product/initiatives/README.md +41 -0
- package/templates/docs/product/ux-guidelines.md +27 -0
- package/templates/docs/product/vision.md +36 -0
- package/templates/docs/reviews/.gitkeep +0 -0
- package/templates/docs/stories/OPEN_QUESTIONS.md +8 -0
- package/templates/docs/stories/README.md +26 -0
- package/templates/docs/workflow.md +135 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
+
"permissions": {
|
|
4
|
+
"allow": [
|
|
5
|
+
"Bash(node .claude/skills/adopt/scripts/*)",
|
|
6
|
+
"Bash(node .claude/skills/event-storming/scripts/validate-events.ts)",
|
|
7
|
+
"Bash(node .claude/skills/event-storming/scripts/render-event-storming.ts)",
|
|
8
|
+
"Bash(node .claude/skills/user-stories/scripts/validate-stories.ts)",
|
|
9
|
+
"Bash(node .claude/skills/user-stories/scripts/render-backlog.ts)",
|
|
10
|
+
"Bash(node .claude/skills/implement/scripts/*)",
|
|
11
|
+
"Bash(git status *)",
|
|
12
|
+
"Bash(git diff *)",
|
|
13
|
+
"Bash(git log *)"
|
|
14
|
+
],
|
|
15
|
+
"deny": [],
|
|
16
|
+
"ask": []
|
|
17
|
+
},
|
|
18
|
+
"hooks": {
|
|
19
|
+
"SessionStart": [
|
|
20
|
+
{
|
|
21
|
+
"hooks": [
|
|
22
|
+
{
|
|
23
|
+
"type": "command",
|
|
24
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.ts\""
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"PreToolUse": [
|
|
30
|
+
{
|
|
31
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
32
|
+
"hooks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/protect-files.ts\""
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"matcher": "Bash",
|
|
41
|
+
"hooks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/bash-guard.ts\""
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"PostToolUse": [
|
|
50
|
+
{
|
|
51
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
52
|
+
"hooks": [
|
|
53
|
+
{
|
|
54
|
+
"type": "command",
|
|
55
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate-docs.ts\""
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "command",
|
|
59
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/code-check.ts\"",
|
|
60
|
+
"timeout": 90
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "command",
|
|
64
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/project-check.ts\"",
|
|
65
|
+
"timeout": 60
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"Stop": [
|
|
71
|
+
{
|
|
72
|
+
"hooks": [
|
|
73
|
+
{
|
|
74
|
+
"type": "command",
|
|
75
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop-gate.ts\"",
|
|
76
|
+
"timeout": 600
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: adopt
|
|
3
|
+
description: Brownfield entry point – maps the repository, adopts it in slices (one domain plus at most one shared library), drafts the domain model with evidence, grills the user, documents each package where it lives and records the gap; it derives stories only when asked (--stories). Use when the workflow is dropped into a repository that already has code.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[scope, e.g. 'apps/billing' or 'the order process' – empty = map the repository and choose a slice; add --stories to derive stories now]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Adopt an Existing Repository
|
|
9
|
+
|
|
10
|
+
The repository already works. Your job is to **recover the domain it encodes** – in slices, not by rewriting it
|
|
11
|
+
and not by documenting the whole monorepo in one pass. Code is evidence of decisions someone already made; the
|
|
12
|
+
user is the only one who can say which of the readings is the intended domain.
|
|
13
|
+
|
|
14
|
+
Scope: the arguments from the invocation (empty = map the repository and choose a slice). `--stories` is an
|
|
15
|
+
explicit opt-in for Phase 6; without it the adoption records the gap but creates no stories. Pick a short
|
|
16
|
+
kebab-case slug for the adoption (`adoption-<scope>`) for the report file.
|
|
17
|
+
|
|
18
|
+
## Preconditions
|
|
19
|
+
|
|
20
|
+
1. Read `.claude/project.json`. If it is missing, tell the user to run `npx kataster init` first and stop.
|
|
21
|
+
2. If the repository has no code yet, this is the wrong command: use `/bootstrap`.
|
|
22
|
+
3. Read what already exists, before analysing anything: `CONTEXT.md`, `docs/product/vision.md`,
|
|
23
|
+
`docs/domain/events.yaml`, `docs/domain/context-map.md`, `docs/architecture/data-model.md`,
|
|
24
|
+
`docs/architecture/repo-map.md`, `docs/engineering/conventions.md`, `docs/adr/`, `README*`, existing `docs/`
|
|
25
|
+
and any `AGENTS.md`/`CLAUDE.md`. Existing documentation is **primary evidence** – it outranks your inference
|
|
26
|
+
from code. Contradictions between docs and code are findings, not something to resolve silently.
|
|
27
|
+
|
|
28
|
+
## Phase 0 – Repository map (deterministic, no questions)
|
|
29
|
+
|
|
30
|
+
Run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
node .claude/skills/adopt/scripts/repo-map.ts
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
It scans manifests and git history and writes:
|
|
37
|
+
|
|
38
|
+
- `docs/architecture/repo-map.json` – packages, paths, kinds, internal dependencies, consumers, adoption ranking,
|
|
39
|
+
and the build tool's own graph when it answers (Turbo, Nx, Bazel)
|
|
40
|
+
- `docs/architecture/repo-map.md` – the same as a readable map (never edit it by hand)
|
|
41
|
+
- the generated repository block in `AGENTS.md` – tooling, layout, commands, adopted slices
|
|
42
|
+
- `.claude/project.json` → `repo.tooling` – Nx, Turborepo, Bazel, pnpm/npm/yarn workspaces, Go, Cargo, Gradle, Maven
|
|
43
|
+
|
|
44
|
+
Read the map yourself. **Do not hand-scan the repository for packages**; if the map is stale, run it again.
|
|
45
|
+
The map is facts, not domain: it says where code lives and what depends on what, never what a word means.
|
|
46
|
+
|
|
47
|
+
## Phase 1 – Choose the slice (one round, at most three questions)
|
|
48
|
+
|
|
49
|
+
The map suggests a first slice. Ask, each with a recommended answer:
|
|
50
|
+
|
|
51
|
+
1. **Slice**: the suggested domain plus its most-used shared library, or a different one? Recommended: the
|
|
52
|
+
suggestion from `repo-map.md` – it weighs recent churn, fan-in and kind, not size.
|
|
53
|
+
2. **Intent**: a domain model for future work, a map for onboarding, or a backlog for a rewrite? Recommended:
|
|
54
|
+
the domain model first; the other two follow from it.
|
|
55
|
+
3. **Language**: confirm `languages.ui` and `languages.artifacts` from the profile. Recommended: what the code
|
|
56
|
+
and UI already use.
|
|
57
|
+
|
|
58
|
+
Hard rule: **one domain plus at most one shared library per session.** A simple repository without monorepo
|
|
59
|
+
tooling is one slice – then the whole repository is in scope. Never "the whole monorepo"; a shallow map of 80
|
|
60
|
+
packages is worse than a confirmed model of two.
|
|
61
|
+
|
|
62
|
+
Create `docs/domain/adoption-report.md` with the answers under `## Scope`; fill the rest as you go. If earlier
|
|
63
|
+
slices are already adopted, name the next one and what changed since it was adopted (`git log --since=<date>`).
|
|
64
|
+
|
|
65
|
+
## Phase 2 – Evidence for the slice
|
|
66
|
+
|
|
67
|
+
Call the `skill` tool for `grilling`, `domain-model` and `architect` first: grilling sets how you ask,
|
|
68
|
+
domain-model sets what you are looking for, architect decides what becomes an ADR.
|
|
69
|
+
|
|
70
|
+
Dispatch `repo-analyst` subagents **in one message**, each with the slice path, the repository map path and one
|
|
71
|
+
lens. They are read-only.
|
|
72
|
+
|
|
73
|
+
- **Monorepo / several packages**: three analysts.
|
|
74
|
+
| Lens | What it looks for |
|
|
75
|
+
|---|---|
|
|
76
|
+
| Structure, data and entry points | Manifests, entry points, schema, migrations, enums, state columns, external services, jobs, the slice's internal dependencies and consumers |
|
|
77
|
+
| Language, behaviour and tests | Nouns and verbs in types, routes, UI texts, errors; handlers, validations, permissions; tests as executable specifications; candidate events/commands/read models |
|
|
78
|
+
| Architecture, dependencies and history | Layering and import direction from `repo-map.md`; build tooling and its graph; de-facto decisions in config; `git log` hotspots, reverted changes, TODOs |
|
|
79
|
+
- **Simple repository / no monorepo tooling**: the five lenses from the old adoption (structure and stack,
|
|
80
|
+
domain language, data and integrations, behaviour and tests, history and decisions) – the slice is the whole
|
|
81
|
+
repository.
|
|
82
|
+
|
|
83
|
+
While they run, read the repository's own documentation yourself. Do not block the round on the analysts.
|
|
84
|
+
|
|
85
|
+
## Phase 3 – Draft the slice
|
|
86
|
+
|
|
87
|
+
Merge the reports into one picture. Write the artifacts **as a draft**, every uncertain statement marked.
|
|
88
|
+
|
|
89
|
+
- **`CONTEXT.md`** – only the slice's terms, grouped by guessed bounded context, competing spellings under
|
|
90
|
+
`_Avoid_`, `[OPEN]` where the meaning is unclear. Do not touch terms of other slices.
|
|
91
|
+
- **`docs/domain/events.yaml`** – 10–25 candidate events/commands/actors/read models/policies/flows for this
|
|
92
|
+
slice. Every uncertainty becomes a hotspot (`HS-n`, `status: open`).
|
|
93
|
+
- **`docs/domain/context-map.md`** – the boundaries the module structure suggests, marked as a proposal.
|
|
94
|
+
- **`docs/architecture/data-model.md`** – the **as-is** model for the slice, derived from schema and code.
|
|
95
|
+
- **`docs/engineering/conventions.md`** – fill what the slice actually does: module layout, how a command runs,
|
|
96
|
+
read models, "now", texts, test data, seam catalog. Include how the monorepo tooling is used.
|
|
97
|
+
- **`docs/product/vision.md`** – only if missing or empty, reconstruct and mark `[OPEN]`.
|
|
98
|
+
- **`docs/adr/`** – de-facto decisions worth recording, `status: proposed`. Only the user accepts.
|
|
99
|
+
- **Package docs** – for the domain and the shared library (in a monorepo):
|
|
100
|
+
```bash
|
|
101
|
+
node .claude/skills/adopt/scripts/package-doc.ts apps/billing
|
|
102
|
+
node .claude/skills/adopt/scripts/package-doc.ts libs/shared-kernel
|
|
103
|
+
```
|
|
104
|
+
A single-package repository has no package file: its root `AGENTS.md` is the package doc (`package-doc.ts .`
|
|
105
|
+
deliberately refuses). The script writes `<package>/AGENTS.md` (source of truth) and `<package>/CLAUDE.md`
|
|
106
|
+
(`@AGENTS.md`, for Claude Code's on-demand nested loading). It generates the facts block; **you** fill the prose
|
|
107
|
+
during the grilling:
|
|
108
|
+
- domain/service: Purpose, Key entities, External interfaces, Typical pitfalls, Boundaries
|
|
109
|
+
- shared library: Purpose, Public API, Consumers, Compatibility rules, Typical pitfalls, Boundaries
|
|
110
|
+
Keep each file under ~80 lines. This file is loaded only when someone works in that package.
|
|
111
|
+
- **Root `AGENTS.md`** – the generated block comes from the map. Below it, add only structure, commands, hard
|
|
112
|
+
conventions and links. Keep at most ten bullets under `## Hard conventions`, each naming where it is enforced
|
|
113
|
+
(`lint`, a test, `.claude/rules/<file>.md`, `docs/engineering/checks.yaml`) – a rule without an enforcement
|
|
114
|
+
point is a wish. **No domain rules, no entities, no business vocabulary** – those belong in `CONTEXT.md` and
|
|
115
|
+
the package docs.
|
|
116
|
+
- **`.claude/rules/`** – only for path-scoped rules that cannot be a directory document (e.g. `**/*.sql`,
|
|
117
|
+
`**/migrations/**`), with `paths:` frontmatter. Directory-scoped rules belong in `<dir>/AGENTS.md` because that
|
|
118
|
+
is the mechanism both harnesses load on demand. A rule for a whole group gets `<group>/AGENTS.md` plus a
|
|
119
|
+
one-line `<group>/CLAUDE.md` (`@AGENTS.md`) – e.g. `libs/AGENTS.md` for "everything under `libs/**`". Never
|
|
120
|
+
duplicate the same rule in both mechanisms.
|
|
121
|
+
|
|
122
|
+
After every write of `events.yaml`, the hook validates and renders it. Fix errors immediately.
|
|
123
|
+
|
|
124
|
+
### Rules for the draft
|
|
125
|
+
|
|
126
|
+
- A code name is a *spelling*, never automatically the domain term. `OrderService.place()` is evidence for
|
|
127
|
+
"Order placed", not proof of the word "order".
|
|
128
|
+
- One concept with three spellings → one candidate term and two `_Avoid_` entries, or a hotspot.
|
|
129
|
+
- Never invent a business rule. If the code enforces something, report it as "the code enforces X (path)"; the
|
|
130
|
+
user decides whether that is a rule or an accident.
|
|
131
|
+
- If the repository contradicts itself, that is a hotspot, not a choice you make.
|
|
132
|
+
|
|
133
|
+
## Phase 4 – Grill the user against the draft
|
|
134
|
+
|
|
135
|
+
This is the core of the adoption. Present the draft, then work the frontier in rounds exactly as the `grilling`
|
|
136
|
+
skill says: numbered questions, each with a recommended answer, whole frontier per round.
|
|
137
|
+
|
|
138
|
+
Questions brownfield needs, roughly in this order:
|
|
139
|
+
|
|
140
|
+
1. **Terms** – one question per cluster of competing spellings, worst first.
|
|
141
|
+
2. **Boundaries** – which package owns which state; where a shared library ends and a domain begins.
|
|
142
|
+
3. **Lifecycle** – states the schema allows, transitions it does not block.
|
|
143
|
+
4. **Invariants** – what the code checks only in the UI; what must always hold.
|
|
144
|
+
5. **Missing behaviour** – what has no trace: never needed, or a gap?
|
|
145
|
+
6. **Architecture** – layering, CQRS/read models, dependency direction, cross-context communication. Which are
|
|
146
|
+
real decisions and which are accidents? Record the real ones as ADRs.
|
|
147
|
+
7. **Build tooling** – how packages are built, tested and filtered; whether affected tests are trustworthy.
|
|
148
|
+
8. **Shared libraries** – public API, consumers, what may not break without a migration.
|
|
149
|
+
9. **Intent** – which of this is deliberate, and which is legacy you want to leave behind.
|
|
150
|
+
|
|
151
|
+
Every answer updates the draft **immediately**: `CONTEXT.md`, `events.yaml`, the package's `AGENTS.md`, the ADR.
|
|
152
|
+
Resolved hotspots get `status: resolved` + `resolution`. New uncertainty becomes a new hotspot. Do not move on
|
|
153
|
+
until the frontier is empty and the user confirms a shared understanding.
|
|
154
|
+
|
|
155
|
+
## Phase 5 – Safety net: make the confirmed rules checkable
|
|
156
|
+
|
|
157
|
+
For every confirmed hard rule or invariant, choose the cheapest deterministic enforcement – in this order:
|
|
158
|
+
|
|
159
|
+
1. **Type system** (a state that cannot be represented cannot be written)
|
|
160
|
+
2. **Lint / boundary check** (import direction, layer, package visibility – dependency-cruiser, Nx module
|
|
161
|
+
boundaries, Bazel visibility, ArchUnit, import-linter)
|
|
162
|
+
3. **Architecture or characterization test** (a test pins the rule or the existing behaviour)
|
|
163
|
+
4. **Hook** (only for fast, edit-time checks; full checks belong in Stop/CI)
|
|
164
|
+
5. **Documentation only** (when nothing can check it)
|
|
165
|
+
|
|
166
|
+
What you may create here:
|
|
167
|
+
|
|
168
|
+
- 3–5 **characterization tests** for the slice's most important existing behaviour – they pin what is, they do
|
|
169
|
+
not assert what should be.
|
|
170
|
+
- The architecture boundaries and checks:
|
|
171
|
+
```bash
|
|
172
|
+
node .claude/skills/adopt/scripts/boundary-check.ts --init
|
|
173
|
+
# edit docs/architecture/boundaries.yaml with the rules the user confirmed, then
|
|
174
|
+
node .claude/skills/adopt/scripts/boundary-check.ts --update-baseline
|
|
175
|
+
```
|
|
176
|
+
Run `--init` on the first slice only; later slices extend the existing `boundaries.yaml`. It writes a proposal
|
|
177
|
+
for `docs/architecture/boundaries.yaml`, the default `docs/engineering/checks.yaml` and an empty baseline.
|
|
178
|
+
Rules are evaluated in order; the first matching `from` → `to` pair decides (no match = allow). The engine is
|
|
179
|
+
`scan` for JS/TS imports, or `command` for the project's own tool (dependency-cruiser, Nx module boundaries,
|
|
180
|
+
Bazel, ArchUnit, import-linter).
|
|
181
|
+
- `.claude/rules/` entries for confirmed rules that a directory cannot express:
|
|
182
|
+
```bash
|
|
183
|
+
node .claude/skills/adopt/scripts/rule-doc.ts libs-shared --paths "libs/**" --title "Shared libraries"
|
|
184
|
+
```
|
|
185
|
+
A rule for a whole directory belongs in `<dir>/AGENTS.md` instead; do not duplicate it in both mechanisms.
|
|
186
|
+
- `docs/engineering/checks.yaml` entries with `phase: edit` (fast, changed file only) or `phase: stop` (full set).
|
|
187
|
+
|
|
188
|
+
What you may **not** do: change production code, or write a test that fails on existing behaviour. On a
|
|
189
|
+
brownfield repository the checks are **report-only first**: record existing violations in a baseline, then let
|
|
190
|
+
only new violations fail (ratchet). A hook that is red on day one gets switched off.
|
|
191
|
+
|
|
192
|
+
Hooks are wired once, through the `project-check.ts` dispatcher reading `docs/engineering/checks.yaml`, not by
|
|
193
|
+
adding per-package hook entries to `.claude/settings.json`. Keep edit-time checks fast; the full set runs at
|
|
194
|
+
Stop/CI. If a rule needs new behaviour, it becomes a story – not a failing test.
|
|
195
|
+
|
|
196
|
+
## Phase 6 – The gap register (stories only on request)
|
|
197
|
+
|
|
198
|
+
Compare the confirmed model with the code. Classify, and show the table to the user:
|
|
199
|
+
|
|
200
|
+
| Class | Meaning | Default |
|
|
201
|
+
|---|---|---|
|
|
202
|
+
| **Exists and is intended** | Code matches the confirmed model | Documented in the data model/context map. No action. |
|
|
203
|
+
| **Exists but contradicts the model** | Code does something the user says is wrong | Candidate in the gap register |
|
|
204
|
+
| **Missing** | The model needs it, the code has no trace | Candidate in the gap register |
|
|
205
|
+
| **Dead** | Code has no place in the model | Candidate: removal or an explicit "leave it" |
|
|
206
|
+
|
|
207
|
+
**The default is no stories.** The first adoption pass is about understanding the repo, not about filling a
|
|
208
|
+
backlog. Write the table into `docs/domain/adoption-report.md`; open questions go into
|
|
209
|
+
`docs/stories/OPEN_QUESTIONS.md` or a hotspot. This keeps the model reviewable without committing to work the
|
|
210
|
+
user has not prioritised.
|
|
211
|
+
|
|
212
|
+
Only when the invocation contains `--stories`, or the user explicitly asks after seeing the table:
|
|
213
|
+
|
|
214
|
+
- delegate to `requirements-engineer` with the **selected** gaps only, the confirmed IDs from `events.yaml`, the
|
|
215
|
+
label `adoption:<slug>`, and `ui` for stories with a frontend part;
|
|
216
|
+
- new stories start as `status: draft`; the ones the user wants first go through `/review-stories`.
|
|
217
|
+
|
|
218
|
+
**Do not write stories for behaviour that already works** – that turns the backlog into a description of the
|
|
219
|
+
past. Existing behaviour is covered by its tests, and the domain model is the map. If an earlier run created
|
|
220
|
+
stories the user does not want, do not delete them silently: ask whether to `supersede` them or keep them.
|
|
221
|
+
|
|
222
|
+
## Phase 7 – Report and the next slice
|
|
223
|
+
|
|
224
|
+
Write `docs/domain/adoption-report.md`:
|
|
225
|
+
|
|
226
|
+
```md
|
|
227
|
+
# Adoption – <scope>
|
|
228
|
+
Date: YYYY-MM-DD · Commit: <sha> · Slice: <paths> · Analysts: <n> lenses
|
|
229
|
+
|
|
230
|
+
## Scope and intent
|
|
231
|
+
## Repository map (tooling, packages, why this slice)
|
|
232
|
+
## What the repository is (facts)
|
|
233
|
+
## Confirmed domain model
|
|
234
|
+
- contexts, aggregates, glossary changes
|
|
235
|
+
## Package documentation written
|
|
236
|
+
- <path>/AGENTS.md + CLAUDE.md – what was confirmed and what stays [OPEN]
|
|
237
|
+
## Contradictions found and how they were resolved
|
|
238
|
+
## Rules and checks
|
|
239
|
+
- rule → enforcement (type / lint / test / hook / doc) → baseline or green
|
|
240
|
+
## Gap register (candidates – stories only with --stories)
|
|
241
|
+
## Deliberately left alone
|
|
242
|
+
## Open hotspots
|
|
243
|
+
## Next slice
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Mark the slice adopted so the next session sees the progress:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
node .claude/skills/adopt/scripts/repo-map.ts --adopt apps/billing
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Then run `node .claude/skills/event-storming/scripts/validate-events.ts` and
|
|
253
|
+
`node .claude/skills/user-stories/scripts/validate-stories.ts`, and show the result.
|
|
254
|
+
|
|
255
|
+
## Wrap-up
|
|
256
|
+
|
|
257
|
+
Summarize in a few lines: terms added, contexts/aggregates proposed, hotspots open, package docs written,
|
|
258
|
+
checks created, gap candidates (and stories only if requested), ADRs proposed. Then name the next step:
|
|
259
|
+
|
|
260
|
+
- `git diff` is the review: no production code changed, only docs, package docs and tooling.
|
|
261
|
+
- `/adopt <next path>` for the next slice.
|
|
262
|
+
- `/feature <idea>` for the next piece of work, now that the domain has a language.
|
|
263
|
+
- `/adopt <scope> --stories` (or `/review-stories` if stories already exist) when the user wants the gap turned
|
|
264
|
+
into a backlog.
|
|
265
|
+
- `/implement` once a story is `ready`.
|
|
266
|
+
|
|
267
|
+
## Rules
|
|
268
|
+
|
|
269
|
+
- **Never change production code in `/adopt`.** Tests and tooling are allowed only as the safety net above.
|
|
270
|
+
- **Never present an inference as a fact.** Confidence and evidence, or a hotspot.
|
|
271
|
+
- **The user owns the language.** You may propose a better word; you may not rename the domain on your own.
|
|
272
|
+
- **Adopt in slices.** One domain plus at most one shared library. Never the whole monorepo in one pass.
|
|
273
|
+
- **The root `AGENTS.md` stays free of domain.** Structure, commands, hard conventions and links only.
|
|
274
|
+
- **Package docs are short and on demand.** `<package>/AGENTS.md` + `<package>/CLAUDE.md`, under ~80 lines.
|
|
275
|
+
- **Directory docs before glob rules.** `.claude/rules/` is for patterns a directory cannot express. Both
|
|
276
|
+
harnesses see the same file: Claude Code scopes it natively by `paths:`, OpenCode's plugin attaches it when a
|
|
277
|
+
matching file is read or written. Directory-scoped rules still belong in `<dir>/AGENTS.md`.
|
|
278
|
+
- **No backlog by default.** Adoption produces the model and a gap register; stories are an explicit second step
|
|
279
|
+
(`--stories`) after the user has prioritised.
|
|
280
|
+
- **Checks are green on day one.** Baseline existing violations, ratchet new ones; no red hook.
|
|
281
|
+
- **The map is generated.** Never hand-edit `repo-map.json`/`repo-map.md` or the generated blocks.
|
|
282
|
+
- **Stop when the frontier is empty.** A model that is 80% confirmed and 20% hotspot is more useful than one
|
|
283
|
+
that is 100% invented.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture boundary check with baseline/ratchet.
|
|
3
|
+
*
|
|
4
|
+
* node .claude/skills/adopt/scripts/boundary-check.ts --init
|
|
5
|
+
* node .claude/skills/adopt/scripts/boundary-check.ts
|
|
6
|
+
* node .claude/skills/adopt/scripts/boundary-check.ts --changed [file]
|
|
7
|
+
* node .claude/skills/adopt/scripts/boundary-check.ts --update-baseline
|
|
8
|
+
* node .claude/skills/adopt/scripts/boundary-check.ts --json
|
|
9
|
+
*
|
|
10
|
+
* `--init` writes a proposal for `docs/architecture/boundaries.yaml`, the default `docs/engineering/checks.yaml`
|
|
11
|
+
* and an empty baseline. The user confirms the rules during /adopt; `--update-baseline` freezes violations that
|
|
12
|
+
* already exist, so only new ones fail.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import {
|
|
17
|
+
BOUNDARIES_FILE, BASELINE_FILE, CHECKS_FILE, adapterHints, baselineFrom, checkBoundaries, defaultChecks, defaultRules,
|
|
18
|
+
emptyBaseline, evaluateBaseline, formatViolation, loadBaseline, loadBoundaries, relPath, rootMap,
|
|
19
|
+
writeBaseline, writeBoundaries, writeChecks,
|
|
20
|
+
} from "../../../lib/architecture.ts";
|
|
21
|
+
import { ROOT } from "../../../lib/repo.ts";
|
|
22
|
+
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const help = args.includes("--help") || args.includes("-h");
|
|
25
|
+
const init = args.includes("--init");
|
|
26
|
+
const update = args.includes("--update-baseline");
|
|
27
|
+
const json = args.includes("--json");
|
|
28
|
+
|
|
29
|
+
function usage(): void {
|
|
30
|
+
console.log(
|
|
31
|
+
[
|
|
32
|
+
"Usage: node .claude/skills/adopt/scripts/boundary-check.ts [options]",
|
|
33
|
+
"",
|
|
34
|
+
" --init write a boundaries.yaml proposal, checks.yaml and an empty baseline",
|
|
35
|
+
" --force with --init: overwrite existing files",
|
|
36
|
+
" --changed [file] check only this file (or $CHANGED_FILE, used by the edit hook)",
|
|
37
|
+
" --update-baseline freeze current violations so only new ones fail",
|
|
38
|
+
" --json machine-readable result",
|
|
39
|
+
].join("\n"),
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (help) {
|
|
44
|
+
usage();
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
if (init) {
|
|
50
|
+
const map = rootMap(ROOT);
|
|
51
|
+
const force = args.includes("--force");
|
|
52
|
+
if (!force) {
|
|
53
|
+
for (const file of [BOUNDARIES_FILE, CHECKS_FILE, BASELINE_FILE]) {
|
|
54
|
+
if (existsSync(join(ROOT, file))) throw new Error(`${file} already exists – edit it, or pass --force`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const boundaries = { version: 1 as const, engine: "auto" as const, command: "", rules: defaultRules(map) };
|
|
58
|
+
const boundariesPath = writeBoundaries(ROOT, boundaries, force);
|
|
59
|
+
const checksPath = writeChecks(ROOT, { version: 1, checks: defaultChecks() }, force);
|
|
60
|
+
const baselinePath = writeBaseline(ROOT, emptyBaseline());
|
|
61
|
+
console.log(`Wrote ${relPath(ROOT, boundariesPath)} with ${boundaries.rules.length} proposed rule(s).`);
|
|
62
|
+
console.log(`Wrote ${relPath(ROOT, checksPath)} and ${relPath(ROOT, baselinePath)}.`);
|
|
63
|
+
if (!boundaries.rules.length) {
|
|
64
|
+
console.log("No apps/, services/, libs/ or packages/ directories were found – add the rules by hand.");
|
|
65
|
+
}
|
|
66
|
+
for (const hint of adapterHints(map)) console.log(`Hint: ${hint}`);
|
|
67
|
+
console.log("Review and confirm the rules with the user, then freeze existing violations:");
|
|
68
|
+
console.log(" node .claude/skills/adopt/scripts/boundary-check.ts --update-baseline");
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const changedIndex = args.indexOf("--changed");
|
|
73
|
+
const changedArg = changedIndex === -1 ? undefined : args[changedIndex + 1];
|
|
74
|
+
const changed = changedIndex === -1
|
|
75
|
+
? undefined
|
|
76
|
+
: changedArg && !changedArg.startsWith("--")
|
|
77
|
+
? relPath(ROOT, changedArg)
|
|
78
|
+
: process.env.CHANGED_FILE
|
|
79
|
+
? relPath(ROOT, process.env.CHANGED_FILE)
|
|
80
|
+
: undefined;
|
|
81
|
+
|
|
82
|
+
if (update && changed) {
|
|
83
|
+
console.error("--update-baseline must run without --changed – freezing a single file would drop the rest.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const boundaries = loadBoundaries(ROOT);
|
|
88
|
+
if (!boundaries) {
|
|
89
|
+
console.log(`No ${BOUNDARIES_FILE} – architecture boundaries are not configured yet.`);
|
|
90
|
+
console.log("Run `node .claude/skills/adopt/scripts/boundary-check.ts --init` during /adopt.");
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!boundaries.rules.length && boundaries.engine !== "command") {
|
|
95
|
+
console.log("No boundary rules configured – nothing to check.");
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const map = rootMap(ROOT);
|
|
100
|
+
const result = checkBoundaries(ROOT, boundaries, map, changed);
|
|
101
|
+
|
|
102
|
+
if (update) {
|
|
103
|
+
const path = writeBaseline(ROOT, baselineFrom(result));
|
|
104
|
+
const command = result.command ? ` and the command failure` : "";
|
|
105
|
+
console.log(`Baseline written to ${relPath(ROOT, path)}: ${result.violations.length} violation(s)${command} frozen.`);
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const report = evaluateBaseline(result, loadBaseline(ROOT));
|
|
110
|
+
|
|
111
|
+
if (json) {
|
|
112
|
+
console.log(JSON.stringify({
|
|
113
|
+
ok: report.ok,
|
|
114
|
+
engine: report.engine,
|
|
115
|
+
checked: report.checked,
|
|
116
|
+
violations: report.violations.length,
|
|
117
|
+
new: report.newViolations,
|
|
118
|
+
stale: report.stale,
|
|
119
|
+
command: report.command ? { name: report.command.name, baselined: report.commandBaselined, output: report.command.output } : undefined,
|
|
120
|
+
note: report.note,
|
|
121
|
+
}, null, 2));
|
|
122
|
+
process.exit(report.ok ? 0 : 1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (report.note) console.log(report.note);
|
|
126
|
+
const unit = report.engine === "scan" ? "import edge(s)" : "check(s)";
|
|
127
|
+
console.log(`Architecture boundaries (${report.engine}): ${report.checked} ${unit}, ${report.violations.length} violation(s).`);
|
|
128
|
+
|
|
129
|
+
if (report.command && !report.commandBaselined) {
|
|
130
|
+
console.error(`\nThe architecture command failed (not baselined):\n${report.command.output}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (report.newViolations.length) {
|
|
135
|
+
const shown = report.newViolations.slice(0, 50);
|
|
136
|
+
console.error(`\nNew boundary violations – fix them or, if they are existing debt, freeze them with --update-baseline:\n${shown.map(formatViolation).join("\n")}`);
|
|
137
|
+
if (report.newViolations.length > shown.length) {
|
|
138
|
+
console.error(`… and ${report.newViolations.length - shown.length} more (see --json).`);
|
|
139
|
+
}
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (report.violations.length) {
|
|
144
|
+
console.log(`${report.violations.length} baselined violation(s) – existing debt, not failing.`);
|
|
145
|
+
}
|
|
146
|
+
if (report.stale.length) {
|
|
147
|
+
console.log(`${report.stale.length} baseline entr${report.stale.length === 1 ? "y" : "ies"} no longer occur – update the baseline to tighten the ratchet.`);
|
|
148
|
+
}
|
|
149
|
+
if (report.command && report.commandBaselined) {
|
|
150
|
+
console.log("The architecture command failure is baselined.");
|
|
151
|
+
}
|
|
152
|
+
console.log("OK – no new boundary violations.");
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writes or refreshes the per-package documentation that is loaded only when an agent works in that package.
|
|
3
|
+
*
|
|
4
|
+
* node .claude/skills/adopt/scripts/package-doc.ts apps/billing
|
|
5
|
+
* node .claude/skills/adopt/scripts/package-doc.ts apps/billing --adopt
|
|
6
|
+
*
|
|
7
|
+
* It creates `<package>/AGENTS.md` (source of truth) and `<package>/CLAUDE.md` (`@AGENTS.md` for Claude Code).
|
|
8
|
+
* The generated Facts block is refreshed on every run; the prose sections (Purpose, Key entities, External
|
|
9
|
+
* interfaces, Typical pitfalls, Boundaries) are never touched. If an existing AGENTS.md has no generated
|
|
10
|
+
* markers, the script leaves it alone and says so.
|
|
11
|
+
*/
|
|
12
|
+
import {
|
|
13
|
+
ROOT, findPackage, markAdopted, readRepoMap, scanRepo, updateProjectTooling, writePackageDoc, writeRepoMap, writeRootBlock,
|
|
14
|
+
} from "../../../lib/repo.ts";
|
|
15
|
+
|
|
16
|
+
const args = process.argv.slice(2).filter((arg) => !arg.startsWith("--"));
|
|
17
|
+
const adopt = process.argv.includes("--adopt");
|
|
18
|
+
const path = args[0];
|
|
19
|
+
|
|
20
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
21
|
+
console.log("Usage: node .claude/skills/adopt/scripts/package-doc.ts <package-path> [--adopt]");
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
if (!path) {
|
|
25
|
+
console.error("Usage: node .claude/skills/adopt/scripts/package-doc.ts <package-path> [--adopt]");
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
if (path === "." || path === "./" || path === "") {
|
|
31
|
+
console.error("The root package is documented in AGENTS.md, not in a package file.");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let map = readRepoMap(ROOT);
|
|
36
|
+
if (!map) {
|
|
37
|
+
map = scanRepo(ROOT);
|
|
38
|
+
writeRepoMap(ROOT, map);
|
|
39
|
+
updateProjectTooling(ROOT, map.tooling);
|
|
40
|
+
writeRootBlock(ROOT, map);
|
|
41
|
+
console.log("Wrote docs/architecture/repo-map.json and the root AGENTS.md block first (they were missing).");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const pkg = findPackage(map, path);
|
|
45
|
+
if (!pkg) {
|
|
46
|
+
const available = map.packages.map((p) => p.path).slice(0, 25).join(", ");
|
|
47
|
+
console.error(`Package '${path}' is not in the repository map. Known packages: ${available}${map.packages.length > 25 ? ", …" : ""}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = writePackageDoc(ROOT, map, pkg);
|
|
52
|
+
const agentsRel = result.agents.replace(`${ROOT}/`, "");
|
|
53
|
+
const claudeRel = result.claude.replace(`${ROOT}/`, "");
|
|
54
|
+
|
|
55
|
+
if (result.status === "created") {
|
|
56
|
+
console.log(`Created ${agentsRel} and ${claudeRel}`);
|
|
57
|
+
console.log("Fill the [OPEN] sections in AGENTS.md during the grilling – do not invent domain meaning.");
|
|
58
|
+
} else if (result.status === "refreshed") {
|
|
59
|
+
console.log(`Refreshed the generated block in ${agentsRel}`);
|
|
60
|
+
} else {
|
|
61
|
+
console.log(`Kept ${agentsRel}: it has no generated markers, so it is treated as hand-written.`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (adopt) {
|
|
65
|
+
markAdopted(ROOT, pkg.path);
|
|
66
|
+
console.log(`Marked adopted: ${pkg.path}`);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|