Skip to content

fix(ci): widen node workspace detection, refuse a silent pass (G-015) - #92

Merged
acamarata merged 1 commit into
mainfrom
p6/g015-ci-detection
Sep 12, 2026
Merged

acamarata merged 1 commit into
mainfrom
p6/g015-ci-detection

Conversation

@acamarata

Copy link
Copy Markdown
Contributor

Summary

  • nself-ci wired into nself-org/plugins ran only secrets:gitleaks and reported Overall: PASSED, because node workspace-member detection required a formal pnpm-workspace.yaml or package.json "workspaces" field. plugins has 5 nested package.json files and neither declaration, so the node stack contributed zero checks.
  • Adds a bounded fallback walk (discoverNestedMembers, gate_workspace.go) that discovers nested member packages when no workspace is declared (skips node_modules/dist/build/.git/etc). Declared workspaces still win and run via pnpm -r; implicit members run individually since pnpm can't recurse into packages it doesn't know about. Also fixes package.json "workspaces" support, previously dead code (the old lookup could never succeed).
  • GateResult gains Substantive/Skipped fields. Run() now refuses to report a pass when every gate that executed was non-substantive (secrets/gateway/eval only) — the exact shape of this bug, where the pre-existing "zero gates" guard didn't fire because gitleaks counted as a gate. Every script the node gate can't find anywhere gets an explicit SKIP entry naming the reason.
  • Split gate_runners.go/gate_helpers.go to stay under the repo's 300-line-per-file cap: node runners → gate_runners_node.go, workspace detection → gate_workspace.go.

Coordinates with #91 (workflow/docs wiring) without touching the same files — no conflict.

Verification (real output, this repo)

Before (git stash the fix, same repo):

Stacks: node
────────────────────────────────────────────────────────────
  secrets:gitleaks                PASS  (7.383s)
────────────────────────────────────────────────────────────
  Overall: PASSED  (7s)

After, fresh checkout with no node_modules (honest — deps were never installed, so it says so instead of lying):

Stacks: node
  secrets:gitleaks                            PASS
  node:lint                                   SKIP
    skipped: no "lint" script in package.json or any of 5 workspace member(s)
  node:typecheck (.workers/plugins-registry)  FAIL
  node:typecheck (free/feature-flags/sdk-ts)  FAIL
  node:typecheck (free/file-processing/ts)    FAIL
  node:typecheck (free/media-processing/ts)   FAIL
  node:test (.workers/plugins-registry)       PASS
  ...
────────────────────────────────────────────────────────────
  Overall: FAILED

After, deps installed (pnpm install per member) — real, pre-existing bugs in plugins the old gate never once ran a check against:

node:typecheck (free/feature-flags/sdk-ts)  FAIL  — real TS2345 type errors in src/index.ts
node:typecheck (free/file-processing/ts)    FAIL  — @nself/plugin-utils not resolvable (no workspace linking)
node:test (free/feature-flags/sdk-ts)       FAIL  — jest not configured for TS syntax
node:build (shared)                         PASS
────────────────────────────────────────────────────────────
  Overall: FAILED

None of this is invented — it's real signal the old gate never surfaced because it only ever ran gitleaks. Fixing those app-level bugs is separate, follow-on work.

Test plan

  • go build ./... && go vet ./... clean
  • go test ./... — 22 passed (12 pre-existing unchanged + 10 new), 0 failed
  • gofmt -l clean on every touched/added file
  • Ran the built binary against plugins before and after, pasted above
  • All new/changed files ≤ 300 lines, functions ≤ 50 lines

nself-ci wired into nself-org/plugins ran only secrets:gitleaks and still
reported "Overall: PASSED", because the node stack detector required a
formal pnpm-workspace.yaml or package.json "workspaces" field to find
member packages. plugins has 5 nested package.json files and neither
declaration, so the gate verified zero lines of code while looking green.

Detection: add a bounded fallback walk (discoverNestedMembers) that finds
nested package.json files when no workspace is declared, skipping
node_modules/dist/build/.git/etc. Declared workspaces (pnpm-workspace.yaml
or package.json "workspaces") still take priority and run via `pnpm -r`;
implicit members run individually since pnpm can't recurse into packages
it doesn't know are related. Also fixes package.json "workspaces" support,
which was previously dead code (loadPackageJSON only ever returns the
"scripts" sub-object, so the old type assertion could never succeed).

Silence: GateResult gains Substantive and Skipped fields. Run() now
refuses to pass when every executed gate is non-substantive (secrets scan,
gateway routing, eval) even though the old "zero gates" guard doesn't
fire — this is the exact G-015 shape (gitleaks ran, node contributed
nothing). Every script the node gate doesn't find gets an explicit Skipped
gate naming the reason, so a run is never silently missing a check.

Split gate_runners.go and gate_helpers.go to stay under the 300-line cap:
node-specific runners move to gate_runners_node.go, workspace detection to
gate_workspace.go.
@acamarata
acamarata merged commit 7970b40 into main Sep 12, 2026
30 checks passed
@acamarata
acamarata deleted the p6/g015-ci-detection branch September 12, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant