Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
name: CI
# CI pipeline for vibe-check: build, test, vet, and lint.
# Runs on pushes to main and pull requests targeting main.
name: CI — Build, Test, and Lint

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- uses: actions/setup-go@v5
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod

Expand All @@ -31,13 +37,13 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- uses: actions/setup-go@v5
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod

- name: golangci-lint
uses: golangci/golangci-lint-action@v7
uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7
with:
version: latest
version: v2.12.2
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@
.unbound-force/
.muti-mind/
.mx-f/
# Go coverage output (generated by `go test -coverprofile`)
coverage.out
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/envoy-review-20260831T152907-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: envoy-review
author: jay-flowers
category: pattern
created_at: 2026-08-31T15:29:07Z
identity: envoy-review-20260831T152907-jay-flowers
tier: draft
---

Envoy code-review of vibe-check branch opsx/go-analyze (first public capability: `vibe-check analyze` CLI, JSON metrics, distributed via `go install ...@v0.1.0`). VERDICT: REQUEST CHANGES. Anchor HIGH: first-run error messages omit the spec+design-mandated "suggested remediation" — adapter.go:76 ("no Go packages found in %s") and resolve.go:64 ("unable to determine module path") print cause only, but analyze-command/spec.md:52 and design.md:288-290 both MUST require remediation (design even gives the go.mod example). MEDIUMs: (1) terminology split — help text/CHANGELOG say the tool analyzes Go "packages" but violation strings say `VIOLATION: module %q` where %q is a package import path, and the JSON schema uses ModuleGraph/modules[]/warnings[].module; "module" is a distinct Go concept so this misleads the Go audience (VB-003). Fix = use "package" in the Go CLI's human-readable strings while keeping ModuleGraph as the documented universal schema term (do NOT rename the public contract). (2) The competitive superlative "the Martin metrics suite that no single OSS tool currently computes for Go" is still live at AGENTS.md:9 (origin universal-coupling-model/proposal.md:3) — rivals goda/go-arch-lint make it risky; per prior Envoy reviews it becomes HIGH once it hits a README/announcement/pkg.go.dev. This branch is the publish moment. (3) proposal.md:17 over-promises `analyze [packages...]` but the shipped CLI is `analyze [path]` single-directory (MaximumNArgs(1); load pattern ./... hard-coded in resolve.go:52). (4) No README exists at all for a public go install release, and the public JSON contract (schema v1.1) has no external pointer/docs. Positive: --version format matches spec exactly (cobra default template + Version field), exit codes 0/1/2 consistent across spec/design/help/code, JSON-always-to-stdout well-communicated, schema is strict+self-describing. Recurring Envoy checklist for a project's first public release: (a) README present with install+usage+JSON-contract pointer+v0.1.0 limitations, (b) error messages on failure paths carry remediation, (c) one canonical term per concept across help/CHANGELOG/violations/JSON, (d) no unverified competitive superlatives in ANY public file (AGENTS.md counts), (e) stated stability posture for v0.1.0 output schema.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/envoy-review-20260831T163518-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: envoy-review
author: jay-flowers
category: decision
created_at: 2026-08-31T16:35:18Z
identity: envoy-review-20260831T163518-jay-flowers
tier: draft
---

