Skip to content

[mache-73b885] refactor(writeback): validate + lint via leyline v0.7.8 validate op — drop in-process tree-sitter from the write path#527

Merged
jamestexas merged 7 commits into
mainfrom
feat/mache-73b885-llo-078
Jul 15, 2026
Merged

[mache-73b885] refactor(writeback): validate + lint via leyline v0.7.8 validate op — drop in-process tree-sitter from the write path#527
jamestexas merged 7 commits into
mainfrom
feat/mache-73b885-llo-078

Conversation

@jamestexas

Copy link
Copy Markdown
Contributor

Summary

Completes bead mache-73b885 (items 3+4): the write-back path no longer parses with in-process CGO tree-sitter. grep smacker internal/writeback/ internal/linter/ tests/ → empty. PR-B (mache-37ae8b) is now sized at exactly 23 remaining sitter importers, all parse-side.

Pin: ley-line-open v0.7.5 → v0.7.8 (SHA-verified)

v0.7.8 ships both mache-blocking adds. Baseline regenerated in the same commit per the standing rule — dead_code 16 → 3: the 13 grandfathered identifier-as-VALUE false-positives (cobra RunE: handlers, suite factories) collapse now that the extractor emits those refs; the 3 survivors are the true positives the tree-sitter projection also flags.

Writeback validation → leyline validate op

  • internal/leyline/validate.go: typed client over the existing UDS machinery; codes against the errors[] wire (0-based row/col, byte ranges, MISSING zero-width); a response without the errors key is a hard "daemon too old, need ≥ v0.7.8" error — never a silent fallback.
  • internal/writeback/validate.go: same Validate signature + ValidationError shape (draft-mode diagnostics unchanged); ValidateWithAST returns the emit_ast payload.
  • Non-Go-daemon-set languages (.tf/.sql/.toml/...) now pass through unvalidated (documented + test-pinned; hclwrite remains HCL's structural check).

Linter → SQL over the same parse

internal/linter reimplements the nil-slice rule as SQL over the emit_ast rows (in-memory modernc sqlite; direct-child structure via the materialized-path node_id). mount_nfs runs validate+lint from ONE parse per write. Bonus: fixes the old rule's false positive on var x []T = v.

DiscoverOrStart spawns only the exact-pinned binary

Surfaced during this work: the daemon SPAWN path still did raw LookPath + unchecked cache stat (mache-0acdf6 drift) — a stale PATH leyline would be spawned and every write would draft with daemon-too-old. The spawn now routes through ResolveBinary (exact pin at every tier, SHA-verified download, MACHE_NO_LEYLINE respected). An already-running daemon is still honored (user-owned; wire handshake + per-op probes cover it). Spawn-branch tests seed pin-versioned stubs and can no longer hit the network.

Test infrastructure

internal/lltest: FakeDaemon (canned UDS wire) + StartPinnedDaemon (private arena/socket, skip-never-download). Unit tests cover the wire contract, position mapping, daemon-too-old, pass-through; gated e2e covers real broken-Go positions, emit_ast round trip, nil-slice lint, and the full write-back pipeline through GraphFS (all executed locally, none skipped). tests/integration_test.go no longer imports sitter.

Verification

Full task check green end-to-end; task smells passes with 10 ratchet findings burned down structurally rather than baselined; fresh SHA-verified 0.7.8 download exercised.

After this merges

mache-73b885 closes. PR-B (mache-37ae8b) deletes the remaining 23 sitter importers + CGO_ENABLED=0 releases, pending the language-coverage decision (leyline parses 11/28 registry languages).

🤖 Generated with Claude Code

…) + regen baseline

v0.7.8 ships the two mache-blocking adds: validate emit_ast (one parse
serves syntax validation + _ast/defs/refs SQL - the writeback+linter
migration carrier) and identifier-as-VALUE refs in the Go extractor.

Baseline regenerated against the new pin: dead_code 16 -> 3 - the 13
grandfathered false-positives (cobra RunE handlers, test-suite
factories) collapse exactly as predicted when ley-line-140307 shipped;
the 3 survivors are the true positives the tree-sitter projection also
flagged. Verified: fresh SHA-verified download, deterministic build.
…ne validate op (drop in-process tree-sitter)

Work items 3+4: the last two in-process CGO tree-sitter consumers on the
write-back path now ride the pinned leyline daemon (ley-line-open v0.7.8):

- internal/leyline: Validate client over SendOp for the daemon validate op,
  incl. the emit_ast extension (one parse -> syntax verdict + SQL-shaped
  _ast/defs/refs/imports rows in the response). Daemon acquired lazily per
  call via DiscoverOrStart; responses without the errors key (or without ast
  when emit was requested) are hard daemon-too-old errors, never silent.
