@@ -17,9 +17,14 @@ day-to-day development. Use the `gogo` binary for all dev workflows — see
1717| Cross-compile all | ` gogo cross ` |
1818| Clean artifacts | ` gogo clean ` |
1919
20- CI (` .github/workflows/ci.yml ` ) runs tests, ` golangci-lint ` , and the
21- multi-platform Docker build. Releases (` release.yml ` ) are tag-driven and
22- publish cross-built binaries via ` gh release create ` .
20+ CI (` .github/workflows/ci.yml ` ) runs four jobs: tests (` go test ./... ` ),
21+ ` golangci-lint ` , ` govulncheck ` , and the multi-platform Docker build. The
22+ ` vulncheck ` job also runs on a weekly cron so newly disclosed advisories
23+ surface even when the repo is quiet. Dependabot (` .github/dependabot.yml ` )
24+ bumps Go modules, GitHub Actions SHAs, and Docker base images weekly — pair
25+ the Actions group with the ` ghapin ` skill when reviewing those PRs.
26+ Releases (` release.yml ` ) are tag-driven and publish cross-built binaries via
27+ ` gh release create ` plus build-provenance attestations.
2328
2429The Go toolchain version comes from ` go.mod ` (` go 1.26.3 ` ). Tests run with
2530` -tests=true ` under golangci-lint v2.
@@ -58,7 +63,9 @@ The Go toolchain version comes from `go.mod` (`go 1.26.3`). Tests run with
5863- ** YAML unmarshalling** : when adding a field that should accept both a
5964 string and a struct, follow the ` Cmd ` /` Dep ` /` Var ` /` Precondition ` pattern
6065 (try string first, then re-unmarshal into a ` type plain X ` to avoid
61- recursion).
66+ recursion). For a * string-or-list* field (e.g. ` sources ` , ` aliases ` ),
67+ use the ` StringList ` named slice in ` taskfile/types.go ` instead of
68+ ` []string ` — its ` UnmarshalYAML ` already handles the single-string case.
6269- ** Logging** : never ` fmt.Print ` in library code. Use ` Runner.logTask ` or
6370 write to the injected ` RunnerIO ` / ` App.Stdout|Stderr ` .
6471- ** Comments on exported symbols** : required by ` revive ` ; keep them short
@@ -97,25 +104,61 @@ The Go toolchain version comes from `go.mod` (`go 1.26.3`). Tests run with
97104## Configuration
98105
99106- ** ` gogo.yaml ` ** — repo's own task file (the project eats its own dog food).
100- Edit when changing dev workflows.
107+ Uses the built-in ` go ` source preset (see below) so every Go-aware task
108+ shares one source list. Edit when changing dev workflows.
101109- ** ` .golangci.yml ` ** — single source of truth for lint config; keep
102110 ` gci.sections ` in sync if the module path ever changes.
103111- ** ` Dockerfile ` ** — multi-stage cross build using ` tonistiigi/xx `
104112 (` xx-go build ` ) and ` crazymax/osxcross ` for darwin targets. CGO is on for
105113 darwin, off otherwise. Update ` GO_VERSION ` here when bumping ` go.mod ` .
106- - ** ` .github/workflows/ ` ** — ` ci.yml ` (test/lint/build) and ` release.yml `
107- (tag-triggered cross build + GitHub release). Action SHAs are pinned;
108- use the ` ghapin ` skill when bumping them.
114+ - ** ` .github/workflows/ ` ** — ` ci.yml ` (test/lint/vulncheck/build) and
115+ ` release.yml ` (tag-triggered cross build + GitHub release with build
116+ provenance attestations). Action SHAs are pinned; use the ` ghapin ` skill
117+ when bumping them. ` .github/dependabot.yml ` opens grouped weekly PRs for
118+ Go modules, Actions, and Docker base images.
109119- ** Generated/ignored** (` .gitignore ` ): ` .gogo/ ` (checksum cache),
110120 ` bin/ ` , ` dist/ ` , ` .zig-cache/ ` .
111121- ** No env vars** are required at runtime; gogo only consumes whatever the
112122 user puts in their own ` gogo.yaml ` / dotenv files.
123+ - ** Source presets** — built-ins ` go ` and ` go-vendored ` live in
124+ ` taskfile/sources.go::builtinSourcePresets ` . Users can override or extend
125+ them via a top-level ` sources: ` map (` Config.Sources ` ); user entries win
126+ on a name collision. Presets compose recursively (` go-vendored `
127+ references ` go ` ); cycles and unknown preset-shaped names are caught in
128+ ` expandSources ` . Anything containing a glob metacharacter or path
129+ separator is treated as a literal pattern, so ` go.mod ` / ` *.go ` work as
130+ before.
131+ - ** ` flatten: ` ** (top-level or per-include) lists YAML files whose tasks
132+ merge into the * parent's* namespace without a prefix — the agentic-platform
133+ pattern for splitting one big task file across many. Tasks land at the
134+ ancestor's namespace (root, or the include dir), ` task.Dir ` is resolved
135+ against the ancestor (not the flatten file's dir), and "first defined
136+ wins" so a parent file can override a flattened task by re-declaring it.
137+ See ` loadFlatten ` and ` TestFlattenedTaskRunsFromRootDir ` .
138+ - ** Foreign fallback** (` fallback.go ` ) — when no ` gogo.yaml ` is found, gogo
139+ walks up looking for a ` Taskfile.yml ` , ` mise.toml ` , or ` Makefile ` whose
140+ runner is on ` PATH ` , and shells out. Order is fixed by ` foreignRunners `
141+ and the ` make ` arm intentionally drops ` default ` and skips the ` -- `
142+ separator (since ` make ` doesn't understand it). Tests stub the package-
143+ level ` fallbackLookPath ` / ` fallbackRun ` hooks rather than the real exec.
144+ - ** Internal tasks** — names whose local segment starts with ` _ `
145+ (e.g. ` _helper ` , ` cli:_fmt ` ) are excluded from ` --list ` and ` --complete `
146+ but still callable explicitly. Use ` taskfile.IsInternalTask ` for the
147+ visibility check; ` visibleTaskNames ` in ` main.go ` is the only consumer.
113148
114149## Common development patterns
115150
116151- ** Adding a new top-level CLI flag** : add a tagged field to ` args ` in
117152 ` main.go ` , handle it in ` App.Run ` before ` runner.Run ` is reached, and
118- add a test in ` app_test.go ` using ` newTestApp ` .
153+ add a test in ` app_test.go ` using ` newTestApp ` . The current flags are
154+ ` --list ` , ` --watch ` , ` --force ` , ` --dry ` , ` --completion ` , and the hidden
155+ ` --complete ` (used by the shell-completion scripts embedded in
156+ ` main.go ` ).
157+ - ** Silencing a task's per-cmd log** : set ` silent: true ` on the task. It
158+ suppresses the ` [task] cmd ` log line for * that task's own* cmds only —
159+ sub-tasks invoked via ` cmds: - task: X ` continue to log unless they
160+ also opt in (see ` TestSilentDoesNotPropagateToCalledTasks ` ). The shell
161+ command itself still runs and its stdout/stderr are unaffected.
119162- ** Adding a new task field** : add it to ` Task ` in ` taskfile/types.go ` ,
120163 decide whether ` UnmarshalYAML ` needs string-shorthand support, thread
121164 it through ` Runner.run ` in the right phase (deps → vars → requires →
@@ -134,7 +177,10 @@ The Go toolchain version comes from `go.mod` (`go 1.26.3`). Tests run with
134177 resolve lazily through a recursive lookup in ` resolveAllVars ` (see
135178 ` taskfile/vars.go ` ); they may reference each other and the built-in
136179 ` GIT_* ` family transitively, declaration order is irrelevant, and
137- cycles short-circuit to the empty string. ** Vars are namespace-scoped** :
180+ cycles short-circuit to the empty string. The built-in ` TASK_FILE_DIR `
181+ template var is seeded into every task's resolved-vars map and points
182+ at the task's effective working directory (after ` Runner.taskDir ` ).
183+ ** Vars are namespace-scoped** :
138184 a var declared in an included ` gogo.yaml ` lives in
139185 ` Config.NamespaceVars[namespace] ` (with its own working dir in
140186 ` Config.NamespaceDirs[namespace] ` for ` sh: ` resolution) and is visible
@@ -151,8 +197,9 @@ The Go toolchain version comes from `go.mod` (`go 1.26.3`). Tests run with
151197 rewritten to ` ${2} ` (see ` TestShVarPreservesAwkPositional ` ). Watch mode
152198 must call ` ResetRan ` between iterations — it also clears the gitVars
153199 cache so ` {{.GIT_DIRTY}} ` re-evaluates after each edit.
154- - ** Touching include logic** : cycles must be detected by absolute dir
155- (` includeStack ` ), nested namespaces are colon-joined
200+ - ** Touching include logic** : cycles must be detected by absolute file
201+ path (` loadStack ` , which tracks both ` gogo.yaml ` files and ` flatten: `
202+ YAML files), nested namespaces are colon-joined
156203 (` parent:child:grandchild ` ), and dotenv files dedupe globally via
157204 ` seenDotenv ` . ` Namespaces ` map keys are absolute dirs and are used by
158205 namespace-aware task name resolution.
0 commit comments