Envoy VERIFICATION re-review (council iter 1) of vibe-check opsx/go-analyze — VERDICT flips REQUEST CHANGES → APPROVE. Prior blocking HIGH (non-actionable first-run errors) is RESOLVED: all four first-run paths now carry spec-mandated remediation (analyze-command/spec.md:52; design.md:290-292): adapter.go:97 'no Go packages found in %s — ensure the path is a Go module directory containing .go files and a go.mod'; adapter.go:108 total-load-failure appends 'run go build ./... … go mod download'; resolve.go:68 'verify the path is a valid Go module directory…'; resolve.go:78 'run go mod init if missing'. Prior MEDIUMs resolved: (b) absolute 'no single OSS tool' superlative removed from ALL shipping .md — AGENTS.md now 'few OSS tools compute for Go'; (c) proposal.md:17/29 corrected to analyze [path] (no [packages...] left in shipping artifacts); (d) README.md created with schema pointer at README.md:107 → metrics/modulegraph.schema.json; (a) terminology bridged via README.md:109-113 note (module==Go package in JSON). NEW residual MEDIUM (non-blocking, FA-001/FA-002): README.md:16-17 overstates the --version fallback as reporting 'a meaningful version, commit, AND date', but for `go install …@v0.1.0` (no ldflags) runtime/debug gives Main.Version only — vcs.revision/vcs.time are NOT stamped for module-cache builds, so output is 'vX (commit none, built unknown)'. CHANGELOG.md:33-34 is correctly scoped ('the reported version stays meaningful'); README + design.md:299 overstate. One-line README fix. Good foundations intact: --version format matches design.md:300 (cobra 'Name version' template + versionString '<v> (commit <h>, built <d>)'); exit codes 0/1/2 consistent; JSON-always-to-stdout written before threshold checks (analyze.go:100 before :104); schemaVersion 1.1 consistent everywhere. LOW residuals: README terminology note scoped to 'JSON output' doesn't cover stderr 'VIOLATION: module %q' strings (analyze.go:159/167/175); design.md:288 stale advice to 'scope to specific packages rather than ./...' impossible with single-path CLI (README limitation section is correct). Recurring Envoy pattern: on a first public release, verify the primary README's --version fallback claims against actual runtime/debug behavior — vcs stamping is absent for `go install pkg@version`.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260829T215310-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: gotcha
created_at: 2026-08-29T21:53:10Z
identity: go-analyze-20260829T215310-jay-flowers
tier: draft
---

When implementing Ce (efferent coupling) for a Go adapter, the Martin metrics definition requires counting ALL imports — standard library, third-party, and module-internal packages. The initial implementation excluded stdlib imports (packages with Module==nil) which caused a CRITICAL spec deviation. The correct implementation is simply `len(pkg.Imports)`. Ca (afferent coupling) only counts module-internal dependents since external consumers are not observable. This asymmetry (Ce counts everything, Ca counts only internal) is fundamental to the metrics model and must be documented in both code comments and test assertions. The spec review caught this in advance but implementation still deviated, underscoring the need for the code review council to verify spec-to-code alignment.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260829T215315-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: pattern
created_at: 2026-08-29T21:53:15Z
identity: go-analyze-20260829T215315-jay-flowers
tier: draft
---

The exitCodeError pattern is the correct way to handle process exit codes in cobra CLI applications without calling os.Exit directly in RunE handlers. Define a type `exitCodeError struct { code int; err error }` implementing Error() and Unwrap(), return it from RunE, and extract it with errors.As in main(). This preserves deferred cleanup (signal handlers, context cancellation), makes the full cobra execution path testable, and keeps os.Exit() isolated to main(). The RunAnalyze function (AP-002 testable entry point) returns the exit code in the result struct, while the cobra layer wraps it in exitCodeError for main() to process.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260829T215326-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: context
created_at: 2026-08-29T21:53:26Z
identity: go-analyze-20260829T215326-jay-flowers
tier: draft
---

For the vibe-check Go adapter, the go/packages load mode must include NeedTypesInfo in addition to NeedName|NeedImports|NeedTypes|NeedSyntax|NeedModule. The NeedTypesInfo flag is required for LCOM4 computation because the types.Info.Selections map is needed to resolve field accesses in method bodies — without it, the adapter cannot reliably determine which struct fields each method accesses, which is the foundation of the connected-component LCOM4 algorithm. The environment sanitization allowlist for go/packages should include GOPATH, GOROOT, GOMODCACHE, GOPROXY, GONOSUMCHECK, GOMOD but must NOT include GOFLAGS (which enables arbitrary flag injection into go list subprocesses, including -toolexec for command execution).
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260829T215336-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: pattern
created_at: 2026-08-29T21:53:36Z
identity: go-analyze-20260829T215336-jay-flowers
tier: draft
---

