Documentation
¶
Overview ¶
Package initrepo implements `aiwf init`: idempotent first-time setup for a consumer repo. See docs/archive/pocv3/poc-plan-pre-migration.md Session 3 for the full contract.
The package never produces a git commit — it writes/scaffolds and reports back; the user commits when ready. It is also safe to re-run: pre-existing files (aiwf.yaml, CLAUDE.md, custom .gitignore content) are preserved verbatim; skills are always wiped-and-rewritten per the cache contract.
Index ¶
Constants ¶
const CLAUDETemplate = `# CLAUDE.md
This repository uses [aiwf](https://github.com/23min/aiwf) to track planning state.
## Quick reference
- ` + "`aiwf check`" + ` — validate the planning tree.
- ` + "`aiwf add <kind> --title \"...\"`" + ` — create an entity (epic, milestone, adr, gap, decision, contract).
- ` + "`aiwf promote <id> <status>`" + ` — advance status.
- ` + "`aiwf history <id>`" + ` — show what happened to an entity.
The pre-push hook runs ` + "`aiwf check`" + ` automatically; broken state cannot be pushed.
Skills under ` + "`.claude/skills/aiwf-*/`" + ` are gitignored and regenerated on ` + "`aiwf update`" + `.
`
CLAUDETemplate is the boilerplate written to CLAUDE.md when no file exists. Short by design — consumers customize it freely.
Variables ¶
This section is empty.
Functions ¶
func CommitMsgHookMarker ¶ added in v0.12.0
func CommitMsgHookMarker() string
CommitMsgHookMarker exposes the commit-msg hook's marker line for tests and for `aiwf doctor` to identify a marker-managed hook versus a user-written one.
func GuidanceMarkerLineIdx ¶ added in v0.28.0
GuidanceMarkerLineIdx returns the index of the first line that, once trimmed, equals marker — or -1. Line-anchored: a marker string that appears inside a prose line is NOT matched, so user text mentioning the markers is never treated as a block boundary (review-hardening for the "clobbers nothing" guarantee in ADR-0018).
Exported (F9) so `aiwf doctor`'s guidance-import detection shares this exact line-anchored check — passing the bare "@"+skills.GuidanceFile import line as marker — instead of an independent re-implementation, the same pattern as the hook markers (HookMarker et al.).
func HookMarker ¶
func HookMarker() string
HookMarker exposes the marker line for tests that assert the hook was installed by aiwf vs. someone else.
func PostCommitHookMarker ¶ added in v0.8.1
func PostCommitHookMarker() string
PostCommitHookMarker exposes the post-commit hook's marker line for tests and for `aiwf doctor` to identify a marker-managed hook versus a user-written one.
func PreCommitHookMarker ¶
func PreCommitHookMarker() string
PreCommitHookMarker exposes the pre-commit hook's marker line for tests and for `aiwf doctor` to identify a marker-managed hook versus a user-written one.
Types ¶
type Action ¶
type Action string
Action classifies what init did for a single step. The CLI uses this to render a friendly summary.
const ( ActionCreated Action = "created" ActionPreserved Action = "preserved" ActionUpdated Action = "updated" // ActionSkipped marks a step that init declined to perform because // doing so would clobber user-managed state. The Detail field on // the StepResult explains why and what the user should do next. ActionSkipped Action = "skipped" // ActionRemoved marks a step that uninstalled a previously-managed // artifact because the consumer opted out. Currently used only by // the pre-commit hook step when status_md.auto_update flips false. ActionRemoved Action = "removed" // ActionMigrated marks a hook step that mv'd a pre-existing // non-aiwf hook to <name>.local before installing aiwf's chain-aware // hook (G45). The Detail names what moved where so the user can // audit it. ActionMigrated Action = "migrated" )
Action values reported per step.
type Options ¶
Options carries init-time inputs that override or supplement the defaults. ActorOverride bypasses git-config derivation when set.
DryRun computes the would-be ledger without performing any filesystem mutations. SkipHook omits *both* the pre-push and the pre-commit hook installations entirely (each still reported in the ledger as a skipped step). The flag is for consumers who run husky/lefthook (or similar) and want aiwf to leave .git/hooks/ alone.
Per G47, `aiwf_version:` is no longer stored in aiwf.yaml — the running binary's version is the authoritative answer to "what version are we on" (`aiwf version`); a stored pin produced chronic doctor noise without serving its intended purpose.
type RefreshOptions ¶
type RefreshOptions struct {
DryRun bool
SkipHooks bool
StatusMdAutoUpdate bool
// WireClaudeMd controls whether aiwf maintains its guidance import in
// the consumer's CLAUDE.md. Default-on, opt-out via aiwf.yaml
// `guidance.wire_claudemd: false` (ADR-0018; M-0164). When true,
// init/update add, refresh, and self-heal the marker block — there is
// no CLI flag.
WireClaudeMd bool
}
RefreshOptions carries the inputs that drive RefreshArtifacts — the shared installer pipeline run by both `aiwf init` (after scaffolding) and `aiwf update`.
StatusMdAutoUpdate carries the consumer's opt-out state from `aiwf.yaml.status_md.auto_update`. When true, the pre-commit hook that regenerates `STATUS.md` is installed/refreshed; when false, a previously-installed marker-managed pre-commit hook is removed and a fresh refresh pass installs nothing in its place.
SkipHooks omits both pre-push and pre-commit installation entirely (init's `--skip-hook` flag forwards into this field).
type Result ¶
type Result struct {
Steps []StepResult
HookConflict bool
DryRun bool
}
Result is the per-step ledger init returns. Order matches the order of operations. HookConflict is set when init declined to install the pre-push hook because a non-aiwf hook was already in place; callers should surface remediation guidance to the user. DryRun echoes Options.DryRun so callers can format output appropriately (a dry-run ledger looks identical but no writes occurred).
func Init ¶
Init runs the documented setup steps in order. Returns a Result that describes what was created vs preserved vs updated. Errors abort early — a partially-applied init is rare in practice (init only touches config / scaffolding / skills) and the user can re-run.
Step order:
- aiwf.yaml (first-time-only)
- work/* and docs/adr scaffold dirs (first-time-only)
- CLAUDE.md (first-time-only)
- RefreshArtifacts: skills + .gitignore + pre-push hook + pre-commit hook (the same pipeline `aiwf update` calls).
Steps 1–3 write only if the artifact is missing; step 4 wipes-and- rewrites per the cache contract for derivable artifacts.
type StepResult ¶
StepResult is one line of init's per-step ledger.
func RefreshArtifacts ¶
func RefreshArtifacts(ctx context.Context, root string, opts RefreshOptions) ([]StepResult, bool, error)
RefreshArtifacts runs the wipe-and-rewrite pipeline shared by `aiwf init` (after first-time-only scaffolding) and `aiwf update`. All steps return a StepResult; only the hook steps can produce a conflict (returned as the second value), at which point the caller surfaces remediation guidance to the user.
Step order:
- .claude/skills/aiwf-* (skills materialization)
- aiwf.yaml legacy `actor:` strip (idempotent)
- aiwf.example.yaml (always-fresh schema reference; M-0232/AC-3)
- .gitignore (skill cache patterns + STATUS.md)
- .git/hooks/pre-push (the validation chokepoint)
- .git/hooks/pre-commit (G41 tree-discipline gate — always installs when aiwf is adopted in the repo)
- .git/hooks/post-commit (gated by StatusMdAutoUpdate; G-0112)
SkipHooks bypasses every hook step; each is reported as a Skipped row in the ledger so the user sees what was deliberately not done. StatusMdAutoUpdate=false drives ensurePostCommitHook into its skip/uninstall path (removes a previously-installed marker-managed hook, leaves user-written hooks alone) but does not affect ensurePreCommitHook — the tree-discipline gate stays.