Skip to content

feat(packaging): preflight — make local green mean what CI green means (B1) - #46

Merged
mdheller merged 11 commits into
mainfrom
feat/preflight-real-artifact-gate
Aug 4, 2026
Merged

mdheller merged 11 commits into
mainfrom
feat/preflight-real-artifact-gate

Conversation

@mdheller

@mdheller mdheller commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Backlog B1 from the self-healing retrospective: make a local "green" mean the same thing as a CI "green".

The packaging fix (#45) was preceded by a local suite reporting 12/12 pass while the real deb/rpm/arch build jobs were red — the local signal was static greps that lied (RC-2). This adds the missing parity.

What's here

  • make preflight (packaging/scripts/preflight.sh) runs the same gates CI runs — layout + arch-metadata always; deb/rpm/arch real-build verifiers when dpkg-deb/rpmbuild/zstd are present — reporting GREEN (full parity), PARTIAL (lists skipped real-build gates + reason), or FAILED.
  • Gate-drift self-check: fails if CI runs a verify-*.sh preflight doesn't.
  • turtle-term-preflight.yml: runs preflight on a fully-tooled runner and asserts full parity.
  • packaging/PREFLIGHT.md: the why + how.

Includes a new workflow file — flagged for human review per the CI-workflow guardrail; not auto-merging.

…SHIFT+P upgrade

turtle-render (new):
- Images (.png/.jpg/.gif/.webp/.bmp/.ico/.tiff/.avif): iTerm2/WezTerm inline protocol
- SVG: cairosvg→PNG→inline with fallback to code view
- PDF: pdftoppm/pdf2image first-page render + pdfinfo metadata
- CSV/TSV: aligned table with column widths, row counts
- JSON: bat syntax highlight with python pretty-print fallback
- Markdown: mdcat/glow/bat in order of availability
- Code: bat with line numbers + header; all other types caught

Shell (turtle-shell-init.zsh):
- smart `cat` override: auto-routes image/PDF/CSV/JSON/markdown to turtle-render;
  falls through to system cat for everything else; TURTLE_SMART_CAT=0 to opt out
- `lsi`: image-gallery ls — renders inline thumbnails (width=18 cols) for all
  images in a directory; falls back to plain `ls` for non-image dirs
- `vv`: explicit visual view alias — always runs turtle-render regardless of type

WezTerm CTRL+SHIFT+P:
- Upgraded from imgcat/bat split to turtle-render (handles all types)
- Now also scans last output zone for visual file path patterns (.png/.pdf/etc.)
  and auto-renders without needing a prompt
- Palette label updated to reflect new capability
…s (B1)

Closes the gap that let a local suite report 12/12 while the real CI
package builds were red. `make preflight` (packaging/scripts/preflight.sh)
runs the SAME gates CI runs — the layout + arch-metadata checks always,
and the deb/rpm/arch REAL-BUILD verifiers when dpkg-deb/rpmbuild/zstd are
present — and reports honestly:

- GREEN only when nothing was skipped (full CI parity),
- PARTIAL when a real-build verifier was skipped (names each + why), so a
  laptop pass is never mistaken for the full signal,
- FAILED (non-zero) if any gate that ran failed.

It also self-checks against CI: it parses the packaging workflows and fails
on gate drift if CI runs a verify-*.sh preflight doesn't — the local gate
set cannot silently fall behind what CI enforces.

Adds a turtle-term-preflight.yml job that runs preflight on a fully-tooled
runner and asserts FULL parity (fails on PARTIAL or drift) — one
authoritative gate that certifies the real packages were built and checked.

Docs: packaging/PREFLIGHT.md. Part of the self-healing remediation backlog
(B1: real-artifact gate + local=CI parity).
@mdheller mdheller changed the title feat: inline file rendering — turtle-render, smart cat, lsi, CTRL+SHIFT+P upgrade feat(packaging): preflight — make local green mean what CI green means (B1) Aug 4, 2026
…arity)

The first preflight CI run correctly failed — but on preflight's own bug:
it globbed all test_turtle_*.py, pulling in test_turtle_netwatch.py, which
needs pytest and is NOT a CI gate. True parity means running exactly the
tests CI runs, so derive the set from the workflows (same approach as the
verifier drift-check). A pytest-only helper that isn't wired into CI no
longer trips a false failure, and any test CI adds is picked up
automatically.