The go-analyze spec review went through 2 iterations across both spec and code review phases. Key review council patterns: (1) The Guard agent's CRITICAL finding about Ce/stdlib counting was the most impactful — it caught a fundamental metrics definition error that tests had encoded as correct behavior. (2) The Adversary caught GOFLAGS in the environment allowlist as a command injection vector — an important security insight since go/packages spawns subprocesses. (3) The SRE caught unpinned golangci-lint version (version: latest) which is a common CI reproducibility failure. (4) The Tester caught shallow test assertions — errors.Is checks for context wrapping and Warning field assertions that were missing. The pattern shows that multi-persona review catches different categories of issues that a single reviewer would miss.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260831T152549-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: gotcha
created_at: 2026-08-31T15:25:49Z
identity: go-analyze-20260831T152549-jay-flowers
tier: draft
---

In vibe-check's Go adapter, resolveReceiverType (internal/goadapter/lcom.go:99) has a latent correctness bug with ZERO test coverage: for generic pointer receivers `func (s *S[T]) M()`, the receiver expr is *ast.StarExpr{X: *ast.IndexExpr}, so the `case *ast.StarExpr` branch does `t.X.(*ast.Ident)` which FAILS (X is IndexExpr not Ident), falls through, and returns "" — silently dropping the method from computeLCOM4, corrupting the LCOM metric. The value-receiver `*ast.Ident` branch and the generic `*ast.IndexExpr`/`*ast.IndexListExpr` branches are also untested because every testdata fixture uses only plain pointer receivers `func (s *S)`. Gaze flagged this as CRAP 27.0 / 33.3% line coverage — the highest-CRAP gap in the branch. Fix: add a fixture (or table-driven unit test using go/parser) covering value receiver `func (t T)`, generic value `func (t T[P])`, generic pointer `func (t *T[P])`, and multi-param generic `func (t *T[P1,P2])`; then fix the StarExpr branch to recurse into IndexExpr/IndexListExpr. This is a determinism/correctness-mandate risk (AGENTS.md requires deterministic, correct metric computation).
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260831T152802-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: pattern
created_at: 2026-08-31T15:28:02Z
identity: go-analyze-20260831T152802-jay-flowers
tier: draft
---

Curator doc-gate review of vibe-check `opsx/go-analyze` (ships user-facing `vibe-check analyze` CLI, first working adapter). Key triage findings for future reviewers: (1) The content pipeline IS tracked — issues #18 (docs: README+CHANGELOG), #19 (blog), #22 (tutorial) all exist — so do NOT file duplicates; reference/refresh instead. (2) All three content issues have `labels: []`; the repo uses title prefixes (`docs:`/`blog:`/`tutorial:`) but never created the GitHub labels, so `gh issue list --label docs` returns EMPTY. Any agent following the AGENTS.md documentation gate (which searches by label) will falsely conclude no docs issue exists and file a duplicate. Fix: create+apply the labels. (3) Issue #18's README scope is STALE — it predates the CLI (from the universal-coupling-model change) and describes a LIBRARY install (`go get`), omitting `go install .../cmd/vibe-check@v0.1.0`, `vibe-check analyze`, threshold flags. CHANGELOG half of #18 is done; README half is not. (4) The competitive superlative "the Martin metrics suite that no single OSS tool computes for Go" (AGENTS.md:9, proposal Why) is unsubstantiated (rivals: goda, go-arch-lint) and will propagate into README/blog — Envoy previously flagged it as "HIGH the moment it's published". (5) go-analyze tasks.md Section 9 has NO README task — README deferred entirely to #18. Pattern: when a repo tracks content work by title-prefix instead of labels, the label-based doc-gate search silently breaks; verify labels exist AND that stale tracking issues cover the CURRENT user-facing surface, not a prior change's.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260831T163216-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: pattern
created_at: 2026-08-31T16:32:16Z
identity: go-analyze-20260831T163216-jay-flowers
tier: draft
---

