Tags: GoCodeAlone/workflow
Tags
feat(module): add prevalidated rolling alias Add PrevalidatedRollingDriver and provider hook while preserving the legacy BlueGreenDriver contract for existing deploy_blue_green configs. Closes #1000.
fix: lockio ForStmt.Post must not fold into releaseSeen (#999) Downstream review (workflow-compute, backporting this exact ForStmt case into its own local guard test) found a real soundness gap in the Post folding this package shipped in #996 (v0.85.0): unlike Init/Cond (and RangeStmt's X, SwitchStmt's Tag, TypeSwitchStmt's Assign -- all of which execute unconditionally before any entry into their body), a for-loop's Post clause only runs after a completed, non-returning iteration. Folding a release call found in Post into releaseSeen before recursing into Body made the checker believe the body's first-iteration return path was already covered when it never is on that iteration -- a demonstrated false negative, the exact failure direction this checker exists to prevent. sawAcquire's fold from Post stays: that direction is safe (can only make the checker more suspicious of an unqualified return, matching the over-flag-over-under-flag design); it's specifically releaseSeen that must not fold from Post. New TestForLoopPostReleaseDoesNotMaskFirstIterationLeak proves the regression: fails against the pre-fix code with an empty violation list, passes with the fix. No other consumer of this package is known to be affected in practice (this is a newly-released package; the downstream backport that found this never itself shipped the bug to production, since it caught it in its own pre-merge review), but it's a real gap in a released package regardless. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Avoid locks across persistence I/O (#997) * fix: avoid locks across persistence I/O Refs GoCodeAlone/workspace#133 * fix: address workflow lock review Refs GoCodeAlone/workspace#133
feat(wfctl,lint): add doctor app probe and lock-across-I/O analyzer (#… …996) * feat(lint): add reusable lock-across-I/O analyzer (lockio) Generalizes a go/ast checker originally written inside workflow-compute's mutation lifecycle guard test into a go/analysis-style package parameterized by lock acquire/release method names, store I/O method names, and an allowlist. Ports both violation classes (restricted I/O outside a sanctioned caller; a return path reachable after acquiring a lock/lease with no release call on it) including the goroutine-opaque marker-traversal fix found in that checker's quality review: a release call fired only inside an unawaited `go func(){...}()` must not count as covering the return path. Exposes both FindViolations (for a host app's own shrink-only allowlist test) and NewAnalyzer (a real analysis.Analyzer for golangci-lint/go vet/multichecker integration). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(doctor): add wfctl doctor app deployed-app probe wfctl doctor (ADR 0052) only diagnoses the local checkout. Add an explicitly-online, read-only "wfctl doctor app <url>" subcommand that runs N sequential + M lightly-concurrent GET requests against a health path and reports per-request latency (p50/p99), failure-origin classification, and health flip-flop rate across the probe window. Classification distinguishes a platform-edge failure (the request never reached the app; a reverse proxy or load balancer answered with its own HTML error page) from an app-origin failure (the request reached the app, which returned its own structured JSON error) using content-type and body shape only — no provider-specific logic. Covered by fixtures for three real-world edge shapes: DigitalOcean App Platform, AWS ALB, and nginx default error pages, plus a transport-error class for requests that never got a response at all. Dispatched from the existing "doctor" command on the literal "app" subcommand, following the same flag conventions (--format text|json, --strict) as the rest of doctor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: document doctor app probe and lockio analyzer; add ADR 0054 Document "wfctl doctor app" flags/examples and failure-origin classes in docs/WFCTL.md, register the new lint/ top-level root in docs/REPO_LAYOUT.md's Main Roots table, and record ADR 0054 for both additions. ADR 0054 explicitly flags two things for maintainer sign-off rather than assuming them: "doctor app" is an online mode that goes beyond ADR 0052's checkout-only remit, and lint/lockio's path is a proposal (no analysis/ tooling package convention existed in this repo before this change). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(lockio): ground Class A fixtures in ecosystem-sweep shapes A cross-repo sweep of Workflow ecosystem code (team-lead, 2026-07-04; full inventory to land at workflow-compute's docs/validation/2026-07-04-ecosystem-lock-io-scan.md) found the same lock-across-I/O shape workflow-compute hit in at least nine instances beyond that incident, including a scheduler holding its lock across a persistence save, an authz module holding its mutex across a policy save while every request-path call contends for the same mutex, and a cloud provider driver holding its deployment mutex across a list call while health checks contend. Add three fixtures modeled on those shapes (anonymized method/field names, not the real identifiers) to prove Class A generalizes to plain sync.Mutex Lock()/defer Unlock() call sites, not just the error-returning acquire idiom the existing Class B fixtures exercise. Also document, in the package doc comment, that Class B checks release-path completeness and does not itself detect I/O between Lock() and a deferred Unlock() (which always covers every return path by construction) — that shape is Class A's job when the I/O method is listed as restricted, not Class B's. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: add CHANGELOG entries for doctor app probe and lockio analyzer Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(lockio): inspect for/switch header expressions for acquire/release returnPathWalker previously only inspected an IfStmt's Init/Cond before recursing into its body; ForStmt (Init/Cond/Post), RangeStmt (X), SwitchStmt (Init/Tag), and TypeSwitchStmt (Init/Assign) recursed using stale sawAcquire/releaseSeen state that hadn't accounted for their own header expressions. A return inside a for/switch body could go unflagged even though the critical section began in that header — a false negative found in Copilot review on the upstream PR. Extend all four cases to fold their header expressions into the running state before recursing, mirroring IfStmt's existing Init/Cond handling. Add regression fixtures for the for-loop and switch cases. Also fix a doc-comment typo ("Class ClassRestrictedIO" / "Class ClassUncoveredReturnPath" reads like a duplicated word). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(doctor): normalize health path and surface body-read failures Two Copilot findings on the upstream PR: - Health path concatenation assumed opts.HealthPath started with "/". "--health-path healthz" produced an invalid URL (e.g. "https://example.comhealthz") with no separator. Add normalizeHealthPath to insert the leading slash when missing. - io.ReadAll's error was ignored when reading the probe response body. A failed read (truncated connection, mid-stream reset) left body partially filled, and the probe was classified against that partial body as if it had read cleanly — misreporting a transport failure as healthy/platform-edge/app-origin depending on what had been read so far. Report a body-read failure as its own transport-error result instead. Also rename TestDoctorAppStrictExitsNonZeroOnWarn to TestDoctorAppStrictExitsNonZeroOnError (a third Copilot finding): its fixture is 0/1 healthy probes, which buildDoctorAppReport marks ERROR, not WARN. Add TestDoctorAppStrictExitsNonZeroOnGenuineWarn alongside it to actually cover the WARN case (partial degradation) the old name claimed but never exercised. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
feat(wfctl): add guarded repair command (#994) * docs: plan wfctl repair lifecycle * chore: lock scope for wfctl repair * feat(wfctl): add guarded repair command * docs(wfctl): document repair lifecycle * chore: complete wfctl repair scope lock * fix(wfctl): repair corrupt lockfiles
docs: clarify wfctl install lifecycle (#991) * docs: plan wfctl install lifecycle * docs: review wfctl install lifecycle plan * docs: align wfctl install plan manifest * chore: lock scope for wfctl install lifecycle * docs: clarify wfctl install lifecycle * docs: amend wfctl install lifecycle scope * docs: clarify tap formula verification * docs: record website snapshot scope * docs: improve wfctl checksum examples * docs: clarify project plugin install dir * docs: align wfctl quickstart examples * docs: guard browser checksum example * docs: fail closed on missing checksum rows * docs: match checksum assets exactly * docs: ensure wfctl install target exists * docs: normalize checksum filenames
PreviousNext