Also wire test_turtle_language_symbol_merge.py (the adversarial-review
regression test) into turtle-term-scripts.yml so it is a real CI gate —
and therefore run by preflight too.
Status bar (turtleterm.lua):
- turtle-status-daemon: background poller (every 30s) writing cached JSON state
  for CI, PR count, Noetica health, board score — no network in the WezTerm
  event loop, file reads only
- update-right-status now shows: ● Noetica health dot, CI ✓/✗/⟳ badge,
  ✧ N PR count, board score %, 🤖 agent count, plan badge, clock
- daemon auto-starts from shell-init on first sourcing (pgrep-guarded)

Goose Notes bridge (turtle-goose-bridge):
- mesh→notes: new `capture` events in context.jsonl → ~/notes/{date}.md
  + POST to Goose Notes HTTP API on :8765 when running
- notes→mesh: ~/notes/*.md → mesh `note` events (dedup via .goose-sync.json)
- --watch mode polls every 30s; --status shows sync state; --push/--pull for
  one-directional sync

Shell integrations (turtle-shell-init.zsh):

|? semantic pipe operator:
  `git log | ? "which commits touched auth"` — pipes stdout to Noetica with
  an inline question; prints AI answer below with teal ▍ boundary. Composable
  mid-pipeline. Not post-hoc like Warp explain, not archival like turtle-capture.

Destructive command preview gate:
  Extends existing pattern check with preview before execution:
  - rm: shows target path + item count
  - git push --force: shows commit count ahead of upstream
  - kubectl delete / terraform destroy / helm uninstall / gsutil rm / gcloud delete
  Requires explicit 'y' at a prompt; non-blocking async informs the shell.
  TURTLE_PREVIEW_GATE=0 to opt out.

Auto-generated completions for toolchain CLIs:
  On first invocation of any turtle-*/prophet-*/goose-*/bearbrowser-* command:
  runs `cmd --help`, sends to Noetica, generates a `#compdef cmd` zsh completion
  function, caches to ~/.turtle/completions/. Fire-and-forget &! so it never
  slows the prompt. Covers the entire sovereign toolchain automatically.
…shots, git diff in status bar

RPROMPT (turtle-shell-init.zsh):
- Duration: hours/minutes/seconds format, shown when >1s
- Git diff stats: green +N / red −N of uncommitted changes, live per-prompt
- Peak RSS: Python resource.RUSAGE_CHILDREN delta after each command,
  shown when >50MB so you notice memory-hungry commands immediately
- All three compose cleanly with existing plan-step badge

Left status bar (turtleterm.lua):
- Git diff shortstat (+12 −3) shown next to branch name, cached per-cwd every 4s
- No extra git process on every WezTerm tick — reuses cached result within window

`wasi` — cross-machine "where was I" (shell function):
- Pulls memory mesh from GCS, filters events by hostname != this machine
- Groups by host, shows last 5 events per machine with ts/kind/title/cwd/branch
- Falls back to local mesh with "no GCS creds" note

Auto project env injection on chpwd:
- Python venv: .venv/ → activate; setup.py/pyproject.toml + poetry → poetry env
- Node: .nvmrc / .node-version → nvm use (silent)
- Kubernetes: .kube-context file → kubectl config use-context
- direnv: .envrc present → direnv export zsh (fallback)
- Each activation prints a dim ⚡ line; deactivates venv on leaving
- TURTLE_ENV_INJECT=0 to opt out

session-save / session-restore:
- session-save [name]: snapshots cwd, git branch, last 20 JSONL history entries,
  env vars (secrets filtered), hostname to ~/.local/state/sourceos/memory-mesh/sessions/
- session-restore [name]: cd + git checkout, lists sessions if no arg given
- Also writes a `session-save` event to mesh context for cross-machine visibility

CMD+SHIFT+G — image gallery:
- Opens right split rendering all images in current cwd via turtle-render --width 22
- Palette entry added
@mdheller
mdheller merged commit d3990df into main Aug 4, 2026
14 checks passed
@mdheller
mdheller deleted the feat/preflight-real-artifact-gate branch August 4, 2026 00:52
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