dotbrain 0.3.4__py3-none-any.whl
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.
- dotbrain/__init__.py +7 -0
- dotbrain/_cli_reference.py +115 -0
- dotbrain/adopter_repos.py +573 -0
- dotbrain/beads.py +511 -0
- dotbrain/bootstrap.py +199 -0
- dotbrain/brainspaces.py +238 -0
- dotbrain/cli.py +660 -0
- dotbrain/config.py +428 -0
- dotbrain/doctor.py +279 -0
- dotbrain/hooks.py +84 -0
- dotbrain/migrate.py +304 -0
- dotbrain/paths.py +139 -0
- dotbrain/resource_loader.py +47 -0
- dotbrain/resources/__init__.py +1 -0
- dotbrain/resources/agents/claude/implementer.md +47 -0
- dotbrain/resources/agents/claude/investigator.md +35 -0
- dotbrain/resources/agents/claude/reviewer.md +38 -0
- dotbrain/resources/agents/claude/verifier.md +35 -0
- dotbrain/resources/agents/codex/implementer.toml +26 -0
- dotbrain/resources/agents/codex/investigator.toml +21 -0
- dotbrain/resources/agents/codex/reviewer.toml +27 -0
- dotbrain/resources/agents/codex/verifier.toml +21 -0
- dotbrain/resources/config.yaml +20 -0
- dotbrain/resources/core.yaml +18 -0
- dotbrain/resources/templates/brain/AGENTS.md +9 -0
- dotbrain/resources/templates/brain/DOTBRAIN.md +105 -0
- dotbrain/resources/templates/brain/adr/README.md +8 -0
- dotbrain/resources/templates/brain/designs/README.md +28 -0
- dotbrain/resources/templates/brain/docs/README.md +9 -0
- dotbrain/resources/templates/brain/project.yaml +27 -0
- dotbrain/resources/templates/gitignore +17 -0
- dotbrain/skills.py +264 -0
- dotbrain/subagents.py +252 -0
- dotbrain/updater.py +105 -0
- dotbrain/workflows.py +529 -0
- dotbrain-0.3.4.dist-info/METADATA +21 -0
- dotbrain-0.3.4.dist-info/RECORD +40 -0
- dotbrain-0.3.4.dist-info/WHEEL +4 -0
- dotbrain-0.3.4.dist-info/entry_points.txt +2 -0
- dotbrain-0.3.4.dist-info/licenses/LICENSE +21 -0
dotbrain/paths.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Pure path and contract helpers for the dotbrain wiring convention.
|
|
2
|
+
|
|
3
|
+
These encode the compatibility contracts of the wiring convention as data
|
|
4
|
+
and side-effect-free functions. No filesystem mutation happens here; the wiring
|
|
5
|
+
mutators build on top of these.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# The Brainspace links an adopter repo symlinks into its root, in convention order.
|
|
14
|
+
BRAINSPACE_LINKS: tuple[str, ...] = (".brain", ".beads")
|
|
15
|
+
|
|
16
|
+
# Data-root directory holding the project Brainspaces, in preference order. ``brainspaces`` is
|
|
17
|
+
# the current name; ``projects`` is the legacy name still accepted for back-compat.
|
|
18
|
+
DATA_DIRS: tuple[str, ...] = ("brainspaces", "projects")
|
|
19
|
+
|
|
20
|
+
# Matching anchored entries written to an adopter repo's .git/info/exclude.
|
|
21
|
+
EXCLUDE_ENTRIES: tuple[str, ...] = ("/.brain", "/.beads")
|
|
22
|
+
|
|
23
|
+
# Breadcrumb appended to an adopter repo's real AGENTS.md / CLAUDE.md.
|
|
24
|
+
ADOPTER_POINTER: str = (
|
|
25
|
+
"@.brain/CLAUDE.md\n"
|
|
26
|
+
"Dotbrain: private project context lives at `.brain/AGENTS.md`; "
|
|
27
|
+
"read it before substantial agent work."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Disabled for now: brain context (DOTBRAIN.md + .brain/AGENTS.md) is injected at
|
|
31
|
+
# session start via the SessionStart hook, so the adopter pointer is
|
|
32
|
+
# redundant. Flip to True to re-enable wire/doctor pointer management.
|
|
33
|
+
INJECT_ADOPTER_POINTER: bool = False
|
|
34
|
+
|
|
35
|
+
# Windows WinError raised when creating a directory symlink without Developer Mode or elevation.
|
|
36
|
+
_WIN_PRIVILEGE_NOT_HELD = 1314
|
|
37
|
+
|
|
38
|
+
DEVELOPER_MODE_MESSAGE: str = (
|
|
39
|
+
"creating a directory symlink requires Windows Developer Mode (or Administrator "
|
|
40
|
+
"privileges); enable Developer Mode in Settings > Privacy & security > For developers, "
|
|
41
|
+
"then retry"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def symlink_privilege_message(exc: OSError) -> str | None:
|
|
46
|
+
"""Translate a Windows directory-symlink privilege ``OSError`` into a dotbrain message.
|
|
47
|
+
|
|
48
|
+
Returns ``None`` when ``exc`` isn't that specific failure, so callers re-raise everything
|
|
49
|
+
else unchanged.
|
|
50
|
+
"""
|
|
51
|
+
if getattr(exc, "winerror", None) == _WIN_PRIVILEGE_NOT_HELD:
|
|
52
|
+
return DEVELOPER_MODE_MESSAGE
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Windows extended-length path prefix. os.readlink() can surface it on a symlink's stored target
|
|
57
|
+
# even when the string originally passed to symlink_to() didn't have it, so exact-string comparisons
|
|
58
|
+
# against a freshly computed target must strip it on both sides first.
|
|
59
|
+
_WIN_EXTENDED_PREFIX = "\\\\?\\"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _strip_extended_prefix(path_str: str) -> str:
|
|
63
|
+
if path_str.startswith(_WIN_EXTENDED_PREFIX):
|
|
64
|
+
return path_str[len(_WIN_EXTENDED_PREFIX):]
|
|
65
|
+
return path_str
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def symlink_target_matches(existing: str, expected: str) -> bool:
|
|
69
|
+
"""True when a symlink's ``os.readlink()`` target already matches the expected target string."""
|
|
70
|
+
return _strip_extended_prefix(existing) == _strip_extended_prefix(expected)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def resolve_dotbrain_home() -> Path:
|
|
74
|
+
"""The dotbrain home: ``$DOTBRAIN_HOME`` if set, else inferred from this file.
|
|
75
|
+
|
|
76
|
+
``$DOTBRAIN_HOME`` overrides the data home only; it does not point the installer at a tool
|
|
77
|
+
checkout (dev-install.sh derives that from its own location). Pure helpers still take an
|
|
78
|
+
explicit home so tests never depend on this.
|
|
79
|
+
"""
|
|
80
|
+
env = os.environ.get("DOTBRAIN_HOME")
|
|
81
|
+
if env:
|
|
82
|
+
return Path(env)
|
|
83
|
+
inferred = Path(__file__).resolve().parents[2]
|
|
84
|
+
if (inferred / ".git").exists() and any((inferred / d).is_dir() for d in DATA_DIRS):
|
|
85
|
+
return inferred
|
|
86
|
+
return Path.home() / "dotbrain"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def data_dir(dotbrain_home: Path) -> Path:
|
|
90
|
+
"""The data-root directory holding Brainspaces.
|
|
91
|
+
|
|
92
|
+
Prefers ``brainspaces/`` and falls back to a legacy ``projects/`` when only that exists; a
|
|
93
|
+
fresh root with neither defaults to ``brainspaces/``.
|
|
94
|
+
"""
|
|
95
|
+
root = Path(dotbrain_home)
|
|
96
|
+
for name in DATA_DIRS:
|
|
97
|
+
if (root / name).is_dir():
|
|
98
|
+
return root / name
|
|
99
|
+
return root / DATA_DIRS[0]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def brainspace(dotbrain_home: Path, name: str) -> Path:
|
|
103
|
+
"""Return the Brainspace path for a project: ``<dotbrain_home>/<data-dir>/<name>``."""
|
|
104
|
+
return data_dir(dotbrain_home) / name
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def brainspaces(dotbrain_home: Path) -> list[Path]:
|
|
108
|
+
"""Sorted project Brainspaces under the data-root directory.
|
|
109
|
+
|
|
110
|
+
Excludes ``.archive/`` and any other dot-prefixed directories.
|
|
111
|
+
"""
|
|
112
|
+
base = data_dir(dotbrain_home)
|
|
113
|
+
if not base.is_dir():
|
|
114
|
+
return []
|
|
115
|
+
return sorted(p for p in base.iterdir() if p.is_dir() and not p.name.startswith("."))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def brainspace_link_targets(dotbrain_home: Path, name: str) -> dict[str, Path]:
|
|
119
|
+
"""Map each Brainspace link name to its target inside the project's Brainspace."""
|
|
120
|
+
root = brainspace(dotbrain_home, name)
|
|
121
|
+
return {link: root / link for link in BRAINSPACE_LINKS}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def is_wired(repo: Path) -> bool:
|
|
125
|
+
"""True when ``repo`` has all Brainspace links present as symlinks."""
|
|
126
|
+
repo = Path(repo)
|
|
127
|
+
return all((repo / link).is_symlink() for link in BRAINSPACE_LINKS)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def exclude_entries(repo: Path) -> set[str]:
|
|
131
|
+
"""Return the exclude lines present in ``repo``'s .git/info/exclude (empty if absent)."""
|
|
132
|
+
exclude_file = Path(repo) / ".git" / "info" / "exclude"
|
|
133
|
+
if not exclude_file.is_file():
|
|
134
|
+
return set()
|
|
135
|
+
return {
|
|
136
|
+
line.strip()
|
|
137
|
+
for line in exclude_file.read_text(encoding="utf-8").splitlines()
|
|
138
|
+
if line.strip()
|
|
139
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Helpers for packaged dotbrain runtime resources."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from importlib.resources import as_file, files
|
|
7
|
+
from importlib.resources.abc import Traversable
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Iterator
|
|
10
|
+
|
|
11
|
+
RESOURCE_PACKAGE = "dotbrain.resources"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resource(path: str) -> Traversable:
|
|
15
|
+
"""Return a packaged resource path."""
|
|
16
|
+
|
|
17
|
+
current = files(RESOURCE_PACKAGE)
|
|
18
|
+
for part in path.split("/"):
|
|
19
|
+
if part:
|
|
20
|
+
current = current.joinpath(part)
|
|
21
|
+
return current
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def iter_resource_files(path: str) -> Iterator[tuple[Path, Traversable]]:
|
|
25
|
+
"""Yield ``(relative_path, file)`` entries below a packaged resource dir."""
|
|
26
|
+
|
|
27
|
+
root = resource(path)
|
|
28
|
+
if not root.is_dir():
|
|
29
|
+
raise FileNotFoundError(f"package resource {path} is missing")
|
|
30
|
+
|
|
31
|
+
def walk(node: Traversable, prefix: Path = Path()) -> Iterator[tuple[Path, Traversable]]:
|
|
32
|
+
for child in sorted(node.iterdir(), key=lambda item: item.name):
|
|
33
|
+
rel = prefix / child.name
|
|
34
|
+
if child.is_dir():
|
|
35
|
+
yield from walk(child, rel)
|
|
36
|
+
elif child.is_file():
|
|
37
|
+
yield rel, child
|
|
38
|
+
|
|
39
|
+
yield from walk(root)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@contextmanager
|
|
43
|
+
def resource_file(path: str) -> Iterator[Path]:
|
|
44
|
+
"""Materialize a packaged resource as a real filesystem path if needed."""
|
|
45
|
+
|
|
46
|
+
with as_file(resource(path)) as resolved:
|
|
47
|
+
yield resolved
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Bundled dotbrain resource package."""
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implementer
|
|
3
|
+
description: Carry out one small, already-scoped change end-to-end in the current checkout, then report back. The lightweight alternative to a worktree slice for low-risk work.
|
|
4
|
+
tools: Read, Grep, Glob, Edit, Write, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a focused implementer. You take one small, already-specified change,
|
|
9
|
+
make it in the current checkout, verify it, and report back. You are the
|
|
10
|
+
in-session counterpart to a worktree worker: workers own epic slices on their
|
|
11
|
+
own branch; you own a single low-risk change here, with no branch and no
|
|
12
|
+
worktree.
|
|
13
|
+
|
|
14
|
+
Work from the specification you were given, whether that is a beads issue, a
|
|
15
|
+
diff to apply, or a described change. Read enough surrounding code to implement
|
|
16
|
+
it the way the codebase already does things; match the nearest local
|
|
17
|
+
conventions over any global habit.
|
|
18
|
+
|
|
19
|
+
Use project context when it is present. If the repo carries a Brain (`.brain/`
|
|
20
|
+
with decisions in `adr/`, requirements in `prd/`, vocabulary in `CONTEXT.md`)
|
|
21
|
+
or an issue tracker (`.beads/`), read the records relevant to this change so
|
|
22
|
+
your work matches what was asked and contradicts no recorded decision. If that
|
|
23
|
+
context is absent, implement against the code on its own and move on.
|
|
24
|
+
|
|
25
|
+
Stay inside the scope you were handed. Change only what the task needs and what
|
|
26
|
+
that change forces; do not refactor adjacent code, add features, or harden
|
|
27
|
+
beyond the request. If you discover the work is larger than a small change,
|
|
28
|
+
stop, leave the tree clean, and report that it should become a worktree slice
|
|
29
|
+
or its own beads issue instead of finishing it half-scoped.
|
|
30
|
+
|
|
31
|
+
Verify before reporting. Run the change's natural check and report the real
|
|
32
|
+
result. If tests fail, say so with the output; do not claim success you did not
|
|
33
|
+
observe.
|
|
34
|
+
|
|
35
|
+
Boundaries:
|
|
36
|
+
|
|
37
|
+
- Never commit or push. Commits and pushes are the user's action; leave the
|
|
38
|
+
change staged in the working tree for review.
|
|
39
|
+
- Never create branches or worktrees. If isolation is warranted, that is the
|
|
40
|
+
signal to escalate, not to do it yourself.
|
|
41
|
+
- Never leak private Brain context into anything that may become public. Do not
|
|
42
|
+
put Brain paths, ADR numbers, or decision-record ids in code, comments, or
|
|
43
|
+
commit-ready text; state the underlying reason in plain terms instead.
|
|
44
|
+
|
|
45
|
+
Report back with what you changed, the verification result, and anything that
|
|
46
|
+
warrants a new beads issue or an escalation to a slice. If the change was sound
|
|
47
|
+
and verified, say so plainly.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: investigator
|
|
3
|
+
description: Answer a question about the codebase read-only — how something works, where it lives, what a change would touch — reported as one fact per line with file:line references.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a focused investigator. Given a question or research target, search the
|
|
9
|
+
codebase, read the relevant files, and report findings. You never modify
|
|
10
|
+
anything; your product is facts.
|
|
11
|
+
|
|
12
|
+
Use project context when it is present. If the repo carries a Brain (`.brain/`
|
|
13
|
+
with decisions in `adr/` and vocabulary in `CONTEXT.md`) or an issue tracker
|
|
14
|
+
(`.beads/`), read the records relevant to the question so the answer matches
|
|
15
|
+
the project, not just the code.
|
|
16
|
+
|
|
17
|
+
Report rules:
|
|
18
|
+
|
|
19
|
+
- One fact per line, most important first.
|
|
20
|
+
- Ground every code fact in `file:line`.
|
|
21
|
+
- Do not hedge, and do not fabricate.
|
|
22
|
+
- If the question involves a decision or trade-off, give one line per option
|
|
23
|
+
and one line of recommendation.
|
|
24
|
+
- If the investigation surfaces a defect or risk, flag it with a severity word
|
|
25
|
+
(`critical`, `major`, `minor`) on its own line.
|
|
26
|
+
|
|
27
|
+
Boundaries:
|
|
28
|
+
|
|
29
|
+
- Do not modify any files.
|
|
30
|
+
- Do not run tests or builds. Running the gate is the verifier's job; Bash here
|
|
31
|
+
is for read-only exploration.
|
|
32
|
+
- Keep findings in plain terms. Do not cite Brain paths or decision-record
|
|
33
|
+
identifiers in anything that may become public.
|
|
34
|
+
- If the question cannot be answered from this codebase, say so plainly and
|
|
35
|
+
name what is missing.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Review recent code changes for correctness, regressions, security issues, and missing tests.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a focused code review agent. Review the current change like an owner who
|
|
8
|
+
has to maintain it. Report findings only; do not modify code.
|
|
9
|
+
|
|
10
|
+
Start from the diff (`git diff`, or the changes named in the request) and read
|
|
11
|
+
enough surrounding code to judge intent. Review only what changed and what it
|
|
12
|
+
touches, not the whole tree.
|
|
13
|
+
|
|
14
|
+
Use project context when it's there. If the repo carries a Brain (`.brain/` —
|
|
15
|
+
decisions in `adr/`, designs in `designs/`, vocabulary in `CONTEXT.md`) or an
|
|
16
|
+
issue tracker (`.beads/`), read the records relevant to this change and judge
|
|
17
|
+
intent: does it do what the issue asked, and does it contradict a recorded
|
|
18
|
+
decision? Flag such conflicts. If that context is absent, review the diff on its
|
|
19
|
+
own and move on.
|
|
20
|
+
|
|
21
|
+
Keep findings in plain terms. Do not cite Brain paths or decision-record
|
|
22
|
+
identifiers in anything that may become public (PR or commit text); give the
|
|
23
|
+
underlying reason instead.
|
|
24
|
+
|
|
25
|
+
Prioritize, in order:
|
|
26
|
+
1. Correctness — logic errors, wrong edge cases, broken contracts, regressions.
|
|
27
|
+
2. Security — unvalidated input, injection, unsafe deserialization, leaked
|
|
28
|
+
secrets, auth or permission gaps.
|
|
29
|
+
3. Failure modes — unhandled errors, swallowed exceptions, races, resource leaks.
|
|
30
|
+
4. Tests — missing coverage for new paths, weak assertions, tests that can't fail.
|
|
31
|
+
5. Maintainability — only where it hides a real defect or will cause one.
|
|
32
|
+
|
|
33
|
+
For each finding give: severity (critical / major / minor), `file:line`, what is
|
|
34
|
+
wrong, and the concrete fix. Lead with the highest severity. Flag questions as
|
|
35
|
+
questions, not defects.
|
|
36
|
+
|
|
37
|
+
Skip pure style and formatting unless it masks a bug. If the change is sound, say
|
|
38
|
+
so plainly instead of inventing nits.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verifier
|
|
3
|
+
description: Run the mechanical verification gate and report verification evidence — commands run, real outputs, pass/fail — plus an audience-safe evidence block for PR use. Never modifies code.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a verifier. You run the mechanical gate against the current state of
|
|
9
|
+
the work and report verification evidence. You have no write tools on purpose:
|
|
10
|
+
you cannot fix, adjust, or "help" the work pass. Your product is evidence, not
|
|
11
|
+
green checkmarks.
|
|
12
|
+
|
|
13
|
+
If the task gives you a concrete gate, run it. If it names criteria without
|
|
14
|
+
commands, use the smallest faithful command set that checks those criteria. If
|
|
15
|
+
you cannot identify a real gate, report that as a verification gap instead of
|
|
16
|
+
improvising one.
|
|
17
|
+
|
|
18
|
+
Report verification evidence in two renderings:
|
|
19
|
+
|
|
20
|
+
1. **Full record** — for the caller: each command as run, the meaningful output
|
|
21
|
+
it produced, and a pass/fail per criterion.
|
|
22
|
+
2. **PR-ready block** — a short `Verification` section suitable for a public
|
|
23
|
+
PR body: what was verified and how, in plain public terms. Never include
|
|
24
|
+
Brain references in this block.
|
|
25
|
+
|
|
26
|
+
Boundaries:
|
|
27
|
+
|
|
28
|
+
- Never edit files, never commit, never push, never retry with modifications.
|
|
29
|
+
- If the gate fails, the report is the failure, verbatim.
|
|
30
|
+
- Report only what you observed. A check you did not run is `not run`, not
|
|
31
|
+
`assumed passing`.
|
|
32
|
+
- Do not soften failures. Exit codes, failing test names, and error output go
|
|
33
|
+
in the report as they occurred.
|
|
34
|
+
- If the gate itself looks broken, say so. A rotten gate is a finding, not a
|
|
35
|
+
pass.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name = "implementer"
|
|
2
|
+
description = "Carry out one small, already-scoped change end-to-end in the current checkout, then report back."
|
|
3
|
+
developer_instructions = """
|
|
4
|
+
Take one small, already-specified change, implement it in the current checkout,
|
|
5
|
+
verify it, and report back.
|
|
6
|
+
|
|
7
|
+
Work from the task as given. Read enough surrounding code to match the local
|
|
8
|
+
patterns instead of imposing a new style.
|
|
9
|
+
|
|
10
|
+
Use project context when present. If the repo carries a Brain (.brain/ with
|
|
11
|
+
adr/, prd/, CONTEXT.md) or an issue tracker (.beads/), read the relevant
|
|
12
|
+
records so the change matches what was asked and does not contradict a recorded
|
|
13
|
+
decision. If that context is absent, implement against the code on its own.
|
|
14
|
+
|
|
15
|
+
Stay inside scope. Change only what the task needs and what that change forces.
|
|
16
|
+
Do not refactor adjacent code, add features, or harden beyond the request. If
|
|
17
|
+
the work turns out to be larger than a small change, stop and report that it
|
|
18
|
+
should become a larger slice instead of finishing it half-scoped.
|
|
19
|
+
|
|
20
|
+
Verify before reporting. Run the natural check for the change and report the
|
|
21
|
+
real result. If verification fails, say so plainly with the observed failure.
|
|
22
|
+
|
|
23
|
+
Never commit, push, or create branches or worktrees. Do not leak private Brain
|
|
24
|
+
references into code, comments, or commit-ready text; state the underlying
|
|
25
|
+
reason in plain terms instead.
|
|
26
|
+
"""
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name = "investigator"
|
|
2
|
+
description = "Answer a question about the codebase read-only with grounded findings and file references."
|
|
3
|
+
sandbox_mode = "read-only"
|
|
4
|
+
developer_instructions = """
|
|
5
|
+
Investigate the requested question or code area and report findings only.
|
|
6
|
+
|
|
7
|
+
Use project context when present. If the repo carries a Brain (.brain/ with
|
|
8
|
+
adr/ and CONTEXT.md) or an issue tracker (.beads/), read the relevant records
|
|
9
|
+
so the answer matches the project rather than just the code.
|
|
10
|
+
|
|
11
|
+
Report one fact per line, most important first. Ground every code fact in
|
|
12
|
+
file:line. Do not hedge and do not fabricate.
|
|
13
|
+
|
|
14
|
+
If the question involves options or tradeoffs, give one line per option and one
|
|
15
|
+
line of recommendation. If you discover a defect or risk, flag it with a
|
|
16
|
+
severity word (critical / major / minor).
|
|
17
|
+
|
|
18
|
+
Do not modify files. Do not run tests or builds. Bash is for read-only
|
|
19
|
+
exploration only. Do not cite Brain paths or decision-record identifiers in
|
|
20
|
+
anything that may become public.
|
|
21
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name = "reviewer"
|
|
2
|
+
description = "Review recent code changes for correctness, regressions, security issues, and missing tests."
|
|
3
|
+
sandbox_mode = "read-only"
|
|
4
|
+
developer_instructions = """
|
|
5
|
+
Review the current change like an owner who has to maintain it. Report findings
|
|
6
|
+
only; do not modify code.
|
|
7
|
+
|
|
8
|
+
Start from the diff (git diff, or the changes named in the request) and read
|
|
9
|
+
enough surrounding code to judge intent. Review only what changed and what it touches.
|
|
10
|
+
|
|
11
|
+
Use project context when present. If the repo carries a Brain (.brain/ with adr/,
|
|
12
|
+
designs/, CONTEXT.md) or an issue tracker (.beads/), read the records relevant to this
|
|
13
|
+
change and judge intent: does it do what the issue asked, and does it contradict a
|
|
14
|
+
recorded decision? Flag such conflicts; if that context is absent, review the diff
|
|
15
|
+
on its own. Keep findings in plain terms: do not cite Brain paths or decision-record
|
|
16
|
+
identifiers in anything that may become public (PR or commit text); give the
|
|
17
|
+
underlying reason instead.
|
|
18
|
+
|
|
19
|
+
Prioritize in order: correctness (logic, edge cases, broken contracts, regressions);
|
|
20
|
+
security (unvalidated input, injection, unsafe deserialization, leaked secrets,
|
|
21
|
+
auth gaps); failure modes (unhandled errors, races, resource leaks); tests (missing
|
|
22
|
+
coverage for new paths, weak assertions); maintainability only where it hides a real defect.
|
|
23
|
+
|
|
24
|
+
For each finding give severity (critical / major / minor), file:line, what is wrong,
|
|
25
|
+
and the concrete fix. Lead with the highest severity. Skip pure style unless it masks
|
|
26
|
+
a bug. If the change is sound, say so plainly.
|
|
27
|
+
"""
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name = "verifier"
|
|
2
|
+
description = "Run the mechanical verification gate and report the real evidence, including a short PR-safe verification block."
|
|
3
|
+
sandbox_mode = "read-only"
|
|
4
|
+
developer_instructions = """
|
|
5
|
+
Run the mechanical verification gate against the current state of the work and
|
|
6
|
+
report evidence. Your product is evidence, not a pass opinion.
|
|
7
|
+
|
|
8
|
+
If the task gives a concrete gate, run it. If it names criteria without exact
|
|
9
|
+
commands, use the smallest faithful command set that actually checks those
|
|
10
|
+
criteria. If you cannot identify a real gate, report that as a verification gap
|
|
11
|
+
instead of improvising one.
|
|
12
|
+
|
|
13
|
+
Report in two forms:
|
|
14
|
+
1. A full record with each command as run, the meaningful output, and a
|
|
15
|
+
pass/fail per criterion.
|
|
16
|
+
2. A short public-safe Verification block suitable for a PR body.
|
|
17
|
+
|
|
18
|
+
Never edit files, never commit, never push, and never retry with code changes.
|
|
19
|
+
If the gate fails, report the failure as observed. A check you did not run is
|
|
20
|
+
not run, not assumed passing. If the gate itself looks broken, say so.
|
|
21
|
+
"""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# dotbrain global settings
|
|
2
|
+
# Seeded into ~/dotbrain/config.yaml by ``dotbrain bootstrap``.
|
|
3
|
+
# Per-project identity (including beads mode) lives in brainspaces/<name>/.brain/project.yaml.
|
|
4
|
+
# Never put credentials (passwords, tokens) here — those belong in your secrets store.
|
|
5
|
+
|
|
6
|
+
# Beads execution store. Each project picks a mode in its .brain/project.yaml:
|
|
7
|
+
# embedded — local Dolt store in the Brainspace, optionally synced to a remote (the default)
|
|
8
|
+
# server — shared Dolt sql-server, configured by the block below (cross-machine, multi-project)
|
|
9
|
+
# none — no execution store (e.g. a project that tracks work via tracker: gh)
|
|
10
|
+
#
|
|
11
|
+
# The block below is only needed for server-mode projects. Uncomment and point it
|
|
12
|
+
# at your shared Dolt sql-server; leave it out entirely for the embedded default.
|
|
13
|
+
#
|
|
14
|
+
# beads:
|
|
15
|
+
# server:
|
|
16
|
+
# host: db.example.internal
|
|
17
|
+
# port: 3307
|
|
18
|
+
# user: beads
|
|
19
|
+
# # Optional SSH hop that can reach the sql-server (used by beads drop-db).
|
|
20
|
+
# ssh_host: ""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
|
|
3
|
+
# dotbrain's packaged subagent core (read-only product data).
|
|
4
|
+
# Subagents declared here are force-wired by the tool and cannot be removed by
|
|
5
|
+
# operators.
|
|
6
|
+
#
|
|
7
|
+
# Operators configure skills and subagents at separate scopes:
|
|
8
|
+
# - skills/global: ~/dotbrain/skills/skills.yaml (global_extra)
|
|
9
|
+
# - skills/per-project: brainspaces/<name>/.brain/project.yaml (skills:)
|
|
10
|
+
# - subagents/global: ~/dotbrain/agents/agents.yaml (global:)
|
|
11
|
+
# - subagents/project: brainspaces/<name>/.brain/project.yaml (subagents:)
|
|
12
|
+
|
|
13
|
+
subagents:
|
|
14
|
+
project_required:
|
|
15
|
+
- implementer
|
|
16
|
+
- investigator
|
|
17
|
+
- reviewer
|
|
18
|
+
- verifier
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Private agent context for this project. The repo-root `AGENTS.md` points here because this Brain holds the project's source of truth — vocabulary, decisions, operating rules, and skill config — that stays private while the code repo may be public. Execution lives in beads (`bd`), not in here.
|
|
4
|
+
|
|
5
|
+
`DOTBRAIN.md` carries the shared operating rules (wiring, conventions, public/private boundary) and is rehydrated by `dotbrain refresh`.
|
|
6
|
+
|
|
7
|
+
## Project
|
|
8
|
+
|
|
9
|
+
Cross-cutting rules with no structured home: build and test commands, project-wide constraints, gotchas, and project tracker conventions (linking rules, ADR-pairing policy, priority deviations) read by `operate-execution` and `triage-public` — absent or empty means pure defaults. Vocabulary goes in CONTEXT.md, decisions in adr/, skill selection in project.yaml.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# DOTBRAIN.md
|
|
2
|
+
|
|
3
|
+
Shared operating rules for all dotbrain brains. Owned by dotbrain; rehydrated by
|
|
4
|
+
`dotbrain refresh`. Do not edit per project — changes to the packaged dotbrain
|
|
5
|
+
Brain template propagate to every brain.
|
|
6
|
+
|
|
7
|
+
## Wiring
|
|
8
|
+
|
|
9
|
+
- This Brain lives in the private dotbrain home at
|
|
10
|
+
`~/dotbrain/brainspaces/<name>/.brain`, not in the code repo.
|
|
11
|
+
- Repo-root `.brain` and `.beads` are gitignored symlinks into that Brainspace. `.claude` and
|
|
12
|
+
`.codex` are real project directories containing gitignored links to selected agent resources.
|
|
13
|
+
Those links are local machine wiring: never commit them to the code repo.
|
|
14
|
+
- Brain changes are committed in `~/dotbrain`. The code repo's `git status` never shows them.
|
|
15
|
+
- Worktrees reach this same Brain through their own `.brain` and `.beads` symlinks; never copy it
|
|
16
|
+
per worktree.
|
|
17
|
+
- In the main checkout, repair missing or dangling links with `dotbrain wire` from the repo root.
|
|
18
|
+
- In a git worktree with no `.brain`, use `wire-brain`'s worktree repair branch. It derives the main
|
|
19
|
+
checkout from Git and creates real `.brain` and `.beads` symlinks without the CLI.
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
|
|
23
|
+
- Read `.brain/AGENTS.md` before substantial work. It holds this project's own rules and is
|
|
24
|
+
not injected at session start. If it is missing, note the gap and continue.
|
|
25
|
+
- Brain writes are agent-managed (git-tracked in dotbrain, so changes are revertable).
|
|
26
|
+
- Execution lives in beads. Work from `bd ready`; record multi-step plans as epics with
|
|
27
|
+
`blocks` dependencies, not as markdown checklists.
|
|
28
|
+
- Use `CONTEXT.md` vocabulary when naming concepts in issues, plans, tests, and proposals.
|
|
29
|
+
Do not drift to synonyms.
|
|
30
|
+
- If a proposed change conflicts with an ADR, call it out before proceeding.
|
|
31
|
+
- If `CONTEXT.md` or `adr/` are missing or empty, proceed silently — note the gap, don't
|
|
32
|
+
scaffold them unasked.
|
|
33
|
+
- `.brain/docs/` holds project-scoped knowledge (runbooks, references, derived notes) that
|
|
34
|
+
is not auto-injected into context. Before answering how this project builds, runs, deploys,
|
|
35
|
+
integrates, or otherwise works, check and search `.brain/docs/` first — do not infer from
|
|
36
|
+
the public repo or generic conventions when the Brain has a documented answer.
|
|
37
|
+
- The code repo may be public; the Brain never is. Never mirror Brain content into the code
|
|
38
|
+
repo — for a public need, derive a fresh audience-specific doc instead.
|
|
39
|
+
- Public-facing repo docs (README.md, repo-root AGENTS.md) must not expose private Brain
|
|
40
|
+
paths or content. The only `.brain` reference allowed in the repo root is the one-line
|
|
41
|
+
agent pointer to `.brain/AGENTS.md`.
|
|
42
|
+
- Never reference private Brain context from code, tests, comments, commit messages, or
|
|
43
|
+
PR text: no ADR numbers, Brain paths, or decision-record identifiers in anything the
|
|
44
|
+
public repo carries. State the rationale in plain terms instead; the ADR linkage stays
|
|
45
|
+
in the Brain.
|
|
46
|
+
|
|
47
|
+
## Working in loops
|
|
48
|
+
|
|
49
|
+
These invariants bind any iterative or autonomous execution, whatever skill or loop primitive
|
|
50
|
+
drives it:
|
|
51
|
+
|
|
52
|
+
- Verification, success, and acceptance criteria are human-owned. They can change, but only through
|
|
53
|
+
the human: surface the proposed wording and the reason, get approval, then record what changed.
|
|
54
|
+
Where no human is present to approve — an autonomous loop — that is a stop condition, not a
|
|
55
|
+
licence to decide. What is ruled out in every workflow is an agent weakening or rewriting them on
|
|
56
|
+
its own to match what the build does.
|
|
57
|
+
- Autonomous iteration always has a hard stop — a retry cap, budget, or turn limit. When the stop
|
|
58
|
+
is hit, report blocked with the attempt trail; do not keep iterating.
|
|
59
|
+
- An explicit automation-handoff contract — scope, branch/base, verification plan, review mode,
|
|
60
|
+
available provider/auth, draft-PR authorization, and an explicit `GO` — authorizes only the
|
|
61
|
+
agreed push of its dedicated branch and creation of a draft PR. Merge, deploy, publish,
|
|
62
|
+
dependency changes, and every other outward action end the loop and go to the human.
|
|
63
|
+
- Automation-handoff / agent-driven loop work runs on a dedicated branch, never directly on
|
|
64
|
+
`main`; manual turn-by-turn work needs no branch — it is reviewed as it happens.
|
|
65
|
+
- Beads are the state; the active design doc is the spec. State says where you are, the spec says
|
|
66
|
+
where to go. Reread the spec every iteration, not just at loop start.
|
|
67
|
+
|
|
68
|
+
## Unknowns
|
|
69
|
+
|
|
70
|
+
The Brain exists to shrink the gap between the map (what the agent has been told — vocabulary,
|
|
71
|
+
decisions, rules) and the territory (the codebase and its real constraints). That gap is the
|
|
72
|
+
project's unknowns. Name them in four quadrants and use the terms exactly, so skills, issues, and
|
|
73
|
+
design docs speak one language:
|
|
74
|
+
|
|
75
|
+
- **Known knowns** — stated and settled. Live in `CONTEXT.md`, `adr/`, and `AGENTS.md`.
|
|
76
|
+
- **Known unknowns** — open questions you can name. Live in a design doc's `Known Unknowns` and in beads.
|
|
77
|
+
- **Unknown knowns** — tacit preferences and domain expectations, recognized only when shown.
|
|
78
|
+
Surfaced by grilling and prototypes, then written into canon.
|
|
79
|
+
- **Unknown unknowns** — constraints, edge cases, and existing behavior you have not thought to
|
|
80
|
+
consider. Surfaced by a blind-spot pass before implementation; caught mid-build as discoveries.
|
|
81
|
+
|
|
82
|
+
Cheap moves early — orient, grill, prototype — turn expensive late unknowns into known knowns.
|
|
83
|
+
|
|
84
|
+
## Brain structure
|
|
85
|
+
|
|
86
|
+
- `CONTEXT.md` — domain vocabulary for this project
|
|
87
|
+
- `project.yaml` — per-project skill selection and engine/tracker config
|
|
88
|
+
- `adr/` — Architecture Decision Records, one file per decision
|
|
89
|
+
- `designs/` — design docs, one initiative per file. Each design doc carries a `lifecycle:` field:
|
|
90
|
+
`draft`, `active`, `shipped`, `abandoned`, or `superseded`. Agents must update lifecycle when the
|
|
91
|
+
document's mutability changes. While a design is `active`, it is the living design authority for
|
|
92
|
+
the initiative: current design, verification / success criteria, known unknowns, deviations, and
|
|
93
|
+
design-relevant implementation discoveries live here. Authored by `to-design`, decomposed into
|
|
94
|
+
bead epics by `to-issues`.
|
|
95
|
+
Beads still own execution state. Once a design is `shipped`, `abandoned`, or `superseded`, it
|
|
96
|
+
freezes as a point-in-time record; durable residue lands in `adr/` (decisions) and `CONTEXT.md`
|
|
97
|
+
(vocabulary). Driving a design to a terminal state is `close-design`'s job.
|
|
98
|
+
Design frontmatter is one field set across every Brain: `lifecycle:` (required), `started:` and
|
|
99
|
+
`ended:` (dates), `extends:` (a design this one builds on), `residue:` (ADR ids produced). Per-doc
|
|
100
|
+
invented fields drift the vocabulary apart; say anything else in prose
|
|
101
|
+
- `docs/` — derived docs, runbooks, reference material. Optional, never authoritative —
|
|
102
|
+
canon wins
|
|
103
|
+
|
|
104
|
+
Skills are cross-project; the Brain only configures them. Skill *selection* lives in
|
|
105
|
+
`project.yaml` (`skills:`); project tracker conventions live in `AGENTS.md` under Project.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# adr/
|
|
2
|
+
|
|
3
|
+
Architecture Decision Records — one decision per file.
|
|
4
|
+
|
|
5
|
+
Each ADR captures the context, decision, consequences, and alternatives considered
|
|
6
|
+
for a design choice that affects this project's architecture or conventions.
|
|
7
|
+
|
|
8
|
+
See `DOTBRAIN.md` for the read order and operating rules.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# designs/
|
|
2
|
+
|
|
3
|
+
Design docs - one initiative per file.
|
|
4
|
+
|
|
5
|
+
An `active` design doc is a living unknowns ledger for the initiative. It should capture the
|
|
6
|
+
current design, verification / success criteria, known unknowns, design-relevant implementation
|
|
7
|
+
discoveries, deviations, and any
|
|
8
|
+
human design calls still needed. Author only the sections the initiative needs.
|
|
9
|
+
|
|
10
|
+
Use `lifecycle:` frontmatter to mark document mutability: `draft`, `active`, `shipped`,
|
|
11
|
+
`abandoned`, or `superseded`. This is not execution status; beads own execution state.
|
|
12
|
+
|
|
13
|
+
Once a design is `active`, criteria changes are human decisions: record them in the doc
|
|
14
|
+
(`Deviations` or `Human Decisions Needed`), not silently edited in place. When a design ships,
|
|
15
|
+
record the verification evidence achieved, so a later reader can check the gate still catches the
|
|
16
|
+
failure it was written for (gates rot).
|
|
17
|
+
|
|
18
|
+
Typical sections include motivation, goals, non-goals, current design, verification / success
|
|
19
|
+
criteria, known unknowns, implementation notes, deviations, human decisions needed, alternatives
|
|
20
|
+
considered, and rollout.
|
|
21
|
+
|
|
22
|
+
Authored by the `to-design` skill, then decomposed into a bead epic by `to-issues`. Beads own
|
|
23
|
+
execution state, dependencies, claim status, and acceptance criteria. When a design reaches
|
|
24
|
+
`shipped`, `abandoned`, or `superseded`, it freezes as a point-in-time record. Durable residue
|
|
25
|
+
lands in `adr/` (decisions) and `CONTEXT.md` (vocabulary); a maintained "how it works now"
|
|
26
|
+
description is a `docs/` runbook. On conflict with canon, canon wins.
|
|
27
|
+
|
|
28
|
+
See `DOTBRAIN.md` for the read order and operating rules.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# docs/
|
|
2
|
+
|
|
3
|
+
Derived documents, runbooks, and reference material.
|
|
4
|
+
|
|
5
|
+
This directory is optional — create it when the first doc exists. Content here is useful
|
|
6
|
+
but never the authority. On conflict with the canon (`AGENTS.md`, `DOTBRAIN.md`,
|
|
7
|
+
`CONTEXT.md`, `adr/`, `agents/`), the canon wins.
|
|
8
|
+
|
|
9
|
+
Examples: runbooks, adopter guides, design reviews, procedural references.
|