Nano Banana Pro
Agent skill for nano-banana-pro
- `cmd/`: CLI entrypoints for trace analysis (`analyze`, `collect`), deterministic builds (`determinize`), inspection (`inspect`), and sleeve demos.
Sign in to like and favorite skills
cmd/: CLI entrypoints for trace analysis (analyze, collect), deterministic builds (determinize), inspection (inspect), and sleeve demos.pkg/: core libraries (tracecheck, replay, interactive, tracegen, diff, util, etc.) with tests beside implementations.internal/: helper wiring for CLIs and lenses; mocks/ holds generated doubles.examples/: runnable scenarios such as examples/knative-serving; visualizer/ and analysis/ contain small scripts for rendering and post-processing traces.tracestore/ provides MinIO manifests for trace storage; webhook/ and sleevectrl/ host sample components with Dockerfiles and manifests.make test # runs go test ./... across the repo go test ./pkg/... # fast inner-loop unit tests for core libs make determinize # builds ./cmd/determinize into ./bin go run ./cmd/inspect --dump <file> # open a saved inspector dump
Use Go 1.24+. After dependency changes run
go mod tidy; before review run go fmt ./... (or gofmt -w) to keep imports and spacing clean.
Use 'bd' for issue tracking.
pkg/ and unit-test it there; prefer small helpers over wide structs.go test; many packages use Ginkgo/Gomega (sleevectrl/pkg, sleevectrl/test/e2e).sleevectrl/test/e2e. These were auto-generated by the Kubebuilder tool and are not actively being used.It(...)/Describe(...) blocks or TestXxx functions; table-driven cases are preferred in core libraries.pkg/tracecheck or pkg/replay to guard against path regressions.update file structure for determinize; wrap bodies near 72 chars and add a short Why/What when non-obvious.make test, targeted go test, e2e notes), and artifacts that help reviewers (trace dumps, inspector screenshots).When exploring controller behavior, the inspector can produce a DAG (directed acyclic graph) showing state transitions. This is useful for analyzing non-determinism and divergence points.
# From a dump file, output DOT to stdout (for LLM analysis) go run ./cmd/inspect --dump <dump.jsonl> --interactive=false # Write DOT to a file go run ./cmd/inspect --dump <dump.jsonl> --dot output.dot --interactive=false # Open in TUI with optional DOT export go run ./cmd/inspect --dump <dump.jsonl> --dot output.dot
The DOT output represents the exploration state graph:
ContentsHash (8-char alphanumeric)Example DOT snippet:
"2tkg7wfg" [label="abc123", shape=box, fillcolor="#e0e0e0"]; "2tkg7wfg" -> "def456" [label="KPA"]; "2tkg7wfg" -> "ghi789" [label="EndpointsController"];
This shows state
2tkg7wfg with two outbound edges - a divergence point where KPA and EndpointsController can both run, leading to different successor states.
To inspect the full resource state for a hash, grep the dump file:
grep "2tkg7wfg" dump.jsonl | head -1 | jq .
The dump contains full
ObjectVersions (all K8s resources) and PendingReconciles for each state, enabling detailed analysis of controller readsets/writesets at divergence points.
The dump structure is:
states[stateIdx].paths[pathIdx][stepIdx]
| Query | jq path |
|---|---|
| Get step 47 of state 0, path 0 | |
| Controller that ran step 47 | |
| Objects changed in step 47 | |
| Effects (CREATE/UPDATE/DELETE) | |
| State before step ran | |
| State after step ran | |
| YAML diffs for step | |
| Reconciles triggered by step | |
| Total steps in path 0 | `.states[0].paths[0] |
| All controller IDs in path 0 | |
| Final converged state objects | |
Looking up object content by hash:
# Find object content for a hash (objects are stored separately) jq '.objects[] | select(.hash.Value | startswith("abc123"))' dump.jsonl
The
kamera-analyze CLI provides tools for investigating divergence in exploration results. The approach is "backward-trace": start from known differences in converged states and trace backwards to understand root causes.
go build -o bin/kamera-analyze ./cmd/kamera-analyze
The
diff command compares converged states and identifies objects with different final values:
./bin/kamera-analyze diff <dump.jsonl>
Example output:
2 converged states with 3 differing object(s), 13 identical Endpoints/default/kamera-test-private: State state-0: 8e6fd09 State state-1: c950902 PodAutoscaler/default/kamera-test: State state-0: bc8e586 State state-1: eb2c2c3
The
report command shows which controller last wrote each differing object:
./bin/kamera-analyze report <dump.jsonl>
Example output:
Last write analysis for Endpoints/default/kamera-test-private: Path 0 (-> state state-0): Last write: step 25 by EndpointsController Final hash: 8e6fd09 Path 0 (-> state state-1): Last write: step 40 by EndpointsController Final hash: c950902
This tells you the controller wrote the same object at different steps (25 vs 40), indicating ordering divergence.
For more detailed investigation, use the
pkg/analysis package directly:
import "github.com/tgoodwin/kamera/pkg/analysis" // Load dump dump, _ := analysis.LoadDump("dump.jsonl") // Find differing objects diff := analysis.DiffConvergedStates(dump) // Analyze last write for a specific object result := analysis.AnalyzeLastWrite(dump, diff.DifferingObjects[0].Key) // Access StateBefore to see what the controller saw for _, pathResult := range result.ByPath { stateBefore := pathResult.LastWriteStep.StateBefore // Compare stateBefore across paths to understand why writes differed } // Check if a hash appears elsewhere in a path (Module 2) lifecycle := analysis.AnalyzeObjectLifecycle(dump, stateIdx, pathIdx, key, targetHash)
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until
git push succeeds.
MANDATORY WORKFLOW:
git pull --rebase bd sync git push git status # MUST show "up to date with origin"
CRITICAL RULES:
git push succeeds