Skip to content

Commit c64071e

Browse files
feat(cli): build offline artifact packs
1 parent f1bade8 commit c64071e

12 files changed

Lines changed: 1377 additions & 6 deletions

File tree

.beads/issues.jsonl

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

acfs/zsh/acfs.zshrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,17 @@ acfs() {
412412
return 1
413413
fi
414414
;;
415+
offline-pack|artifact-pack)
416+
if [[ -f "$acfs_home/scripts/lib/offline_artifact_pack.sh" ]]; then
417+
bash "$acfs_home/scripts/lib/offline_artifact_pack.sh" "$@"
418+
elif [[ -x "$acfs_bin" ]]; then
419+
"$acfs_bin" offline-pack "$@"
420+
else
421+
echo "Error: offline_artifact_pack.sh not found"
422+
echo "Re-run the ACFS installer to get the latest scripts"
423+
return 1
424+
fi
425+
;;
415426
landing-plane|land|closeout)
416427
if [[ -f "$acfs_home/scripts/lib/landing_plane.sh" ]]; then
417428
bash "$acfs_home/scripts/lib/landing_plane.sh" "$@"
@@ -493,6 +504,7 @@ acfs() {
493504
echo " session List/export/import agent sessions (cass)"
494505
echo " support-bundle Collect diagnostic data for troubleshooting"
495506
echo " provisioning-packet Validate/render provider packet JSON"
507+
echo " offline-pack Build verified offline artifact packs"
496508
echo " landing-plane Closeout checklist for gates, Beads, Mail, and reservations"
497509
echo " provenance Installed-tool provenance ledger for diagnostics"
498510
echo " changelog Show recent changes (--all, --since 7d, --json)"

docs/operations/offline-artifact-pack.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,26 @@ Future pack builder commands must:
337337
module counts
338338
- emit JSON output for CI and support
339339

340+
## Builder Command
341+
342+
`acfs offline-pack build` prepares `acfs-offline-pack/` from a connected
343+
machine:
344+
345+
```bash
346+
acfs offline-pack build --output /tmp/acfs-pack --module stack.rch
347+
acfs offline-pack build --dry-run --json
348+
```
349+
350+
The command resolves modules from `acfs.manifest.yaml`, includes only modules
351+
with `verified_installer` metadata, reads source URLs and SHA256 values from
352+
`checksums.yaml`, downloads each approved installer into `artifacts/`, verifies
353+
the downloaded bytes, copies the local ACFS scripts/configuration needed for
354+
offline verification, and writes `manifest.json`.
355+
356+
Default behavior is fail-closed: any missing checksum entry, unsupported module,
357+
download failure, timeout, or hash mismatch aborts the pack. `--best-effort`
358+
must be set explicitly to write a diagnostic pack with failure metadata.
359+
340360
## Consumer Requirements
341361

342362
Future installer consumers must:

install.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7093,6 +7093,7 @@ finalize() {
70937093
try_step "Installing swarm_inventory.sh" install_asset "scripts/lib/swarm_inventory.sh" "$ACFS_HOME/scripts/lib/swarm_inventory.sh" || return 1
70947094
try_step "Installing landing_plane.sh" install_asset "scripts/lib/landing_plane.sh" "$ACFS_HOME/scripts/lib/landing_plane.sh" || return 1
70957095
try_step "Installing provenance.sh" install_asset "scripts/lib/provenance.sh" "$ACFS_HOME/scripts/lib/provenance.sh" || return 1
7096+
try_step "Installing offline_artifact_pack.sh" install_asset "scripts/lib/offline_artifact_pack.sh" "$ACFS_HOME/scripts/lib/offline_artifact_pack.sh" || return 1
70967097
try_step "Installing changelog.sh" install_asset "scripts/lib/changelog.sh" "$ACFS_HOME/scripts/lib/changelog.sh" || return 1
70977098
try_step "Installing export-config.sh" install_asset "scripts/lib/export-config.sh" "$ACFS_HOME/scripts/lib/export-config.sh" || return 1
70987099
try_step "Installing cheatsheet.sh" install_asset "scripts/lib/cheatsheet.sh" "$ACFS_HOME/scripts/lib/cheatsheet.sh" || return 1

packages/manifest/src/generate.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ const INTERNAL_SCRIPTS_TO_CHECKSUM = [
360360
'scripts/lib/update.sh',
361361
'scripts/lib/doctor.sh',
362362
'scripts/lib/doctor_fix.sh',
363+
'scripts/lib/offline_artifact_pack.sh',
363364
'scripts/lib/autofix.sh',
364365
'scripts/lib/install_helpers.sh',
365366
'scripts/lib/logging.sh',

scripts/completions/_acfs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ _acfs() {
9090
'-h[Show help message]' \
9191
'--help[Show help message]'
9292
;;
93+
offline-pack|artifact-pack)
94+
_arguments \
95+
'1: :((build\\:Build\\ verified\\ offline\\ artifact\\ pack))' \
96+
'--json[Emit machine-readable JSON]' \
97+
'--markdown[Emit human-readable output]' \
98+
'--output[Output directory]:directory:_files -/' \
99+
'--module[Manifest module id to include]:module id:' \
100+
'--dry-run[Print resolved plan without writing files]' \
101+
'--best-effort[Write diagnostic pack after download failures]' \
102+
'--source-root[ACFS source root]:directory:_files -/' \
103+
'--manifest-file[Manifest YAML file]:file:_files' \
104+
'--checksums-file[checksums.yaml file]:file:_files' \
105+
'--arch[Target architecture]:architecture:(x86_64 aarch64)' \
106+
'--ubuntu-version[Target Ubuntu version]:version:' \
107+
'--timeout[Per-download timeout in seconds]:seconds:' \
108+
'--expires-days[Pack expiry window in days]:days:' \
109+
'-h[Show help message]' \
110+
'--help[Show help message]'
111+
;;
93112
swarm)
94113
_arguments -C \
95114
'1: :_acfs_swarm_commands' \
@@ -443,6 +462,8 @@ _acfs_commands() {
443462
'swarm_inventory:Local host inventory report/import/export/validate'
444463
'provisioning-packet:Validate/render provider provisioning packet JSON'
445464
'provider-packet:Validate/render provider packet JSON'
465+
'offline-pack:Build verified offline artifact packs'
466+
'artifact-pack:Build verified offline artifact packs'
446467
'coordinate:Coordination preflight helpers'
447468
'coord:Coordination helpers (alias for coordinate)'
448469
'cheatsheet:Command reference (aliases, shortcuts)'

scripts/completions/acfs.bash

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ _acfs_completions() {
88
local cur prev words cword
99
_init_completion || return
1010

11-
local commands="newproj new services svc services-setup setup doctor check session sessions update status continue progress info i capacity cap policy-lint policy_lint credential-preflight credential_preflight secrets-preflight secrets_preflight swarm swarm-plan swarm_plan swarm-status swarm_status swarm-simulate swarm_simulate swarm-packet swarm_packet swarm-assign swarm_assign swarm-convergence swarm_convergence swarm-calibration swarm_calibration swarm-inventory swarm_inventory provisioning-packet provider-packet coordinate coord cheatsheet cs changelog changes log export-config export dashboard dash support-bundle bundle version help"
11+
local commands="newproj new services svc services-setup setup doctor check session sessions update status continue progress info i capacity cap policy-lint policy_lint credential-preflight credential_preflight secrets-preflight secrets_preflight swarm swarm-plan swarm_plan swarm-status swarm_status swarm-simulate swarm_simulate swarm-packet swarm_packet swarm-assign swarm_assign swarm-convergence swarm_convergence swarm-calibration swarm_calibration swarm-inventory swarm_inventory provisioning-packet provider-packet offline-pack artifact-pack coordinate coord cheatsheet cs changelog changes log export-config export dashboard dash support-bundle bundle version help"
1212

1313
# Subcommand-specific flags
1414
local newproj_flags="-i --interactive --no-br --no-claude --no-agents -h --help"
@@ -29,6 +29,7 @@ _acfs_completions() {
2929
local swarm_calibration_flags="--json --markdown --artifact-dir --rch-file -h --help"
3030
local swarm_inventory_flags="report import export validate --json --markdown --inventory --input --output --format --artifact-dir -h --help"
3131
local provisioning_packet_flags="--json --markdown --file --packet -h --help"
32+
local offline_pack_flags="build --json --markdown --output --module --dry-run --best-effort --source-root --manifest-file --checksums-file --arch --ubuntu-version --timeout --expires-days -h --help"
3233
local coordinate_subcommands="doctor preflight help"
3334
local cheatsheet_flags="--json"
3435
local changelog_flags="--all --since --json -h --help"
@@ -49,7 +50,7 @@ _acfs_completions() {
4950
local cmd=""
5051
for ((i=1; i < cword; i++)); do
5152
case "${words[i]}" in
52-
newproj|new|services|svc|services-setup|setup|doctor|check|session|sessions|update|status|continue|progress|info|i|capacity|cap|policy-lint|policy_lint|credential-preflight|credential_preflight|secrets-preflight|secrets_preflight|swarm|swarm-plan|swarm_plan|swarm-status|swarm_status|swarm-simulate|swarm_simulate|swarm-packet|swarm_packet|swarm-assign|swarm_assign|swarm-convergence|swarm_convergence|swarm-calibration|swarm_calibration|swarm-inventory|swarm_inventory|provisioning-packet|provider-packet|coordinate|coord|cheatsheet|cs|changelog|changes|log|export-config|export|dashboard|dash|support-bundle|bundle|version|help)
53+
newproj|new|services|svc|services-setup|setup|doctor|check|session|sessions|update|status|continue|progress|info|i|capacity|cap|policy-lint|policy_lint|credential-preflight|credential_preflight|secrets-preflight|secrets_preflight|swarm|swarm-plan|swarm_plan|swarm-status|swarm_status|swarm-simulate|swarm_simulate|swarm-packet|swarm_packet|swarm-assign|swarm_assign|swarm-convergence|swarm_convergence|swarm-calibration|swarm_calibration|swarm-inventory|swarm_inventory|provisioning-packet|provider-packet|offline-pack|artifact-pack|coordinate|coord|cheatsheet|cs|changelog|changes|log|export-config|export|dashboard|dash|support-bundle|bundle|version|help)
5354
cmd="${words[i]}"
5455
break
5556
;;
@@ -89,6 +90,10 @@ _acfs_completions() {
8990
mapfile -t COMPREPLY < <(compgen -W "$provisioning_packet_flags" -- "$cur")
9091
return
9192
;;
93+
offline-pack|artifact-pack)
94+
mapfile -t COMPREPLY < <(compgen -W "$offline_pack_flags" -- "$cur")
95+
return
96+
;;
9297
swarm)
9398
local swarm_cmd=""
9499
for ((j=i+1; j < cword; j++)); do

scripts/generated/internal_checksums.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
declare -gA ACFS_INTERNAL_CHECKSUMS=(
1111
[scripts/lib/security.sh]="34a72de448d98229913465ad5914d19f9d17d8921b33f5438ef8bb0e1ef9fb60"
1212
[scripts/lib/agents.sh]="66fac24c48c9ce7d17ae213ff2f8669a1902e77f01266f4eeaccdcef09e02856"
13-
[scripts/lib/update.sh]="59ba47a1284d590319e2d392e6c8838d545a35e09efb1f3ac8cbfb834ef9d4c6"
14-
[scripts/lib/doctor.sh]="8315bdeb06051af7e12143f229e0ddec36eda69a2f5e7845ee9bdf754aa1e9e7"
13+
[scripts/lib/update.sh]="7bcad29c1bf19308841c4f090361b405b3a7ae1ddc2b0783705686f45b9cfb86"
14+
[scripts/lib/doctor.sh]="f784629ae65d0a258d92d759b9dc785d66a68b6b439930c78bef79f038c476ea"
1515
[scripts/lib/doctor_fix.sh]="074e8512b1b5cc6a6d27513d5463b585b0e5c35540180e58747793a7c67d3a6f"
16+
[scripts/lib/offline_artifact_pack.sh]="38c6c2821044e2ac197b686403902419d73859f5eb370244f27e2ae54a5f1db1"
1617
[scripts/lib/autofix.sh]="0468d4889d304a404f161778ddf393a71fa7657317f88f692a47442760ed78d9"
1718
[scripts/lib/install_helpers.sh]="7fb952755e0401bec1c2a20b247d35809eab73ce51a1de1c2b6d725be9431481"
1819
[scripts/lib/logging.sh]="af95380f740a905f990e68a627508eb6dbaa6f83e03014c8eea2b69c2750dabe"
@@ -27,5 +28,5 @@ declare -gA ACFS_INTERNAL_CHECKSUMS=(
2728
[scripts/acfs-update]="3ab9578caa95e7866a706c543bc8af9302ccf20538b716cca621e5c037ee24b0"
2829
)
2930

30-
ACFS_INTERNAL_CHECKSUMS_COUNT=17
31+
ACFS_INTERNAL_CHECKSUMS_COUNT=18
3132
ACFS_INTERNAL_CHECKSUMS_GENERATED="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo unknown)"

scripts/lib/doctor.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ print_acfs_help() {
10071007
echo " swarm calibration Artifact-backed capacity calibration report"
10081008
echo " swarm inventory Local host inventory report/import/export/validate"
10091009
echo " provisioning-packet Validate/render provider provisioning packet JSON"
1010+
echo " offline-pack Build verified offline artifact packs"
10101011
echo " coordinate doctor Alias for swarm doctor"
10111012
echo " cheatsheet Command reference (aliases, shortcuts)"
10121013
echo " changelog [options] Show recent project changes"
@@ -4673,6 +4674,18 @@ main() {
46734674
echo "Error: provisioning_packet.sh not found" >&2
46744675
return 1
46754676
;;
4677+
offline-pack|artifact-pack)
4678+
shift
4679+
local offline_artifact_pack_script=""
4680+
offline_artifact_pack_script="$(_acfs_doctor_find_lib_script "offline_artifact_pack.sh" 2>/dev/null || true)"
4681+
4682+
if [[ -n "$offline_artifact_pack_script" ]]; then
4683+
_acfs_doctor_exec_bash_script "$offline_artifact_pack_script" "$@"
4684+
fi
4685+
4686+
echo "Error: offline_artifact_pack.sh not found" >&2
4687+
return 1
4688+
;;
46764689
version|-v|--version)
46774690
local version_file=""
46784691
version_file="$(_acfs_doctor_find_project_path "VERSION" 2>/dev/null || true)"

0 commit comments

Comments
 (0)