Wolfcastle is a Go CLI with 20 internal packages. Here's the map:
| Package | What it does |
|---|---|
internal/state |
Types, I/O, mutations, navigation, propagation for the distributed state files |
internal/daemon |
Iteration loop, stages, retry, signal handling, spinner |
internal/pipeline |
Prompt assembly, fragment resolution, script reference filtering |
internal/invoke |
Model CLI subprocess execution, marker detection, terminal restoration |
internal/config |
Three-tier config loading, deep merge, validation |
internal/validate |
Structural validation engine: 28 validation categories, multi-pass deterministic repair, JSON recovery |
internal/tree |
Address parsing, slug validation, filesystem path resolution |
internal/logging |
Per-iteration NDJSON log files, rotation, retention |
internal/output |
JSON envelope formatting, PrintHuman, spinner animation |
internal/project |
Scaffolding (init), embedded templates, project creation |
internal/archive |
Timestamped archive entries for completed nodes |
internal/errors |
Typed error categories (Config, State, Invocation, Navigation) |
internal/clock |
Time abstraction for deterministic testing |
internal/selfupdate |
Binary self-update mechanism |
internal/git |
Git operations behind a Provider interface for real repositories or test stubs |
internal/knowledge |
Per-namespace codebase knowledge files (add, show, edit, prune, token budget) |
internal/logrender |
Log record rendering (summaries, thoughts, session views) |
internal/signals |
Canonical OS signal set (SIGINT, SIGTERM, SIGTSTP) for graceful shutdown |
internal/tierfs |
Three-tier file resolution (base < custom < local) and tier name registry |
internal/testutil |
Shared test helpers |
The cmd/ directory mirrors the CLI surface: cmd/daemon/ (start, stop, log, status), cmd/task/ (add, claim, complete, block, unblock, deliverable, scope), cmd/audit/ (breadcrumb, gap, scope, summary, etc.), cmd/config/ (show, set, unset, append, remove, validate), cmd/orchestrator/, cmd/inbox/, cmd/project/, cmd/knowledge/ (add, show, edit, prune). Shared command utilities live in cmd/cmdutil/.
git clone https://github.com/dorkusprime/wolfcastle.git
cd wolfcastle
make test
All 3,000+ tests should pass. If they do, you're ready to contribute.
- Create a file in the appropriate
cmd/subdirectory (e.g.,cmd/task/newcmd.go) - Define a
newXxxCmd(app *cmdutil.App) *cobra.Commandfunction - Register it in the subdirectory's
register.gowith flags and completions - Add the command to the execute stage's
AllowedCommandsininternal/config/config.goif models should use it - Add the command to
internal/project/templates/prompts/script-reference.md - Write a doc page in
docs/humans/cli/ - Write tests in the same package
If the command generates a file (like adr create or spec create), use the template system rather than building content with string concatenation or fmt.Sprintf:
- Create a
.tmplfile underinternal/project/templates/artifacts/using Gotext/templatesyntax - Define a typed context struct for the template variables (e.g.,
ADRContext,SpecContext) ininternal/pipeline/template_data.go - Render via
PromptRepository.RenderToFile(tmplName, data, destPath), which resolves the template through the three-tier system so users can override the format - Add a snapshot test that renders the template with representative data and compares against a golden file
- Add a category constant in
internal/validate/types.go - Add the check in
internal/validate/engine.goinsideValidateAll - If the fix is deterministic, add it in
internal/validate/fix.go - Write tests that trigger the validation and verify the fix
- Update the structural validation spec in
docs/specs/
go test -race ./...must pass with zero failures- Use
t.Parallel()on every test - Use
t.Helper()on test helpers - Table-driven tests for multiple similar cases
- Test error paths, not just happy paths
- Integration tests in
test/integration/exercise real command sequences - Smoke tests in
test/smoke/verify the binary builds and runs
- Branch from
main(always pull first) - CI must pass: build, vet, gofmt, test (race detector), lint, cross-compile
- PRs auto-merge when CI passes
- Keep commits focused. One concern per commit.
graph TD
subgraph CLI["cmd/ (CLI surface)"]
root[cmd]
cmdutil[cmd/cmdutil]
cmddaemon[cmd/daemon]
cmdtask[cmd/task]
cmdaudit[cmd/audit]
cmdconfig[cmd/config]
cmdinbox[cmd/inbox]
cmdproject[cmd/project]
cmdorch[cmd/orchestrator]
cmdknow[cmd/knowledge]
end
subgraph Domain["Domain packages"]
daemon[daemon]
pipeline[pipeline]
validate[validate]
archive[archive]
project[project]
knowledge[knowledge]
end
subgraph Core["Core packages"]
state[state]
config[config]
invoke[invoke]
tierfs[tierfs]
tree[tree]
end
subgraph Foundation["Leaf packages (no internal deps)"]
clock[clock]
errors[errors]
git[git]
output[output]
logging[logging]
logrender[logrender]
signals[signals]
end
root --> cmdutil
cmddaemon --> cmdutil
cmdtask --> cmdutil
cmdaudit --> cmdutil
cmdconfig --> cmdutil
cmdinbox --> cmdutil
cmdproject --> cmdutil
cmdorch --> cmdutil
cmdknow --> cmdutil
cmdutil --> daemon
cmdutil --> state
cmdutil --> config
cmdutil --> pipeline
cmdutil --> git
cmdutil --> invoke
daemon --> state
daemon --> pipeline
daemon --> invoke
daemon --> logging
daemon --> archive
daemon --> signals
daemon --> tree
pipeline --> config
pipeline --> invoke
pipeline --> state
pipeline --> tierfs
validate --> state
validate --> config
validate --> tree
validate --> invoke
archive --> state
archive --> config
archive --> clock
project --> config
project --> state
project --> tierfs
state --> clock
config --> tierfs
invoke --> config
logging --> output
Dependencies flow strictly downward. Domain packages orchestrate core packages. Core packages depend only on each other and on leaf packages. Leaf packages have no internal dependencies.
100 ADRs document every major design decision. Read docs/decisions/INDEX.md before making architectural changes. If your change introduces a new pattern or reverses an existing decision, write an ADR.