@@ -301,6 +301,84 @@ trond network destroy pn --confirm pn -o json
301301
302302---
303303
304+ ## Workflow 5 — Build java-tron from source
305+
306+ Use when the user wants a custom build: a fork, an unreleased patch,
307+ a wired-in profiler. The build pipeline is content-addressed by
308+ git revision + builder image digest + gradle task + args, so
309+ repeated ` apply ` calls against an unchanged source are sub-second
310+ cache hits, not full recompiles.
311+
312+ Trigger: the intent file carries a ` build: ` block under the node.
313+ ` trond apply ` invokes the build automatically; you rarely need to
314+ call ` trond build ` directly except for cache mgmt or pre-warming.
315+
316+ ``` bash
317+ # 1. Validate the intent like any other.
318+ trond config validate my-dev.yaml -o json
319+
320+ # 2. Preflight gains LOCAL-side `build-*` checks when build: is set:
321+ # build-git, build-source-<dir>, build-docker-local (if builder=docker),
322+ # build-host-jdk + build-host-gradlew-<dir> (if builder=host).
323+ # Target-side checks (jdk, disk, ports) still run too.
324+ trond preflight --intent my-dev.yaml -o json
325+
326+ # 3. Apply — the build kicks off automatically before the deploy step.
327+ # Cold first build: 3-5 min for java-tron. Cached: ~50ms.
328+ trond apply --intent my-dev.yaml -o json
329+ # Output now carries a `build` field alongside the usual envelope:
330+ # {"name":"...", "result":"created",
331+ # "build": {"cache_key":"abc12345-bd…+dirty-7f2a…",
332+ # "source_revision":"8f4e2a3c…",
333+ # "dirty": true,
334+ # "artifact_path":"/home/.../FullNode.jar",
335+ # "sha256":"160185…", "cache_hit": false,
336+ # "duration_ms": 215000},
337+ # ...}
338+
339+ # 4. Survey what's in the cache.
340+ trond build list -o json
341+ # Output: {"count": N, "entries": [{cache_key, artifact_kind, size_bytes,
342+ # orphaned, source_revision, ...}, ...]}
343+
344+ # 5. Inspect a specific entry — full key OR unambiguous prefix.
345+ trond build inspect 8f4e2a3c -o json
346+ # Returns the single entry (same shape as build_list entries).
347+ # Errors: NOT_FOUND (no match), AMBIGUOUS_PREFIX (multi-match;
348+ # message lists candidates).
349+
350+ # 6. Prune. Filters AND together; dry-run is the default — only
351+ # --confirm performs deletions.
352+ trond build prune --older-than 168h -o json # dry-run
353+ trond build prune --older-than 168h --keep-last 3 --confirm # delete
354+ trond build prune --orphan --confirm # GC
355+ ```
356+
357+ ### Key invariants for agents
358+
359+ - The build runs on the LOCAL machine even when ` target.type: ssh ` —
360+ trond ` scp ` s the JAR over with an SHA256-skip fast-path. No source
361+ bytes ever leave the host.
362+ - ` build.builder: host ` works without docker but pins the cache key
363+ to ` sha256(java -version) ` , so a JDK upgrade orphans prior entries
364+ (orphans are surfaced in ` list --include-orphans ` and cleaned by
365+ ` prune --orphan ` ).
366+ - The CLI rejects ` --keep-last N --confirm ` without an explicit
367+ scoping filter (` --all ` , ` --orphan ` , or ` --older-than > 0s ` ).
368+ This is a footgun guard: ` --keep-last 1 --confirm ` would wipe
369+ every entry except the newest, which is rarely what the user
370+ meant.
371+ - Build * execution* is intentionally NOT exposed via MCP — it's a
372+ long-running, stderr-streaming operation. The CLI's ` -o json `
373+ stream is the right surface. The cache-mgmt tools (` build_list ` ,
374+ ` build_inspect ` , ` build_prune ` ) ARE exposed via MCP — see below.
375+
376+ Full walkthrough including image artifacts, cross-arch builds, and
377+ the ` image_strategy: jar-wrap ` variant for stock java-tron:
378+ [ ` specs/002-trond-build-pipeline/quickstart.md ` ] ( specs/002-trond-build-pipeline/quickstart.md ) .
379+
380+ ---
381+
304382## Test-harness primitives (for agents driving CI / fuzz / chaos)
305383
306384These exist for agents that drive trond programmatically rather than
@@ -401,6 +479,18 @@ topic; don't paraphrase from training data.
401479 Use the upcoming ` snapshot prune ` (or just ` rm ` the JSON+log pair
402480 when the job is ` state=stopped ` ).
403481
482+ 9 . ** Don't ` rm -rf ` the build cache directory** (` $TROND_STATE_DIR/builds ` ,
483+ defaulting to ` ~/.trond/builds ` ) to clean it. Use ` trond build prune `
484+ so the manifests, image side-files, and docker-stored images all get
485+ reclaimed consistently. Manual ` rm ` leaves dangling docker layers
486+ and orphaned manifests that confuse the next ` trond build list ` .
487+
488+ 10 . ** Don't pass ` --keep-last N --confirm ` alone to prune** . The CLI
489+ rejects it for safety: that combo deletes everything except the N
490+ newest entries, which is rarely the intent. Combine with ` --all `
491+ (to acknowledge near-wipe) or scope with ` --orphan ` / ` --older-than ` .
492+ Same guard applies to the MCP ` build_prune ` tool.
493+
404494---
405495
406496## Schema discovery
@@ -444,7 +534,7 @@ Configure once in your client. Example for Claude Desktop
444534}
445535```
446536
447- The server registers 16 tools (read-only unless marked):
537+ The server registers 19 tools (read-only unless marked):
448538
449539- ** inspection** (3): ` list ` , ` status ` , ` inspect `
450540- ** diagnostic** (4): ` doctor ` , ` version ` , ` health ` , ` diagnose `
@@ -453,6 +543,10 @@ The server registers 16 tools (read-only unless marked):
453543- ** snapshot** (4): ` snapshot_sources ` , ` snapshot_list ` , ` snapshot_jobs ` ,
454544 ` snapshot_download ` (destructive, emits MCP progress notifications)
455545- ** knowledge** (2): ` knowledge_list ` , ` knowledge_get `
546+ - ** build** (3): ` build_list ` , ` build_inspect ` , ` build_prune `
547+ (destructive — dry-run by default; ` confirm=true ` actually deletes).
548+ Build * execution* is NOT exposed via MCP; call the CLI directly
549+ for that (see Workflow 5).
456550
457551Destructive tools carry the MCP ` destructiveHint ` annotation so MCP
458552clients prompt the user. The server's ` Instructions ` field
0 commit comments