@zenera/cli 1.1.22 → 1.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/archive.d.ts +139 -0
- package/dist/archive.js +376 -0
- package/dist/commands/export.d.ts +3 -0
- package/dist/commands/export.js +255 -0
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.js +173 -0
- package/dist/commands/index.d.ts +5 -1
- package/dist/commands/index.js +13 -1
- package/dist/commands/memory.js +117 -10
- package/dist/scaffold.d.ts +8 -0
- package/dist/scaffold.js +4 -1
- package/dist/validate.js +68 -1
- package/package.json +12 -6
- package/templates/editor/.github/prompts/spec-sync-project.prompt.md +25 -2
- package/templates/editor/.github/skills/zen-cli/SKILL.md +6 -1
- package/templates/editor/.github/skills/zen-cli/references/check.md +6 -0
- package/templates/editor/.github/skills/zen-cli/references/export.md +107 -0
- package/templates/editor/.github/skills/zen-cli/references/memory.md +51 -13
- package/templates/editor/.github/skills/zen-cli/references/rag.md +6 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +2 -1
- package/templates/editor/.github/skills/zen-memory-warmup/SKILL.md +188 -58
- package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +6 -5
- package/templates/project/SPECIFICATION.md.tmpl +2 -0
- package/templates/project/scripts/_setup.sh +49 -7
|
@@ -75,12 +75,18 @@ In a setup step, in this order:
|
|
|
75
75
|
|
|
76
76
|
```sh
|
|
77
77
|
if [ "${FORCE:-0}" = 0 ] && zen rag docs ready --dir "$OUT" --quiet; then exit 3; fi
|
|
78
|
+
if [ "${CHECK:-0}" = 1 ]; then zen rag docs ready --dir "$OUT" || true; exit 4; fi
|
|
78
79
|
if [ "${FORCE:-0}" = 0 ] && [ -f "$OUT/manifest.json" ]; then
|
|
79
80
|
zen rag docs restore --dir "$OUT"; exit 0
|
|
80
81
|
fi
|
|
81
82
|
# … otherwise index it from the documents
|
|
82
83
|
```
|
|
83
84
|
|
|
85
|
+
Exit 4 is what `scripts/_setup.sh --check` reports as `needs setup`. Dropping
|
|
86
|
+
`--quiet` there is deliberate: `ready` prints what is missing and the command
|
|
87
|
+
that fixes it, and repeating that in the step would be a second opinion to keep
|
|
88
|
+
in step with this one.
|
|
89
|
+
|
|
84
90
|
## Which index gets read
|
|
85
91
|
|
|
86
92
|
Every reading command takes `-d`, `--dir`. Without one:
|
|
@@ -610,7 +610,7 @@ can act on.
|
|
|
610
610
|
## Inspecting and repairing it
|
|
611
611
|
|
|
612
612
|
```
|
|
613
|
-
zen memory [stats|ls|show|export|forget] [args] [options]
|
|
613
|
+
zen memory [stats|ls|show|export|merge|forget] [args] [options]
|
|
614
614
|
```
|
|
615
615
|
|
|
616
616
|
`zen memory export --open` is the one to reach for: one self-contained HTML
|
|
@@ -627,6 +627,7 @@ so inspection is free and offline.
|
|
|
627
627
|
| What has been corrected? | `zen memory ls --stale` |
|
|
628
628
|
| What files are being kept? | `zen memory ls --files` |
|
|
629
629
|
| Why was that recalled? | `zen memory show <id>` |
|
|
630
|
+
| Fold parallel warmup graphs into one | `zen memory merge <dir...>` |
|
|
630
631
|
| That should never have been written down | `zen memory forget <id>` |
|
|
631
632
|
|
|
632
633
|
The directory is not fixed. `zen run --memory <dir>` sends one run's memory
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zen-memory-warmup
|
|
3
|
-
description: Pre-populating an agent project's memory graph through warm-up queries before production or deployment — isolating scratch memory and workspaces in timestamped .tmp directories, using stronger reasoning models, validating machine-readable JSON output, categorizing queries with limits, shuffling,
|
|
3
|
+
description: Pre-populating an agent project's memory graph through warm-up queries before production or deployment — isolating scratch memory and workspaces in timestamped .tmp directories, using stronger reasoning models, validating machine-readable JSON output, categorizing queries with limits, shuffling, dry-run execution, fanning queries out across parallel runs and folding the results back with zen memory merge, inspecting the graph with zen memory stats/ls, atomic promotion into the project, and generating automated population scripts in scripts/memory_warmup.sh.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Memory Warmup
|
|
@@ -33,7 +33,7 @@ synthesize, connect, and commit high-value knowledge nodes.
|
|
|
33
33
|
|
|
34
34
|
## Core Architecture & Safety Rules
|
|
35
35
|
|
|
36
|
-
Warmup is an offline staging process. It must adhere to
|
|
36
|
+
Warmup is an offline staging process. It must adhere to six safety rules:
|
|
37
37
|
|
|
38
38
|
### 1. Never warm up directly into the project's active `memory/`
|
|
39
39
|
|
|
@@ -101,6 +101,56 @@ warmup queries, and do not overwrite the project's `memory/` until the final
|
|
|
101
101
|
graph in `.tmp/warmup-<timestamp>/memory` has been verified to contain expected
|
|
102
102
|
nodes and vector embeddings.
|
|
103
103
|
|
|
104
|
+
### 6. Give every parallel run its own memory directory
|
|
105
|
+
|
|
106
|
+
The memory lock is **per directory**. Two runs pointed at the same `--memory`
|
|
107
|
+
do not interleave — the second one refuses to start. So a warmup that wants to
|
|
108
|
+
use the wall clock has to fan out into one memory per run:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
.tmp/warmup-$STAMP/memory-1
|
|
112
|
+
.tmp/warmup-$STAMP/memory-2
|
|
113
|
+
...
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
and fold them back together afterwards with `zen memory merge`, which is
|
|
117
|
+
offline, contacts no model, and preserves node ids:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
zen memory merge .tmp/warmup-$STAMP/memory-* --dir .tmp/warmup-$STAMP/memory
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Merging is what makes `--incremental` safe under fan-out: every shard starts
|
|
124
|
+
from a copy of the same project memory, so most of what comes back is a shared
|
|
125
|
+
ancestor rather than a collision. Shared ancestors reconcile silently; two runs
|
|
126
|
+
that genuinely changed the same memory in different ways stop the merge and
|
|
127
|
+
name the ids, because picking a winner silently is how a merge loses an answer.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Fanning Out
|
|
132
|
+
|
|
133
|
+
```mermaid
|
|
134
|
+
flowchart LR
|
|
135
|
+
A["Selected queries"] --> B1["zen run → memory-1"]
|
|
136
|
+
A --> B2["zen run → memory-2"]
|
|
137
|
+
A --> B3["zen run → memory-N"]
|
|
138
|
+
B1 --> M["zen memory merge memory-* --dir memory"]
|
|
139
|
+
B2 --> M
|
|
140
|
+
B3 --> M
|
|
141
|
+
M --> V["zen memory stats --dir memory"]
|
|
142
|
+
V --> P["Backup & promote to memory/"]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Bound the fan-out with `--jobs <n>`. Each run is a model call **and** a Podman
|
|
146
|
+
container, so the useful ceiling is set by the machine and the provider's rate
|
|
147
|
+
limit rather than by the number of queries; 4 is a sane default.
|
|
148
|
+
|
|
149
|
+
Sequential warmup is still the better choice when the queries build on each
|
|
150
|
+
other, because a later query can recall what an earlier one committed. Fan-out
|
|
151
|
+
trades that away for wall-clock time, and `merge` gives back everything except
|
|
152
|
+
the cross-query recall.
|
|
153
|
+
|
|
104
154
|
---
|
|
105
155
|
|
|
106
156
|
## The Warmup Cycle
|
|
@@ -181,6 +231,7 @@ The script should automate the entire pipeline:
|
|
|
181
231
|
- `--shuffle`: Randomize query order before applying limits.
|
|
182
232
|
- `--category <name>`: Filter queries to a specific category.
|
|
183
233
|
- `--model <provider:model>`: Override model with a reasoning flagship.
|
|
234
|
+
- `--jobs <n>`: Run up to $n$ queries at once, each into its own memory.
|
|
184
235
|
- `--incremental`: Copy existing project memory into staging before warming up.
|
|
185
236
|
- `-y`, `--yes`: Promote memory without interactive confirmation.
|
|
186
237
|
2. Create timestamped staging paths under `.tmp/` (e.g.
|
|
@@ -189,8 +240,9 @@ The script should automate the entire pipeline:
|
|
|
189
240
|
4. If `--dry-run` is active, print the execution plan and exit 0 before touching disk.
|
|
190
241
|
5. Invoke `zen run` with `--memory`, `--workspace`, `--model`, and `--json`.
|
|
191
242
|
6. Parse each outcome with `jq`, halt if a turn fails, and report per-query execution time and total elapsed time since start.
|
|
192
|
-
7.
|
|
193
|
-
8.
|
|
243
|
+
7. Under `--jobs <n>`, give each run its own `memory-N` directory and fold them back with `zen memory merge memory-* --dir memory`.
|
|
244
|
+
8. Print graph statistics via `zen memory stats --dir ...` between queries to track graph growth, followed by a final validation.
|
|
245
|
+
9. Safely backup and replace the project's `memory/` directory with the warmed graph.
|
|
194
246
|
|
|
195
247
|
### Recommended Script Template (`scripts/memory_warmup.sh`)
|
|
196
248
|
|
|
@@ -211,6 +263,7 @@ pattern:
|
|
|
211
263
|
# --shuffle Randomize query order before applying limits
|
|
212
264
|
# --category <name> Filter queries to a specific category
|
|
213
265
|
# --model <ref> Override model (e.g. anthropic:claude-sonnet-4-5)
|
|
266
|
+
# --jobs <n> Run up to n queries at once, one memory each (default 1)
|
|
214
267
|
# --incremental Seed staging memory with current memory/ before runs
|
|
215
268
|
# -y, --yes Assume yes for memory promotion
|
|
216
269
|
# -h, --help Show this help
|
|
@@ -219,6 +272,7 @@ pattern:
|
|
|
219
272
|
# ./scripts/memory_warmup.sh --dry-run
|
|
220
273
|
# ./scripts/memory_warmup.sh --dry-run --category workflows --limit 2
|
|
221
274
|
# ./scripts/memory_warmup.sh --shuffle --limit 5 --model anthropic:claude-sonnet-4-5
|
|
275
|
+
# ./scripts/memory_warmup.sh --jobs 4
|
|
222
276
|
# ./scripts/memory_warmup.sh --incremental
|
|
223
277
|
#
|
|
224
278
|
|
|
@@ -234,6 +288,7 @@ INCREMENTAL=false
|
|
|
234
288
|
ASSUME_YES=false
|
|
235
289
|
DRY_RUN=false
|
|
236
290
|
LIMIT=0
|
|
291
|
+
JOBS=1
|
|
237
292
|
SHUFFLE=false
|
|
238
293
|
CATEGORY_FILTER=""
|
|
239
294
|
|
|
@@ -275,6 +330,10 @@ while [[ $# -gt 0 ]]; do
|
|
|
275
330
|
MODEL="$2"
|
|
276
331
|
shift 2
|
|
277
332
|
;;
|
|
333
|
+
--jobs)
|
|
334
|
+
JOBS="$2"
|
|
335
|
+
shift 2
|
|
336
|
+
;;
|
|
278
337
|
--incremental)
|
|
279
338
|
INCREMENTAL=true
|
|
280
339
|
shift
|
|
@@ -292,6 +351,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
292
351
|
echo " --shuffle Randomize query order before applying limits"
|
|
293
352
|
echo " --category <name> Filter queries to a specific category"
|
|
294
353
|
echo " --model <ref> Override model (e.g. anthropic:claude-sonnet-4-5)"
|
|
354
|
+
echo " --jobs <n> Run up to n queries at once, one memory each (default 1)"
|
|
295
355
|
echo " --incremental Seed staging memory with current memory/ before runs"
|
|
296
356
|
echo " -y, --yes Assume yes for memory promotion"
|
|
297
357
|
echo " -h, --help Show this help"
|
|
@@ -378,6 +438,7 @@ if [ "$DRY_RUN" = true ]; then
|
|
|
378
438
|
echo "Category filter: ${CATEGORY_FILTER:-<all>}"
|
|
379
439
|
echo "Shuffled: $SHUFFLE"
|
|
380
440
|
echo "Limit: ${LIMIT:-none}"
|
|
441
|
+
echo "Jobs: $JOBS"
|
|
381
442
|
echo "Selected queries: ${#SELECTED[@]} of ${#ALL_QUERIES[@]}"
|
|
382
443
|
echo ""
|
|
383
444
|
echo "Planned queries:"
|
|
@@ -389,7 +450,15 @@ if [ "$DRY_RUN" = true ]; then
|
|
|
389
450
|
echo ""
|
|
390
451
|
echo "Sample command that would execute:"
|
|
391
452
|
SAMPLE_Q="${SELECTED[0]#*|}"
|
|
392
|
-
|
|
453
|
+
if [ "$JOBS" -le 1 ]; then
|
|
454
|
+
SAMPLE_MEM="$STAGING_MEM"
|
|
455
|
+
else
|
|
456
|
+
SAMPLE_MEM="$SCRATCH_DIR/memory-1"
|
|
457
|
+
fi
|
|
458
|
+
echo " zen run --memory \"$SAMPLE_MEM\" --workspace \"$WORKSPACES_DIR/run-1-<timestamp>\" ${MODEL:+--model \"$MODEL\" }--json \"$SAMPLE_Q\""
|
|
459
|
+
if [ "$JOBS" -gt 1 ]; then
|
|
460
|
+
echo " zen memory merge \"$SCRATCH_DIR\"/memory-* --dir \"$STAGING_MEM\" --yes"
|
|
461
|
+
fi
|
|
393
462
|
echo " zen memory stats --dir \"$STAGING_MEM\""
|
|
394
463
|
echo ""
|
|
395
464
|
echo "Post-run validation that would run:"
|
|
@@ -421,78 +490,139 @@ cleanup() {
|
|
|
421
490
|
}
|
|
422
491
|
trap cleanup EXIT
|
|
423
492
|
|
|
424
|
-
# Prepare staging
|
|
425
|
-
mkdir -p "$
|
|
493
|
+
# Prepare staging paths
|
|
494
|
+
mkdir -p "$WORKSPACES_DIR"
|
|
426
495
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
echo "----------------------------------------"
|
|
434
|
-
|
|
435
|
-
COUNT=0
|
|
436
|
-
for item in "${SELECTED[@]}"; do
|
|
437
|
-
COUNT=$((COUNT + 1))
|
|
438
|
-
CATEGORY="${item%%|*}"
|
|
439
|
-
QUERY="${item#*|}"
|
|
440
|
-
|
|
441
|
-
RUN_STAMP="$(date +%s)"
|
|
442
|
-
RUN_WORKSPACE="$WORKSPACES_DIR/run-$COUNT-$RUN_STAMP"
|
|
443
|
-
mkdir -p "$RUN_WORKSPACE"
|
|
496
|
+
seed_memory() {
|
|
497
|
+
mkdir -p "$1"
|
|
498
|
+
if [ "$INCREMENTAL" = true ] && [ -d "$PROJECT_MEM" ]; then
|
|
499
|
+
cp -R "$PROJECT_MEM/." "$1/"
|
|
500
|
+
fi
|
|
501
|
+
}
|
|
444
502
|
|
|
445
|
-
|
|
446
|
-
|
|
503
|
+
# One query, into the memory directory it is handed. The lock is per directory,
|
|
504
|
+
# so this is the unit that more than one of can be in flight at a time.
|
|
505
|
+
run_query() {
|
|
506
|
+
local index="$1" category="$2" query="$3" mem="$4"
|
|
507
|
+
local workspace="$WORKSPACES_DIR/run-$index-$(date +%s)"
|
|
508
|
+
mkdir -p "$workspace"
|
|
447
509
|
|
|
448
|
-
|
|
449
|
-
CMD=(zen run --memory "$STAGING_MEM" --workspace "$RUN_WORKSPACE" --json)
|
|
510
|
+
local cmd=(zen run --memory "$mem" --workspace "$workspace" --json)
|
|
450
511
|
if [ -n "$MODEL" ]; then
|
|
451
|
-
|
|
512
|
+
cmd+=(--model "$MODEL")
|
|
452
513
|
fi
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
QUERY_START=$(date +%s)
|
|
514
|
+
cmd+=("$query")
|
|
456
515
|
|
|
457
|
-
#
|
|
458
|
-
|
|
459
|
-
EXIT_CODE=$?
|
|
516
|
+
echo "[$index/${#SELECTED[@]}] [$category] \"$query\""
|
|
517
|
+
echo " -> Workspace: $workspace"
|
|
460
518
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
echo " -> Command exited with code $EXIT_CODE (query: $(format_duration $QUERY_DURATION), total elapsed: $(format_duration $TOTAL_ELAPSED))" >&2
|
|
467
|
-
exit $EXIT_CODE
|
|
519
|
+
local start out
|
|
520
|
+
start=$(date +%s)
|
|
521
|
+
if ! out="$("${cmd[@]}")"; then
|
|
522
|
+
echo " -> Command failed" >&2
|
|
523
|
+
return 1
|
|
468
524
|
fi
|
|
469
525
|
|
|
470
|
-
# Parse outcome via jq if available
|
|
471
526
|
if command -v jq >/dev/null 2>&1; then
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
echo "
|
|
475
|
-
|
|
476
|
-
if [ "$
|
|
477
|
-
echo " -> Unexpected stop reason: $
|
|
478
|
-
|
|
527
|
+
local stop agent
|
|
528
|
+
stop=$(echo "$out" | jq -r '.stopReason // empty')
|
|
529
|
+
agent=$(echo "$out" | jq -r '.agent // empty')
|
|
530
|
+
echo " -> Completed: agent=$agent stopReason=$stop"
|
|
531
|
+
if [ "$stop" != "final" ]; then
|
|
532
|
+
echo " -> Unexpected stop reason: $stop" >&2
|
|
533
|
+
return 1
|
|
479
534
|
fi
|
|
480
535
|
else
|
|
481
536
|
echo " -> Turn completed successfully."
|
|
482
537
|
fi
|
|
483
538
|
|
|
484
|
-
|
|
539
|
+
local now
|
|
540
|
+
now=$(date +%s)
|
|
541
|
+
echo " -> Timing: query took $(format_duration $((now - start))) | elapsed since start: $(format_duration $((now - WARMUP_START)))"
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
# `wait` with no arguments always reports success, so every child is waited for
|
|
545
|
+
# by pid. Batches of $JOBS rather than a rolling queue: `wait -n` wants bash
|
|
546
|
+
# 4.3 and macOS still ships 3.2.
|
|
547
|
+
PIDS=()
|
|
548
|
+
FAILED=false
|
|
549
|
+
drain() {
|
|
550
|
+
if [ ${#PIDS[@]} -eq 0 ]; then
|
|
551
|
+
return 0
|
|
552
|
+
fi
|
|
553
|
+
local pid
|
|
554
|
+
for pid in "${PIDS[@]}"; do
|
|
555
|
+
wait "$pid" || FAILED=true
|
|
556
|
+
done
|
|
557
|
+
PIDS=()
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
echo "Running ${#SELECTED[@]} warmup queries (jobs: $JOBS)..."
|
|
561
|
+
echo "----------------------------------------"
|
|
562
|
+
|
|
563
|
+
if [ "$JOBS" -le 1 ]; then
|
|
564
|
+
seed_memory "$STAGING_MEM"
|
|
565
|
+
COUNT=0
|
|
566
|
+
for item in "${SELECTED[@]}"; do
|
|
567
|
+
COUNT=$((COUNT + 1))
|
|
568
|
+
run_query "$COUNT" "${item%%|*}" "${item#*|}" "$STAGING_MEM"
|
|
485
569
|
|
|
486
|
-
|
|
487
|
-
|
|
570
|
+
# Print memory stats between queries to track graph growth
|
|
571
|
+
if [ -f "$STAGING_MEM/manifest.json" ]; then
|
|
572
|
+
echo ""
|
|
573
|
+
echo "Memory stats after query $COUNT:"
|
|
574
|
+
zen memory stats --dir "$STAGING_MEM"
|
|
575
|
+
else
|
|
576
|
+
echo " -> Memory stats: No memories committed yet."
|
|
577
|
+
fi
|
|
488
578
|
echo ""
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
579
|
+
done
|
|
580
|
+
else
|
|
581
|
+
SHARDS=()
|
|
582
|
+
COUNT=0
|
|
583
|
+
for item in "${SELECTED[@]}"; do
|
|
584
|
+
COUNT=$((COUNT + 1))
|
|
585
|
+
SHARD="$SCRATCH_DIR/memory-$COUNT"
|
|
586
|
+
seed_memory "$SHARD"
|
|
587
|
+
SHARDS+=("$SHARD")
|
|
588
|
+
run_query "$COUNT" "${item%%|*}" "${item#*|}" "$SHARD" \
|
|
589
|
+
>"$SCRATCH_DIR/run-$COUNT.log" 2>&1 &
|
|
590
|
+
PIDS+=($!)
|
|
591
|
+
if [ ${#PIDS[@]} -ge "$JOBS" ]; then
|
|
592
|
+
drain
|
|
593
|
+
fi
|
|
594
|
+
done
|
|
595
|
+
drain
|
|
596
|
+
|
|
597
|
+
for log in "$SCRATCH_DIR"/run-*.log; do
|
|
598
|
+
if [ -f "$log" ]; then
|
|
599
|
+
cat "$log"
|
|
600
|
+
echo ""
|
|
601
|
+
fi
|
|
602
|
+
done
|
|
603
|
+
|
|
604
|
+
if [ "$FAILED" = true ]; then
|
|
605
|
+
echo "One or more warmup runs failed; nothing was promoted." >&2
|
|
606
|
+
exit 1
|
|
493
607
|
fi
|
|
608
|
+
|
|
609
|
+
# Only a memory something was committed to can be merged; a run that found
|
|
610
|
+
# nothing worth keeping never writes a manifest.
|
|
611
|
+
MERGE=()
|
|
612
|
+
for shard in "${SHARDS[@]}"; do
|
|
613
|
+
if [ -f "$shard/manifest.json" ]; then
|
|
614
|
+
MERGE+=("$shard")
|
|
615
|
+
fi
|
|
616
|
+
done
|
|
617
|
+
if [ ${#MERGE[@]} -eq 0 ]; then
|
|
618
|
+
echo "No warmup run committed anything." >&2
|
|
619
|
+
exit 1
|
|
620
|
+
fi
|
|
621
|
+
|
|
622
|
+
echo "Merging ${#MERGE[@]} memories into $STAGING_MEM..."
|
|
623
|
+
zen memory merge "${MERGE[@]}" --dir "$STAGING_MEM" --yes
|
|
494
624
|
echo ""
|
|
495
|
-
|
|
625
|
+
fi
|
|
496
626
|
|
|
497
627
|
echo "----------------------------------------"
|
|
498
628
|
TOTAL_RUN_TIME=$(( $(date +%s) - WARMUP_START ))
|
|
@@ -111,11 +111,12 @@ However small the diff:
|
|
|
111
111
|
last.
|
|
112
112
|
2. **`scripts/_setup.sh` has run to completion in this session, and re-runs
|
|
113
113
|
clean.** A one-line specification change can still break a setup step, and a
|
|
114
|
-
pass that did not run it does not know. `
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
committed `manifest.json` skips on a
|
|
118
|
-
vectors are missing, and the project
|
|
114
|
+
pass that did not run it does not know. Then `scripts/_setup.sh --check` must
|
|
115
|
+
report every step `skipped`: it makes each step's own readiness test without
|
|
116
|
+
doing the work, which is what tells a real `skipped` from a step that only
|
|
117
|
+
looked done. A step that tests for a committed `manifest.json` skips on a
|
|
118
|
+
fresh clone whose git-ignored `lance/` vectors are missing, and the project
|
|
119
|
+
cannot search.
|
|
119
120
|
3. **§9 of the copilot instructions, worked as a checklist**, group by group.
|
|
120
121
|
4. **The capability obligations in §0.1.** For every capability the project has
|
|
121
122
|
turned on, load that capability's skill and re-check what it requires - in
|
|
@@ -28,6 +28,8 @@ something in it — and report what was done in enough detail to be checked.
|
|
|
28
28
|
are the steps it runs in order. A step is safe to run twice and reports
|
|
29
29
|
`skipped` the second time — testing for something that survives a clone, not
|
|
30
30
|
for a file `.gitignore` excludes.
|
|
31
|
+
- `scripts/_setup.sh --check` asks the same questions and does none of the work,
|
|
32
|
+
so what is missing can be read without paying to find out.
|
|
31
33
|
- Currently: no steps. Nothing has to be prepared before a run.
|
|
32
34
|
|
|
33
35
|
## Agents
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#
|
|
5
5
|
# scripts/_setup.sh do whatever is not done yet
|
|
6
6
|
# scripts/_setup.sh --force do all of it again
|
|
7
|
+
# scripts/_setup.sh --check say what is not done, and do none of it
|
|
7
8
|
#
|
|
8
9
|
# Anything that has to be in place before a run — an index built, a document
|
|
9
10
|
# fetched, a file generated — is a script in this directory rather than a
|
|
@@ -17,6 +18,11 @@
|
|
|
17
18
|
# - takes no arguments, and reads $FORCE to know whether to redo finished work
|
|
18
19
|
# - exits 0 when it did the work, 3 when there was nothing to do, non-zero
|
|
19
20
|
# when it failed
|
|
21
|
+
# - under $CHECK, does none of the work: it runs the same "already done" test,
|
|
22
|
+
# exits 3 when the answer is yes, and otherwise says what is missing and
|
|
23
|
+
# exits 4. A check must not assume an earlier step has run — a missing
|
|
24
|
+
# prerequisite is a 4 of its own, not a hard failure, or one unbuilt thing
|
|
25
|
+
# hides the rest of the list
|
|
20
26
|
# - writes under .tmp/ and moves the result into place, so an interrupted run
|
|
21
27
|
# never leaves half an artefact behind
|
|
22
28
|
#
|
|
@@ -27,6 +33,10 @@
|
|
|
27
33
|
# first search fails for a reason nobody connects to setup. Ask the tool instead
|
|
28
34
|
# of guessing at files — `zen rag docs ready` answers exactly that question.
|
|
29
35
|
#
|
|
36
|
+
# That test is the whole of `--check`, which is why this is one script and not
|
|
37
|
+
# two: the steps already know what "done" means, and a second script asking the
|
|
38
|
+
# same question would be a second answer to keep in step with this one.
|
|
39
|
+
#
|
|
30
40
|
# Running this twice has to be safe, and the second run is what proves it: every
|
|
31
41
|
# step should report `skipped`.
|
|
32
42
|
|
|
@@ -34,10 +44,17 @@ set -eu
|
|
|
34
44
|
cd "$(dirname "$0")/.."
|
|
35
45
|
|
|
36
46
|
FORCE=0
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
CHECK=0
|
|
48
|
+
case "${1:-}" in
|
|
49
|
+
'') ;;
|
|
50
|
+
--force) FORCE=1 ;;
|
|
51
|
+
--check) CHECK=1 ;;
|
|
52
|
+
*)
|
|
53
|
+
echo "usage: scripts/_setup.sh [--force|--check]" >&2
|
|
54
|
+
exit 2
|
|
55
|
+
;;
|
|
56
|
+
esac
|
|
57
|
+
export FORCE CHECK
|
|
41
58
|
|
|
42
59
|
LOGS=.tmp/logs
|
|
43
60
|
|
|
@@ -58,6 +75,12 @@ LOGS=.tmp/logs
|
|
|
58
75
|
# echo "$OUT is already built"
|
|
59
76
|
# exit 3
|
|
60
77
|
# fi
|
|
78
|
+
# if [ "${CHECK:-0}" = 1 ]; then
|
|
79
|
+
# # Without --quiet it names what is missing and the command that fixes
|
|
80
|
+
# # it; `|| true` because not-ready is the exit code we came for.
|
|
81
|
+
# zen rag docs ready --dir "$OUT" || true
|
|
82
|
+
# exit 4
|
|
83
|
+
# fi
|
|
61
84
|
# # Committed index, git-ignored vectors: re-embed from the copies the index
|
|
62
85
|
# # already holds rather than indexing the documents over again.
|
|
63
86
|
# if [ "${FORCE:-0}" = 0 ] && [ -f "$OUT/manifest.json" ]; then
|
|
@@ -80,9 +103,16 @@ fi
|
|
|
80
103
|
mkdir -p "$LOGS"
|
|
81
104
|
summary=""
|
|
82
105
|
failed=0
|
|
106
|
+
pending=0
|
|
83
107
|
|
|
84
108
|
for name in $STEPS; do
|
|
85
|
-
log
|
|
109
|
+
# A dry run keeps its own log: overwriting the build's would lose the
|
|
110
|
+
# record of the build to a question about it.
|
|
111
|
+
if [ "$CHECK" = 1 ]; then
|
|
112
|
+
log="$LOGS/check-$name.log"
|
|
113
|
+
else
|
|
114
|
+
log="$LOGS/setup-$name.log"
|
|
115
|
+
fi
|
|
86
116
|
echo
|
|
87
117
|
echo "-- $name $(date '+%H:%M:%S') ($log)"
|
|
88
118
|
|
|
@@ -96,6 +126,10 @@ for name in $STEPS; do
|
|
|
96
126
|
case "$code" in
|
|
97
127
|
0) word=ok ;;
|
|
98
128
|
3) word=skipped ;;
|
|
129
|
+
4)
|
|
130
|
+
word="needs setup"
|
|
131
|
+
pending=1
|
|
132
|
+
;;
|
|
99
133
|
*)
|
|
100
134
|
word="failed ($code)"
|
|
101
135
|
failed=1
|
|
@@ -105,12 +139,20 @@ for name in $STEPS; do
|
|
|
105
139
|
"
|
|
106
140
|
# Later steps depend on earlier ones, so a failure stops rather than
|
|
107
141
|
# producing a second failure that is only a consequence of the first.
|
|
142
|
+
# `needs setup` does not stop it: the point of asking is the whole list.
|
|
108
143
|
if [ "$failed" = 1 ]; then
|
|
109
144
|
break
|
|
110
145
|
fi
|
|
111
146
|
done
|
|
112
147
|
|
|
113
148
|
echo
|
|
114
|
-
|
|
149
|
+
if [ "$CHECK" = 1 ]; then
|
|
150
|
+
echo "setup check:"
|
|
151
|
+
else
|
|
152
|
+
echo "setup:"
|
|
153
|
+
fi
|
|
115
154
|
printf '%s' "$summary"
|
|
116
|
-
|
|
155
|
+
if [ "$failed" = 1 ] || [ "$pending" = 1 ]; then
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
158
|
+
exit 0
|