Curator VERIFICATION re-review (council iter 1) of vibe-check `opsx/go-analyze` (ships user-facing `vibe-check analyze` CLI). Resolution status vs prior HIGH: (1) RESOLVED — README.md now created at repo root; comprehensive and correct for the CLI: `go install github.com/zero-dot-force/vibe-check/cmd/vibe-check@v0.1.0`, `analyze [path]`, all 6 flags + `--version`, exit codes 0/1/2, JSON output with schemaVersion 1.1 + `extensions` (go.interfaceWidth/go.interfaceProximity), pointer to metrics/modulegraph.schema.json, terminology note (package↔module), Known limitations, Apache 2.0. Crucially the shipped README does NOT contain the unsubstantiated 'no OSS tool computes Martin metrics for Go' superlative — FA-001 clean. (2) RESOLVED — CHANGELOG.md has [0.1.0] 2026-08-31 (Added/Changed), Keep-a-Changelog + SemVer + compare links. (3) CONFIRMED no GoDoc regression — cmd/vibe-check main.go/root.go/analyze.go all have identifier-first GoDoc on every exported symbol (TD-007); tasks.md 8.6 checked. STILL-OPEN external process caveats (cannot fix from code tree, ADVISORY not blocking): (a) `gh issue list --label docs` STILL returns EMPTY — labels never created; #18/#19/#22 still show `labels: []` and track via title-prefix only, so the AGENTS.md label-based doc-gate will keep falsely reporting 'no docs issue' → duplicate-filing risk; I cannot create labels (only issue list/view/create allowed). (b) Issue #18 body TEXT still stale — describes `go get` LIBRARY install + metrics-package scope, predates CLI; in-tree README supersedes it but the issue should be refreshed/split/closed before merge. (c) website-doc-sync and GoReleaser/release-automation issues NOT filed (proposal lists both as pre-merge TODOs). (d) v0.1.0 tag/release NOT verifiable from tree — README install + CHANGELOG release link depend on it (README honestly hedges this). (e) tasks.md Section 9 still has NO README line item (only 9.1 AGENTS.md, 9.2 CHANGELOG) though README shipped anyway. (f) blog #19 superlative ('first OSS tool… Why No One Computes…') still lives in the issue + AGENTS.md:9 ('which few OSS tools compute') — Herald/Envoy must fact-check at authoring (rivals: goda, go-arch-lint). VERDICT: APPROVE — blocking HIGH resolved, no regressions; remaining items are advisory external-process caveats for the human.
10 changes: 10 additions & 0 deletions .uf/dewey/learnings/go-analyze-20260831T163321-jay-flowers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
tag: go-analyze
author: jay-flowers
category: decision
created_at: 2026-08-31T16:33:21Z
identity: go-analyze-20260831T163321-jay-flowers
tier: draft
---

Adversary council re-review (iteration 1) of vibe-check branch opsx/go-analyze: prior MEDIUM (ExternalAdapter trust boundary under-enforced schema) is RESOLVED via two-layer enforcement. metrics/validate.go now enforces numeric ranges through a moduleNumber helper (instability/abstractness/distance in [0,1]; ca/ce/lcom/exportedTypes/abstractTypes >= 0, plus number-type checks), and metrics/external.go decodes the subprocess response with json.Decoder.DisallowUnknownFields() enforcing additionalProperties:false. Key insight: integer-ness (schema says ca/ce/lcom are integer) is NOT enforced by Validate() alone (moduleNumber accepts any float64), but the strict decoder rejects fractional values because Module.Ca etc. are Go int fields — so the ExternalAdapter boundary (Validate THEN Decode) is airtight, while the standalone public metrics.Validate() has a minor integer-fidelity gap for external callers (LOW). DisallowUnknownFields correctly flattens the embedded Module struct (promoted fields path/name/ca/ce/exportedTypes/abstractTypes) and does NOT restrict the extensions map[string]any (matches open-object schema). packageEnvAllowlist (resolve.go) excludes GOFLAGS with regression test TestPackageEnvAllowlist_ExcludesInjectionVectors that locks exact set+size. Remaining advisories all LOW/non-blocking: (1) binaryPath unvalidated in NewExternalAdapter but caller-supplied trusted config and not wired to CLI, (2) go/packages type-checking can execute code via cgo/-toolexec on untrusted input — undocumented but intended use is self-analysis of trusted code, (3) recursive Tarjan strongConnect has no depth guard (stack overflow only on pathological graphs). VERDICT: APPROVE.
Loading
Loading