Repository navigation
test(golden): lock --help output and shell completions against the registered command/flag surface - #238
Open
javimosch wants to merge 51 commits into
Open
test(golden): lock --help output and shell completions against the registered command/flag surface#238javimosch wants to merge 51 commits into
javimosch wants to merge 51 commits into
Conversation
New subcommand writes ~/.config/tau/config.json as JSONC: it scans the provider table's env_keys (plus TAU_API_KEY), selects the first provider with a detected key (or an explicit --provider), and emits a commented starter that names every provider's env vars -- never copying secret values. Refuses to overwrite an existing file unless --force; --stdout previews without writing. configfile.load now strips // and /* */ comments before parsing so the scaffolded file (and hand-commented configs) load cleanly; string-aware scanning keeps "//" inside values (e.g. URLs) intact. Also wires help/guide entries, bash/zsh completions, an offline smoke group, and fixes a stray literal backslash before the Examples header in --help output. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
docs/troubleshooting.md maps each user-visible error message (by exit
code and envelope type) to its cause and fix. To make the doc
discoverable, every {"err":...} envelope now carries a "docs" field
pointing at the published URL — the constant lives in version.zig as the
single source of truth. README's Troubleshooting section links the doc
and the embedded guide's see_also lists it.
Unit-test run() end-to-end against a hermetic tmp HOME (same convention as configfile.zig's TestHome): fresh write produces a commented config that loads without warning, existing configs are refused without --force (contents untouched), --force regenerates the scaffold, --stdout writes nothing, and a missing HOME exits 110.
…134) Pin the user-visible error contract so DX regressions are caught in CI: - golden test asserting formatErrorJson output byte-for-byte, including the "docs" link to the troubleshooting FAQ - source scan asserting every hand-rolled {"err":...} literal in main/agent/acp/fleet/helpers keeps a "docs" field - doc tests asserting docs/troubleshooting.md indexes every exit code, embeds its own canonical URL, and is linked from the README
Extend shell completion support beyond bash/zsh: - completions/tau.fish — fish completion with subcommand-aware context helpers, per-candidate descriptions, and @file injection that strips the sigil, delegates to the builtin file completer, and re-adds '@' - completions/tau.ps1 — PowerShell Register-ArgumentCompleter script (PS 5.1+/pwsh 7+) with tooltip descriptions, quoted '@file' handling (bare '@x' is splat syntax in PowerShell), and a Get-ChildItem fallback when CompletionCompleters is unavailable - completions/tau.bash, completions/_tau — parity fixes: add the missing 'guide' subcommand and 'calculator' tool, and offer fleet flags before the sub-subcommand (valid per args.zig ordering) - completions/README.md — fish/pwsh install docs, file/shell matrix, the PowerShell @file quoting caveat - scripts/smoke.sh — new offline 'completions' group asserting every --help-json flag, subcommand, and enum value appears in all four completion files (drift guard) - README.md + CONTRIBUTING.md — point to completions/ Verified: fish 3.7 and pwsh 7.4 exercised end-to-end via complete --do-complete / TabExpansion2; bash tested via COMP_WORDS simulation; zsh via zpty. 274/274 zig tests, 13/13 completions smoke checks, no regressions in help/flags/fleet-flags groups. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Read-only diagnostic that prints the fully merged config (config file -> env vars -> CLI flags) as JSON, exactly as a run would see it. Unlike acp/fleet, `config show` falls through the generic flag parser so override flags (--provider/--model/--api-key/--mode/...) are reflected in the output, which makes it useful for previewing merges without running. Secrets are never printed: `api_key.value` is masked to "***" + last 4 via the new cfgmod.redactApiKey, and `api_key.source` reports which precedence level supplied the key (--api-key / config keys[<provider>] / env <VAR> / config api_key / env TAU_API_KEY / builtin) via resolveApiKeyInfo, which resolveApiKey now delegates to. The per-provider `keys` map is emitted sorted with each value masked. config_file reports the probed path, whether a file was read (new Config.config_path set by configfile.load), and any parse warning; endpoint_source attributes the endpoint to the provider table or env:TAU_ENDPOINT. Bare `tau config` and unknown subcommands exit 80; `config show` rejects positional arguments. Non-finite floats (e.g. --temperature nan) serialize as null to keep the JSON valid. Tests: 293/293 zig build test green (resolveApiKeyInfo source attribution, redactApiKey, args parsing, formatEffectiveConfig). New offline smoke group `config-show` (22 checks) covers merge precedence, redaction, error paths, and env attribution. Docs updated: help_text, guide commands, README, docs/configuration.md, AGENTS.md, CHANGELOG, and bash/zsh completions. Closes #140 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…able install.sh Adopters shouldn't need a Zig toolchain to try tau. Push a v* tag and the release workflow cross-compiles all four targets (linux/macos x86_64+aarch64) from a single Linux runner, publishes tau-<os>-<arch>.tar.gz assets plus SHA256SUMS.txt, and creates the GitHub release via gh CLI (no third-party actions beyond checkout/artifact upload). A guard step fails the run when the tag doesn't match src/version.zig; suffixed tags publish as pre-releases. workflow_dispatch runs build-only for validation. install.sh (POSIX sh) detects OS/arch, resolves the latest or --version-pinned asset URL, verifies the checksum when sha256sum/shasum is available, and installs to ~/.local/bin. --dry-run and TAU_OS/TAU_ARCH overrides make the platform mapping testable offline, exercised by a new 27-check 'release' smoke group that also drift-guards the workflow file. Verified: all 4 targets cross-compile with zig 0.16.0; 27/27 release smoke checks green; README + CHANGELOG updated.
Adds a smoke job to release.yml that runs after build and gates release: each dist tarball is staged behind a local HTTP stand-in for the GitHub releases URL, installed end-to-end through install.sh on the matching runner (ubuntu-latest, ubuntu-24.04-arm, macos-15-intel, macos-latest), and verified with tau --version/--help. Covers all four shipped assets. install.sh gains a documented TAU_BASE_URL env override so the installer can be pointed at any base URL exposing the releases layout — this is what the smoke job (and local smoke tests via file://) use. Fixes a latent checksum-verification bug the e2e check surfaced: the release job generated SHA256SUMS.txt with ./-prefixed filenames while install.sh greps " <asset>$" (space before the name), so no line ever matched and every real install would abort. The workflow now emits clean filenames and the installer grep tolerates an optional ./ prefix. Verified: release smoke group 49/49 green, including a full offline file:// install (download → checksum → extract → install → version/help) and a checksum-mismatch rejection. release.yml parses as valid YAML.
… mago/task-151
CI adopters can now install tau with a single `uses: javimosch/tau@<ref>` line. The composite action shells out to the repo's own install.sh via $GITHUB_ACTION_PATH (so installer version matches the action ref), exposes version/install-dir/base-url inputs mapped to the installer's TAU_* env overrides, appends the install dir to $GITHUB_PATH, and surfaces tau-path + version step outputs. release.yml gains a smoke-action job that stages the linux-x86_64 tarball behind a local HTTP stand-in and runs `uses: ./` end-to-end (download → checksum → install → outputs/PATH checks), gating the release publish on the action working as advertised. scripts/smoke.sh's release group pins the action surface: composite type, install.sh invocation, all three inputs and their env mapping, GITHUB_PATH/GITHUB_OUTPUT wiring, outputs, and a conditional YAML parse. Verified: release smoke group 69/69; action run block exercised offline against a staged file:// release tree (install + outputs correct); action.yml and release.yml parse as YAML. Stacked on mago/task-147 (install.sh + release smoke job, PRs #146/#150) — this PR includes those commits until they merge. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Validates the whole setup chain in one JSON report on stdout: config file parse (missing vs invalid vs unknown provider), provider/model/endpoint resolution, API key provenance (source only — never the key), curl on PATH, endpoint reachability (~5s probe), and an optional --deep authenticated probe (max_tokens=1). --offline marks network checks "skip". Exit 0 when no check fails, 1 otherwise; unknown args exit 80. An unknown provider is carried into the report as a failed provider_resolution check instead of exiting 80, so doctor stays useful exactly when setup is broken. Supporting changes: Config gains doctor_offline/doctor_deep/ doctor_bad_provider plus config_path (set by configfile.load when a file is read); resolveApiKeyInfo exposes key provenance (resolveApiKey now delegates to it — same precedence contract, existing tests unchanged). 9 new unit tests in doctor.zig, 4 in args.zig (288/288 green); new 'doctor' smoke group (33 offline checks); help_text Diagnostics section; AGENTS.md cheatsheet + file map; README/docs/configuration.md/CHANGELOG pointers. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… mago/task-161
…um chain in release.yml install.sh previously warned-and-continued when SHA256SUMS.txt was unreachable or no sha256sum/shasum existed — a silent trust path for tampered or corrupted binaries. Verification is now mandatory: the install aborts when the manifest can't be fetched, the asset isn't listed in it, no checksum tool is available, or the digest mismatches. TAU_SKIP_CHECKSUM=1 is a documented opt-out for air-gapped mirrors. release.yml closes the loop end-to-end: the build job emits a per-asset .tar.gz.sha256 alongside each tarball, both smoke jobs verify it against the downloaded artifact before staging, and the release job re-checks SHA256SUMS.txt before publishing so a malformed manifest can never ship (it would brick every install under fail-closed semantics). Smoke release group grows 49 -> 83 checks: drift guards for the new workflow steps plus e2e cases for manifest-miss, unlisted-asset, and the skip-checksum bypass. README + CHANGELOG updated.
…codes Adds the coverage issue #165 asks for on top of the `tau doctor` implementation (PR #160 / mago/task-127): - zig: checkConfigFile now exercised through real file I/O via a throwaway HOME (missing file, valid file, invalid JSON, unreadable/dir-as-file), checkEndpoint and checkAuthProbe failure paths pinned against a refused local port, keyHint/providerListHint contents, ok:true report shape with warnings, and curlHttpCode's spawn-failure null. - smoke: doctor group 33 -> 63 checks — curl missing from PATH cascade (--deep so both network checks report the curl gate), warn-doesn't-fail exit 0, positional-arg exit 80 with stderr message, and a local python stub server driving endpoint_reachable (401 counts as reachable) plus --deep auth_probe for HTTP 200/401/429 including a key-material leak assertion. - CHANGELOG: Tests section entry for #165. Verified: zig build test 297/297, smoke doctor group 63/63.
--debug already streamed [DEBUG] lines to stderr; it now also mirrors them
to ~/.config/tau/debug/<UTC-timestamp>-<suffix>.log (TAU_DEBUG_LOG overrides)
so users can attach the file to bug reports. New src/debuglog.zig owns the
log: it masks the resolved API key plus every other configured/env key,
Bearer tokens, api_key-style JSON fields, and *_KEY=/_TOKEN= env-style
assignments (***REDACTED***); stderr keeps the raw output. The file is
created owner-only (0600) with a provenance header (version, provider,
model, endpoint, key_resolved) and each entry is capped at 8 KiB.
Error envelopes gain an optional "debug_log" field linking the active log
(formatErrorJson + the /goal-session literal emitter — the only literal on
the .run path where a log can exist), and startup emits {"debug_log":...}
on stderr. Failure to create the file degrades to a warn envelope; the run
continues on stderr-only debug output.
Also makes the help text's "perf stats" claim real: a [DEBUG] perf line
(tokens_out, elapsed_ms, exit_code) is emitted once per run.
Stacked on mago/task-130 (PR #131) — both touch the err envelope format;
stacking keeps the docs field consistent.
Closes #167
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ediation hints
Every {"err":...} envelope now carries code, type, message, recoverable,
a remediation hint, and the docs link — emitted from one shared formatter
(src/errors.zig) instead of six hand-rolled literals across main/agent/acp/
fleet/helpers.
- errors.zig: canonical Spec registry (codes 1/80/82/105/106/110/111),
specFor() lookup, format()/printErr()/printOut() emitters that splice in
debuglog's debug_log field, and an OOM fallback that keeps the shape.
- Codes and wire `type` tags are documented as stable (never renumbered or
renamed) in a new "Stable error catalog" table in docs/troubleshooting.md.
- Auth failures keep their dynamic hint (names the provider env var); all
other codes fall back to the catalog hint.
- Snapshot tests pin every catalog entry byte-for-byte; sync tests assert
the catalog covers docs/troubleshooting.md and --help-json exit_codes;
the literal-emitter source scan now also requires the hint field.
- Smoke: envelope assertions now check recoverable/hint/docs (82-path gated
on has_key since fleet's auth check fires first in keyless envs).
Stacked on mago/task-167 (PR #168) — it owns the current envelope shape
(docs + debug_log fields). docs/integration.md (PR #145) already declares
new fields non-breaking; its "minimal {code,message} envelope" line goes
stale once both land and should be updated there.
Closes #171
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…stable tags Adds a `homebrew` job to the release workflow that regenerates Formula/tau.rb from the published SHA256SUMS.txt manifest (new scripts/generate-homebrew-formula.sh, runnable standalone) and pushes it to javimosch/homebrew-tap via the contents API, so macOS/Linux users can `brew install javimosch/tap/tau` and track releases with `brew upgrade`. Pre-release tags (v*-*) are skipped so the tap only tracks stable versions, and the publish step warns + skips when the HOMEBREW_TAP_TOKEN secret is absent rather than failing the release. Docs: README gets a Homebrew install option, release notes mention brew, CHANGELOG + AGENTS.md file map updated. Smoke release group grows to 118 checks covering the generator (render, v-strip, fail-closed paths) and workflow drift guards. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- New docs/providers.md: per-provider credential setup (env vars, config keys map, endpoints, default models), the 6-level key-resolution chain, and exit-106 auth troubleshooting (missing key, silent keyless exit, rejected key, shadowed TAU_API_KEY, TAU_ENDPOINT auth mismatches). - errors.zig: Spec gains a `docs` field (default: troubleshooting URL) and Opts a docs override; the auth_failed spec points envelopes at providers.md so every code-106 error links the credential guide. - version.zig: providers_doc_url constant next to troubleshooting_doc_url. - Cross-links: troubleshooting.md (example envelope, catalog docs column, auth section), README quickstart + troubleshooting table, configuration.md Providers section, `tau guide` see_also. - Pins: golden snapshot updated; new tests pin the 106 -> providers.md link and that providers.md documents every provider's name, env keys, endpoint, and default model; smoke dry-run group gains a keyless fleet-run envelope check.
…imosch/tau into mago/task-177
…re-commit Adds a `validate` subcommand under `tau config` (stacked on the #142 `config` parent). `tau config validate [path]` checks a config file — default ~/.config/tau/config.json — and prints a report to stdout: {"path":..,"ok":bool,"errors":[{key,message}]} in JSON mode or one "path: error in \"key\": message" line per problem in --mode text. Checks are derived at comptime from configfile.FileConfig (now pub), so the validator can't drift from the loader's schema, plus value-level checks the struct can't express: unknown keys, type mismatches, unknown provider/mode, compact_threshold outside 0-1, negative temperature, negative/overflowing integers, and keys.* entries that aren't strings or name an unknown provider. Syntax errors get a line/column via std.json.Diagnostics; key values are never echoed. Exit codes stay inside the pinned contract: 0 valid, 1 problems found, 80 CLI misuse. Fully offline — no network, no env probing beyond HOME. Coordinated points: JSONC comment support (PR #128) lands on the loader later — when it does, validate should strip comments the same way; unknown-key warnings (PR #153) become hard errors here by design. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…Windows smoke Adds the Windows install path end-to-end: - release.yml: new x86_64-windows-gnu build target shipping tau-windows-x86_64.zip (Windows convention); SHA256SUMS.txt now covers .zip assets; new smoke-windows job installs the zip through install.ps1 on a native windows-latest runner (file:// TAU_BASE_URL staging) and verifies tau.exe --version/--help before the release can publish. - install.ps1: mirrors the install.sh contract — -Version/-Dir/-DryRun/ -Help (both -name and --name forms, manual $args parse since pwsh does not bind --switches), TAU_VERSION/TAU_INSTALL_DIR/TAU_ARCH/TAU_BASE_URL/ TAU_SKIP_CHECKSUM overrides, fail-closed Get-FileHash SHA256 verification, Expand-Archive install to %LOCALAPPDATA%\Programs\tau with a user-PATH note. throw/return instead of exit so irm|iex installs don't kill the caller's shell; file:// URLs resolve via System.Uri so the staging trick works on every pwsh host. - scripts/generate-winget-manifest.sh: renders the three-file microsoft/winget-pkgs manifest (version/installer/defaultLocale) from the published checksums; the winget job validates it, uploads it as a workflow artifact, and auto-submits via wingetcreate when WINGET_PKGS_TOKEN is configured (warn-and-skip otherwise). - scripts/generate-scoop-manifest.sh: renders bucket/tau.json for javimosch/scoop-bucket; the scoop job publishes via gh api contents PUT behind SCOOP_BUCKET_TOKEN, warn-and-skip while the token is unset or the bucket repo does not exist. - smoke.sh release group: +install.ps1 surface checks (pwsh-gated), workflow drift guards for the new jobs, generator contract tests, and a file:// install.ps1 e2e exercising the full fail-closed checksum ladder. - README quickstart + release notes + CHANGELOG document the Windows path. Stacked on mago/task-175 (the release chain this extends). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…tor)
`tau setup` runs the full first-run flow as one NDJSON transcript:
scaffolds ~/.config/tau/config.json (init semantics — keeps an existing
file instead of failing), installs shell completions for the $SHELL-
detected shell (--shell bash|zsh|fish|pwsh|all overrides), and embeds the
`tau doctor` health report, ending with a {"step":"setup","ok":...}
verdict. Exit 0 when every step is ok/skipped, 1 on any failure.
Idempotent: rc/profile edits carry a "# tau completions" marker so
re-runs don't duplicate lines.
- build.zig generates a `completions` module embedding completions/*
via addWriteFiles, so `tau setup` installs scripts without a checkout
- doctor.zig: split collectReport() out of run() for reuse; fix
config_file check to strip JSONC comments (init scaffolds parse ok now)
- --provider/--model/--api-key/--offline/--deep pass through to the
doctor step; unknown providers ride in as a failed check (doctor
convention) while init falls back to detection
- completions: add init/doctor/setup coverage to bash, zsh, fish, pwsh
- 6 new unit tests + 41-check smoke group; docs: README, AGENTS.md,
CHANGELOG, completions/README, docs/configuration.md
Closes #181
…ind confirmation
`tau doctor --fix` plans and applies remediations for fixable check
outcomes: scaffold a missing config (init semantics, creates ~/.config/tau),
move an unparseable config to config.json.bak and re-scaffold, tighten POSIX
permission bits (0700 dir / 0600 file — the file can hold API keys), and
install/refresh shell completions. Every fix requires confirmation: --yes
(also -y, implies --fix) applies all non-interactively, a TTY stdin gets a
per-fix y/N prompt on stderr, and anything else is reported as skipped. The
emitted report gains a "fixes" array ({id,check,status,detail}) and reflects
the post-fix state when anything was applied; the exit code follows the
final report.
Two new always-on diagnostics back the remediations: config_permissions
(warn on group/other access, POSIX-only) and shell_completions (warn on
missing/outdated scripts or absent rc hooks for the detected/--shell shell).
Also exports the completion install helpers in setup.zig (installCompletion,
completionState, resolveShells, rc/script accessors) so doctor and setup
share one code path, and completes the new flags in all four shell scripts.
Verified: 324/324 zig tests (8 new covering planning, confirmation, every
fix kind, and round-trips), 84/84 doctor smoke checks including the new
--fix sections (skip-without-confirm, apply-with---yes, .bak restore),
setup/init/completions groups green, x86_64-windows-gnu cross-compile.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…trix Adds .github/workflows/ci.yml which runs `zig build test` and both offline smoke suites on a native runner for each released platform (linux x86_64/aarch64, macos x86_64/aarch64, windows x86_64) on PRs, master pushes, and v* tags — so platform regressions fail before a release is cut. `workflow_call` is exposed so the release workflow can gate on the matrix. Portability fixes to make that matrix green: - args.zig: parse() now takes a plain argv slice instead of std.process.Args, whose POSIX-only `.vector` field broke `zig build test` compilation for windows-gnu. main.zig materializes the platform argv (WTF-16 on Windows, UTF-8 on POSIX) into a UTF-8 slice itself. - smoke.sh: the acp group now pins both documented daemon contracts — exit 0 + running:false on POSIX, exit 111 err envelope on Windows — instead of failing on the Windows leg. - smoke.sh + smoke-features.sh: pass --api-key fake to checks exercising post-auth validation (fleet run without --goal, /goal without --session), so they are deterministic in keyless CI environments — key resolution precedes those checks and would exit 106 first. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
--json replaces the single-object report with line-delimited events matching
the documented stream contract: {"check":{...},"done":false} per check as it
finishes, {"fix":{...},"done":false} per remediation under --fix, and a
terminal {"ok","version","summary","fixes"?,"done":true} verdict. A check
re-diagnosed after an applied fix re-emits with its post-fix status. Exit
codes, the default report shape, and `tau setup`'s embedded report are
unchanged.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts: # completions/README.md # completions/_tau # completions/tau.bash # scripts/smoke.sh # src/args.zig # src/configfile.zig # src/main.zig
…nfig edits Adds git-config-style file editing alongside `config show`/`config validate`: - `set <key> <value> [path]` — coerce + validate the value per the FileConfig field type (provider/mode/ranges), then splice it into the JSONC file with a string/comment-aware scanner so comments and the `tau init` scaffold survive. `keys.<provider>` addresses per-provider API keys. Creates the file (mode 0600) and parent dirs when missing; writes are temp-file + rename atomic. - `get <key> [path] [--raw]` — read a stored value; api_key/keys.* are masked unless --raw (same redaction as `config show`). - `unset <key> [path]` — remove the member including its comma separator; duplicate occurrences are all removed. Exit codes: 0 ok; 1 = key/file not found, or file invalid (never clobbers); 80 = bad key/value/args. Stack also merges mago/task-126 (tau init + JSONC loading) so edits work on the commented scaffold; `config validate` now strips comments too so init output validates clean. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts: # scripts/smoke.sh
Bakes build provenance into the binary via a build.zig options module: git commit (short hash, "-dirty" on uncommitted changes, "unknown" for tarball builds), UTC build date (honors SOURCE_DATE_EPOCH so release binaries stay byte-reproducible), arch-os-abi target triple, and the zig compiler version — all exposed from version.zig's new `build` struct. Surfaced in three places so a bug report can pin down the exact binary: - `tau version --verbose` prints a JSON object (key:value lines under --mode text); bare `tau version` stays identical to -v/--version - `tau doctor` report and --json terminal verdict carry a "build" object - the --debug log header gains a `# build:` line via debuglog.writeHeader Includes version-subcommand args tests, version.zig formatter tests, doctor build-field pins, a 16-check `version` smoke group, completions for all four shells, and AGENTS.md/CHANGELOG updates. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… remediation hints
Adds a golden-errors smoke group that byte-locks the agent-facing failure
contract: 26 deterministic failure paths are run fully offline (provider keys
scrubbed, isolated HOME) and their exit status plus exact stdout/stderr bytes
are compared against snapshots in tests/golden/.
The snapshots pin the contract quirks that exist today:
- stderr {"err":{code,type,message,recoverable}} envelopes (printErrorJson)
- stdout {"err":{code,message}} short envelopes (helpers.fleetRequires)
- stderr {"err":{code,type,message}} variant (agent.goalSubcommand)
- the silent exits: missing API key -> bare 106 with no output
- the remediation-hint text in AuthFailed and unknown-provider envelopes
- 105 Timeout / 110 HTTPRequestFailed via loopback stubs (closed port and
a silent listener), guarded on curl+python3 availability
GOLDEN_UPDATE=1 ./scripts/smoke.sh --group golden-errors regenerates the
snapshots after an intentional contract change.
Also adds unit pins in main.zig: ExitCode numeric values, the --help-json
exit_codes table staying in sync with the enum, and authHint's remediation
text. Documented in CONTRIBUTING.md.
Verified: 277/277 unit tests; golden-errors 78/78 offline. The 17 failures
in goal/dry-run/fleet groups are pre-existing in a keyless environment
(identical count on a clean-HEAD worktree baseline).
Closes #208
… bundle Stacked on mago/task-204 (doctor --json/--fix chain + version.build + debuglog). `tau doctor --report` prints a Markdown bundle for pasting into a GitHub issue: verdict line, build metadata table (version/commit/target/build date/zig), the checks table, a Fixes table when --fix ran, effective settings (provider/model/endpoint/context_window + key source — never the key), and the config file verbatim in a fenced jsonc block. The config dump is passed through debuglog.redactAlloc with every credential source collected (resolved key, --api-key, config api_key + keys.*, TAU_API_KEY, all provider env vars, builtins), so key material can never leak into the report. Paths stay visible, matching the --debug log convention. --report + --json is rejected at parse time with exit 80 (mutually exclusive). Exit codes and the default JSON report are unchanged. debuglog.zig: registerSecrets refactored onto a new pub collectSecrets so the same source enumeration serves both the --debug log and --report. Also: help_text + guide commands row, all four completion scripts + completions README, troubleshooting.md diagnostic-toolkit row, unit tests (formatReportMarkdown shape/redaction, appendMdCell escaping, arg parse + mutex), and 19 new offline smoke checks in the doctor group. 368/368 zig tests, 113/113 doctor smoke checks green.
…n save
`tau config edit [path]` opens the config file in the user's editor
(TAU_EDITOR > VISUAL > EDITOR > vi/notepad, resolved through the system
shell like git, so `EDITOR="code --wait"` works), then runs the same
checks as `config validate` when the editor exits. A missing file is
seeded with the commented `tau init` scaffold first.
On a clean save the report is {"ok":true,"path":...,"editor":...,
"created":bool,"valid":true} (or "<path>: ok" in text mode). On failure
the validation report goes to stdout with exit 1 — the edits stay on
disk so the user can rerun and fix. Editor spawn/non-zero exits emit an
editor_failed envelope (exit 1); misuse exits 80.
Did-you-mean hints land in the shared validator: misspelled config keys,
bad `provider` values, and unknown `keys.<provider>` names now suggest
the nearest candidate (edit distance <= 2, via the suggest.zig helper
task-200 also uses — vendored verbatim so the chains merge cleanly).
The bad-subcommand error for `tau config <x>` gets the same treatment.
Completions (bash + zsh), docs/configuration.md, AGENTS.md, CHANGELOG,
help text, and `tau guide` updated. New `config-editor` smoke group
(18 checks, stubbed TAU_EDITOR); 343/343 unit tests pass.
… + credential sweep --probe emits two rows per registry provider: probe_<name> (endpoint reachability — any HTTP response counts) and probe_<name>_auth (key resolved with the same precedence a run configured for that provider would use, then a one-token authenticated POST when a key is found). Only the key's source label is ever reported — never the key itself. The configured provider probes its resolved endpoint/model (TAU_ENDPOINT/--model honored); auth rows skip when the endpoint probe failed, when offline, when curl is missing, or when no credential resolves. Rows stream as NDJSON check events under --json and appear in the --report checks table. Without --probe a single skipped provider_probes row advertises the sweep. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ng onboarding Adds a "clients" step between completions and doctor in `tau setup`: - `--client zed|vscode|jetbrains` writes a minimal settings file (agent_servers.tau / acp.agents.tau) with the absolute path of the running binary, so GUI editors that lack PATH lookups still resolve it. - Existing settings files are never rewritten — they're JSONC and a parse-and-rewrite would destroy comments. If a "tau" entry is already present (checked via JSONC-aware parse) the entry reports already_installed; otherwise a paste-ready fragment lands in ~/.config/tau/snippets/<client>.jsonc and the entry reports "manual". - `--client nvim` always reports manual: Neovim ACP plugins are Lua config, so setup writes ~/.config/tau/snippets/nvim.lua with both the avante.nvim and CodeCompanion blocks plus an editor_detected flag. - Without --client the step is skipped and only reports which editor config dirs exist; detection never writes. - Manual outcomes pass the setup verdict; only IO failures fail it. Wired: args.zig enum validation (with "code" alias), Config.setup_client, help text, guide row, all four completion scripts, AGENTS.md, README, CHANGELOG, and a docs/acp.md shortcut note. 7 new unit tests cover parsing, paths, JSONC-aware tau-key detection, and the three write outcomes; 30 new offline smoke checks cover the flag end-to-end (324/324 unit, 73/73 setup group). Closes #219 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts: # AGENTS.md # CHANGELOG.md # completions/README.md # completions/_tau # completions/tau.bash # scripts/smoke.sh # src/args.zig # src/config.zig # src/configfile.zig # src/main.zig
# Conflicts: # CONTRIBUTING.md # scripts/smoke.sh # src/main.zig
…, config edit) Adds a golden-onboarding smoke group that byte-locks the whole first-run surface end-to-end on top of the task-208 golden harness: - tau init: fresh/rerun/--force/--stdout/--provider/detected-key/no-HOME runs; exit codes, stdout envelopes, and the generated config.json scaffold are pinned byte-exact - tau setup --offline: the full 5-line NDJSON step transcript (init, completions, clients, embedded doctor report, verdict) for fresh and re-run flows, keyless failure, --client zed/nvim plus the existing-file "manual" path; generated settings.json, snippets, .zshrc, and the installed completion scripts are pinned - tau config edit: TAU_EDITOR-stubbed runs covering a valid save (json + --mode text), an invalid save (validation report on stdout, edits stay on disk), editor failure (scaffold seeded first, editor_failed envelope), and the no-HOME arg error New helpers: golden_check_n (golden_check + normalization), golden_file (snapshot a generated file), _golden_fresh_home (per-scenario isolated HOME), and _golden_norm which rewrites the volatile bits — the temp HOME path, the tau binary path embedded in client configs, and the curl version in the doctor report — to <HOME>/<TAU>/<VER>. Merges the chains the tested features live on: mago/task-212 (config edit/set/get/unset/validate + init), mago/task-219 (setup --client + doctor + init), and mago/task-208 (golden harness). Verified: 383/383 zig unit tests; golden-onboarding 78/78 checks green and deterministic across runs; golden-errors 78/78 unchanged; full offline suite 510 passed with only the 17 pre-existing keyless-env failures (identical to baseline). Regenerate with: GOLDEN_UPDATE=1 ./scripts/smoke.sh --group golden-onboarding Closes #223
…check against a loopback stub Adds a `selftest` check row that spawns the running tau binary with a fully scrubbed environment — every provider env key, TAU_API_KEY, TAU_ENDPOINT and TAU_DEBUG_LOG stripped, HOME pointed at a throwaway dir so no real config can leak in — plus a stub TAU_API_KEY and a TAU_ENDPOINT aimed at an in-process loopback HTTP stub (std.Io.net, no python/sh dependency, Windows-safe). The child must return the canned marker end-to-end (one-shot, --no-tools --no-stream) for the row to report ok; exit code and truncated stderr/stdout excerpts are surfaced on failure. The stub serves up to 4 connections (the provider HTTP layer retries) and is reaped by a done-flag + self-connect kick so a blocked accept() never deadlocks the check. Deliberately not gated on --offline: the stub is loopback-only, so `tau doctor --offline --selftest` is a fully hermetic install check. Skips only when curl is unavailable (the child shells out to curl). Wires --selftest through args parsing, Config, help_text, the guide table, all four shell completions, smoke coverage (env-scrub and isolation assertions included), README/AGENTS.md/troubleshooting/ configuration docs, and CHANGELOG. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…attended onboarding tau setup never prompts and never reads stdin — the new flags make that contract explicit for devcontainers, dotfiles scripts, and CI: - `--yes`/`-y` approves all write steps; `--non-interactive` declares the unattended run. Both are recorded in the verdict as "non_interactive":true/"yes":true so scripts can assert on them. - Env equivalents honored at parse time with flag > env > detect precedence: TAU_YES, TAU_NONINTERACTIVE (truthy = 1/true/yes/on), TAU_SETUP_SHELL, TAU_SETUP_CLIENT (validated like the flags; invalid values exit 80). - CI is deliberately not auto-detected — scripts opt in explicitly. - Shared validSetupShell/validSetupClient validators + envTruthy helper; 5 new parse tests + an unattended() unit test. - Help text, embedded guide, all four completions, README, CHANGELOG, AGENTS.md, and docs/configuration.md env table updated. - 30 new smoke checks in the setup group: flag/env-triggered mode, flag beats env, falsy env ignored, invalid env -> 80, stdin-closed run. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts: # README.md # completions/tau.ps1 # src/config.zig # src/main.zig
# Conflicts: # CHANGELOG.md # scripts/smoke.sh
# Conflicts: # CHANGELOG.md # scripts/smoke.sh # src/args.zig
…or --selftest)
Adds a `first-run` job to the ci workflow that locks the documented
first-run path for every released platform (linux x86_64/aarch64, macos
x86_64/aarch64, windows x86_64):
- builds tau, stages it as a local release tree
(srv/latest/download/<asset> + SHA256SUMS.txt — the exact layout the
installers fetch), and installs it through the shipped installer —
install.sh on POSIX legs, install.ps1 on the Windows leg — against a
file:// TAU_BASE_URL so nothing touches the network;
- then drives scripts/e2e-first-run.{sh,ps1} against the INSTALLED binary
in a scratch HOME with every credential source scrubbed:
`tau setup --yes --offline` (unattended onboarding: config scaffolded,
verdict ok/yes/non_interactive), `tau doctor --offline --selftest`
fully credential-free (asserts the selftest check row reports ok — the
feature's promise — while the keyless verdict honestly exits non-zero),
and the same doctor run with a fake resolvable key (asserts exit 0).
The release workflow's install-smoke jobs now assert the same selftest
check row on the shipped artifacts, so published binaries are verified to
self-test too. A new `first-run` smoke group pins the drivers, the ci.yml
wiring, and runs the POSIX driver end-to-end against zig-out/bin/tau.
Branch carries the prerequisite chain merges: mago/task-222 (doctor
--selftest), mago/task-230 (setup --yes/--non-interactive), mago/task-182
(install.sh + install.ps1 + release.yml), mago/task-193 (ci matrix).
Verified: zig build test 392/392, full offline smoke 625/625, and the
complete install.sh file:// → e2e-first-run.sh chain run locally.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…the registered surface (task #236) Adds a golden-help smoke group that byte-locks `tau --help`, `tau -h`, and `tau --help-json` (version normalized to <VER>), plus a sorted --flag listing extracted from each shipped completion script (tests/golden/completions-<shell>.flags). Four unit tests in main.zig pin the structural contract both ways: every subcommand (`eq(argv[0], "…")`) and flag (`eq(…, "-…")`) literal extracted from args.zig plus flag_specs must appear in help_text and in all four embedded completion scripts; every --flag token a script offers must map back to a registered flag; and every `tau <sub> <action>` documented in help_text must be a real subcommand with a completable action. Verified both directions by injecting a bogus flag (both tests fail) and removing one (forward test fails). The merge of the task-233 and task-223 chains surfaced real drift the new checks now pin: completions lacked the `config` subcommand (fish/ps1), the `-xt` alias (zsh), `--raw` (bash/ps1), and `-y` (doctor). _golden_norm also normalizes the doctor report's build block (commit/target/date/zig) so onboarding goldens stay deterministic across builds. Regenerated golden-errors/golden-onboarding snapshots: the merged chain's envelopes now carry hint+docs and the embedded doctor report grew build metadata and the probe/selftest/permissions/completions checks. 455/455 unit tests; 898/899 offline smoke checks (1 skipped).
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Golden + structural locks for the
--helpoutput and the shipped shell completions against the registered command/flag surface, so doc/completion drift shows up as a test failure instead of a stale script.Stacked base: merges
mago/task-233(widest feature chain: doctor--probe/--selftest/--report/--json,setup --yes,version --verbose, installers, CI matrix) andmago/task-223(golden-test infra +configsubcommand chain). The union surfaced real drift the new checks now pin.What changed
golden-helpsmoke group (scripts/smoke.sh): byte-lockstau --help,tau -h, andtau --help-json(its"version"field normalized to<VER>), plus a sorted one-per-line--flaglisting extracted from each shipped script intotests/golden/completions-<shell>.flags.GOLDEN_UPDATE=1regenerates, same convention asgolden-errors/golden-onboarding.src/main.zig(run underzig build test):eq(argv[0], "…")subcommand inargs.zigappears inhelp_textand all four embedded completion scripts;eq(…, "-…")flag literal plusflag_specs(longs and shorts) is offered by every script — fish's-l/-s/-ospelling handled;--flagtoken a script offers must be a registered flag (fishset -lvariable lines excluded);tau <sub> <action>usage entry inhelp_textnames a real subcommand and a completable action.configsubcommand +show|validate|set|get|unset|editsubs and--mode/--rawadded to fish and ps1 (and to fish's no-subcommand gate);-xtalias added to zsh;--rawadded to bash;-yadded to bash/ps1 doctor flags;completions/README.mdcoverage table updated._golden_normnow also normalizes the doctor report'sbuildblock (commit/target/build_date/zig) so goldens stay deterministic across builds and runners.golden-errors/golden-onboardingsnapshots: the merged chain's error envelopes carryhint+docsand the embeddedtau setupdoctor report grewbuildmetadata plusconfig_permissions,shell_completions,provider_probes, andselftestrows.Verified
zig build test— 455/455 pass (was 451 on the merged base; +4 new tests)../scripts/smoke.sh(offline) — 898/899 checks, 1 skipped (pwshunavailable for the ps1 parse check).--zzz-bogusintotau.bashfails both the forward ("not completed") and reverse ("unregistered flag") tests; restoring returns green.config.zig, guide facts + test blocks inmain.zig, both smoke group sets);args.zigkeeps theargv_fullslice signature withvar argvfor the config-subcommand reslice.Closes #236 (mago task #236)