- internal/writeback: Validate/ASTErrors keep their exact signatures and
  0-based ValidationError shape but delegate to the daemon; new
  ValidateWithAST returns the same-parse AST payload for the linter.
  Language set is now the daemon validate set (go/py/js/ts/tsx/rs/ex/exs);
  .tf/.hcl/.sql/.yaml/.md/.toml become pass-through (documented).
- internal/linter: nil-slice rule reimplemented as SQL over the emit_ast
  rows (in-memory modernc sqlite, direct-child via hierarchical node_id);
  LintAST consumes the write path's existing parse so mount_nfs runs ONE
  parse per write instead of two. The old rule's false positive on
  initialized slices (var x []T = v) is fixed by the expression_list check.
- cmd/mount_nfs.go: validate+lint folded into one ValidateWithAST call.
- tests/integration_test.go: sitter fixture parsing replaced by a
  hand-written functions/<name>/source topology; write-exercising tests
  gated on a private pinned daemon (never downloaded, skip when absent).
- internal/lltest: FakeDaemon (canned wire responses over UDS) and
  StartPinnedDaemon (SHA-pinned binary, isolated arena/socket) test doubles.

grep -rln smacker/go-tree-sitter internal/writeback/ internal/linter/ tests/
now returns nothing.
… + cover new exports

Smell-gate burndown for the previous commit: shared lltest.UsePinnedDaemon
replaces three per-package copies, StartPinnedDaemon fan-out split into
pinnedBinaryOrSkip/awaitSocket, table-driven LintAST + e2e verdict tests
replace near-duplicate bodies, and the new exports (ValidateContent,
PinnedBinaryVersion, FakeDaemon) get direct tests.
…nned binary

Surfaced by the writeback migration: the daemon SPAWN path still did a
raw LookPath + unchecked ~/.mache/bin stat (the mache-0acdf6 drift), so
a stale PATH leyline (0.7.3 on this very machine) would be spawned as
the daemon - and with the validate op requiring >= v0.7.8, every
write-back would draft with a daemon-too-old diagnostic. The spawn now
routes through ResolveBinary (PATH -> cache -> SHA-verified download,
exact pin at every tier; respects MACHE_NO_LEYLINE). An already-RUNNING
daemon (fast paths) is still honored as-is - it is the user's own; the
wire handshake and per-op probes cover it.

The three spawn-branch tests (socket-timeout / crash / clean-exit
during startup) now seed PIN-VERSIONED stubs and set MACHE_NO_LEYLINE
so tests can never hit the network.
…+ honest pass-through docs + infra/syntax distinction

Review findings on PR #527:

1. RESTORED HCL validation (was should-fix 1, taken as behavior not
   docs): broken HCL passed through unvalidated AND hclwrite.Format -
   a token formatter, not a validator - MANGLED it before splicing to
   the source file where pre-73b885 it drafted. HCL/Terraform now
   validates in-process via hclsyntax (pure Go, same hashicorp/hcl
   module), first-error ValidationError with 0-based positions.
   SupportedPath semantics = validated-at-all (daemon set + HCL).

2. Honest pass-through docs (should-fix 2): the public validate
   package and SupportedPath now state plainly that ~25 extensions the
   old grammar set covered (.c/.cpp/.java/.rb/.php/.kt/.lua/.sh/...)
   splice unvalidated until leyline grows grammars
   (ley-line-open-e5addb).

3. Infra vs syntax distinction (nit 2 + open questions): mount
   write-back prefixes _diagnostics with 'validator unavailable' for
   non-ValidationError failures; serve write_file reports status
   validator_unavailable instead of claiming validation_error.
1. The package header still carried the exact stale sentence should-fix
   1 targeted (HCL 'passes through, hclwrite remains the structural
   check') 80 lines above code doing the opposite - rewritten to the
   hclsyntax reality, with the LLO grammar bead (ley-line-open-e5addb)
   named as the recovery path for the unvalidated set.
2. The diagnostics flavor (ASTErrors / public ContentErrors) skipped
   the in-process HCL branch: broken HCL errored via Content() but
   produced EMPTY diagnostics. Routed through a shared hclErrors helper
   returning ALL error diagnostics (validateHCL keeps the first-error
   contract).
3. Tests the review noted missing: ContentErrors on broken HCL (public
   surface, no daemon), and write_file status=validator_unavailable on
   infra failure (dead socket + MACHE_NO_LEYLINE).
@jamestexas jamestexas merged commit 5af690f into main Jul 15, 2026
15 checks passed
@jamestexas jamestexas deleted the feat/mache-73b885-llo-078 branch July 15, 2026 22:09
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