Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
116 lines
7.9 KiB
Diff
116 lines
7.9 KiB
Diff
diff --git a/docs/TOOLS.md b/docs/TOOLS.md
|
|
index e0447341c..3a9de2aa7 100644
|
|
--- a/docs/TOOLS.md
|
|
+++ b/docs/TOOLS.md
|
|
@@ -404,9 +404,12 @@ refuses `capture-failed` before it stops anything. Adopt uses the same rule.
|
|
full id.
|
|
3. Run `activate ID BUSINESS --plan` and take the output to Mos. It names the
|
|
store's schema and the target's, any migration with `--migrate` and the
|
|
- decision 96 condition 2 line (Jason present), the commits the run adds,
|
|
- and the three install commands. It refuses `copies-unrelated` when neither
|
|
- copy is an ancestor of the other.
|
|
+ decision 96 condition 2 line (Jason present), the backup, the commits the
|
|
+ run adds, and the three install commands. The `backup:` line gives the
|
|
+ directory the run backs the stopped store up to, or why it takes none:
|
|
+ there is no store file, or the run rolls back with `store-newer` or
|
|
+ `migration-needs-flag` before the backup. It refuses `copies-unrelated`
|
|
+ when neither copy is an ancestor of the other.
|
|
4. Mos removes any bus drop-in that overrides ExecStart or WorkingDirectory;
|
|
`activate` refuses `drop-in-override` and names the file.
|
|
5. With Mos's go, `activate ID BUSINESS`, plus `--migrate` when the plan
|
|
diff --git a/packages/cli/tests/stack-release.test.mjs b/packages/cli/tests/stack-release.test.mjs
|
|
index e85968006..a2c0e720c 100644
|
|
--- a/packages/cli/tests/stack-release.test.mjs
|
|
+++ b/packages/cli/tests/stack-release.test.mjs
|
|
@@ -380,6 +380,7 @@ async function seed(e,{copy=B,pm=false,store='3g',pointer:how='adopt'}={}){
|
|
|
|
const rolledBack=(code,to=B)=>`stack-release: ${code}; rolled back to ${to}, which passed the gate\n`;
|
|
const planBackup=(e)=>`backup: the run backs up the stopped store to ${e.data}/backups/stack/<activation>/ before any migration`;
|
|
+const planNoBackup='backup: none; the run rolls back before the backup';
|
|
const planTail=(e,to,pm=false)=>[`bus: scripts/bus-service.sh install --copy ${to} --copies ${COPIES}${pm?' --pm':''} --claude ${e.claude}`,`Console: scripts/webui-service.sh install --copy ${to} --copies ${COPIES} --port ${e.port} --business acme`,`CLI: scripts/stack-copy.sh wrapper ${to} --copies ${COPIES} --bin ${e.bin}`];
|
|
|
|
// --- The T table ---
|
|
@@ -643,9 +644,9 @@ test('T26 --plan lists the commits an activate adds, after the migration lines',
|
|
'migration: 3g to 3h, after a backup of the stopped store','migration steps: 3g to 3h',`needs: --migrate (${mig})`,'needs: Jason present for this run (decision 96 condition 2)'];
|
|
const adds=commitLines(`${B}..${C}`);
|
|
assert.equal(adds.length,2);assert.match(adds[0],/^ {2}[0-9a-f]{7,} row 904: C$/);assert.match(adds[1],/^ {2}[0-9a-f]{7,} row 903: C1$/);
|
|
- for(const [flags,mig] of [[[],'not given; the run would roll back with migration-needs-flag'],[['--migrate'],'given']]){
|
|
+ for(const [flags,mig,backup] of [[[],'not given; the run would roll back with migration-needs-flag',planNoBackup],[['--migrate'],'given',planBackup(e)]]){
|
|
const r=await run(e,'activate',C,'acme','--plan',...flags);assert.equal(r.code,0,r.err);
|
|
- assert.equal(r.out,[...head(mig),planBackup(e),'commits: the run adds 2 (newest first, at most 200):',...adds,...planTail(e,C),''].join('\n'));
|
|
+ assert.equal(r.out,[...head(mig),backup,'commits: the run adds 2 (newest first, at most 200):',...adds,...planTail(e,C),''].join('\n'));
|
|
}
|
|
const same=await run(e,'activate',C1,'acme','--plan');assert.equal(same.code,0,same.err);
|
|
assert.ok(same.out.includes(`target schema: 3g\nmigration: none; the store is at the target's version\n${planBackup(e)}\ncommits: the run adds 1 (newest first, at most 200):\n`),same.out);
|
|
@@ -1373,6 +1374,31 @@ test('T51 row 185 test 5: an activate with no store file takes no backup',async(
|
|
const l=logLines(e).at(-1);assert.deepEqual([l.result,l.backup],['ok',null]);
|
|
});
|
|
|
|
+// Row 186 (#1684): the activate plan prints the backup line only when the run reaches backup_store.
|
|
+// Each case plans, checks nothing was written, then runs and checks a backup exists exactly when the plan said so.
|
|
+test('T52 row 186: the activate plan\'s backup line says what the run will do',async(t)=>{
|
|
+ const newer='migration: none possible; 3z is not in 3h\'s migration chain, so the run would roll back with store-newer';
|
|
+ const cases=[
|
|
+ ['same schema','3g',C1,[],'migration: none; the store is at the target\'s version',true,0],
|
|
+ ['same schema with --migrate','3g',C1,['--migrate'],'migration: none; the store is at the target\'s version',true,0],
|
|
+ ['in chain with --migrate','3g',C,['--migrate'],'needs: --migrate (given)',true,0],
|
|
+ ['in chain without --migrate','3g',C,[],'needs: --migrate (not given; the run would roll back with migration-needs-flag)',false,1],
|
|
+ ['outside the chain','3z',C,[],newer,false,1],
|
|
+ ['outside the chain with --migrate','3z',C,['--migrate'],newer,false,1],
|
|
+ ];
|
|
+ for(const [name,store,to,flags,why,backup,code] of cases)await t.test(name,async(t)=>{
|
|
+ const e=await mk(t);await seed(e,{store});
|
|
+ const before=fp(e),data=tree(e.data),n=calls(e).length,logs=logLines(e).length;
|
|
+ const p=await run(e,'activate',to,'acme','--plan',...flags);assert.equal(p.code,0,p.err);assert.equal(p.err,'');
|
|
+ const out=p.out.split('\n');assert.ok(out.includes(why),p.out);
|
|
+ assert.deepEqual(out.filter((x)=>x.startsWith('backup')),[backup?planBackup(e):planNoBackup]);
|
|
+ assert.deepEqual(fp(e),before);assert.deepEqual(tree(e.data),data);assert.deepEqual(startsStops(e,n),[]);assert.equal(logLines(e).length,logs);
|
|
+ assert.ok(!existsSync(join(e.data,'backups')));
|
|
+ const r=await run(e,'activate',to,'acme',...flags,'--timeout','3');assert.equal(r.code,code,r.out+r.err);
|
|
+ assert.equal(existsSync(join(e.data,'backups','stack')),backup);assert.equal(logLines(e).at(-1).backup??null,backup?logLines(e).at(-1).activation:null);
|
|
+ });
|
|
+});
|
|
+
|
|
// Row 178: proof metadata uses temp fixture files, never the installed slot.
|
|
async function seedProof(e) {
|
|
await seed(e);
|
|
diff --git a/scripts/stack-release.sh b/scripts/stack-release.sh
|
|
index f8051d81c..5779b64f7 100755
|
|
--- a/scripts/stack-release.sh
|
|
+++ b/scripts/stack-release.sh
|
|
@@ -797,6 +797,9 @@ plan() {
|
|
echo "store schema: $S_SCHEMA ($S_FROM)"
|
|
echo "target schema: $T_SCHEMA"
|
|
[ "$S_SCHEMA" = "$P_SCHEMA" ] || [ -n "$S_CHANGED" ] || echo "note: the pointer says $P_SCHEMA; the run reads the stopped store and goes by that"
|
|
+ # Row 186: set when run_steps would roll back with store-newer or migration-needs-flag, which
|
|
+ # come before backup_store. A read the bus stopped under judges nothing, so it keeps the backup line.
|
|
+ local early=""
|
|
if [ -n "$S_CHANGED" ]; then
|
|
: # no migration or restore line from a read the bus stopped under
|
|
elif [ "$S_SCHEMA" = "$T_SCHEMA" ]; then
|
|
@@ -806,17 +809,21 @@ plan() {
|
|
echo "migration steps: $(plan_steps)"
|
|
echo "needs: --migrate$([ "$MIGRATE" = 1 ] && echo ' (given)' || echo ' (not given; the run would roll back with migration-needs-flag)')"
|
|
echo "needs: Jason present for this run (decision 96 condition 2)"
|
|
+ [ "$MIGRATE" = 1 ] || early=1
|
|
elif [ "$OP" = activate ]; then
|
|
echo "migration: none possible; $S_SCHEMA is not in $T_SCHEMA's migration chain, so the run would roll back with store-newer"
|
|
+ early=1
|
|
else
|
|
echo "restore: the store must go back to $T_SCHEMA; needs --restore $(from_log backup || echo ACTIVATION)"
|
|
fi
|
|
if [ "$OP" != activate ]; then
|
|
: # rollback takes no backup of its own
|
|
- elif [ -e "$STORE" ]; then
|
|
- echo "backup: the run backs up the stopped store to $DATA/backups/stack/<activation>/ before any migration"
|
|
- else
|
|
+ elif [ ! -e "$STORE" ]; then
|
|
echo "backup: none; there is no store file"
|
|
+ elif [ -n "$early" ]; then
|
|
+ echo "backup: none; the run rolls back before the backup"
|
|
+ else
|
|
+ echo "backup: the run backs up the stopped store to $DATA/backups/stack/<activation>/ before any migration"
|
|
fi
|
|
plan_commits
|
|
[ "$P_PENDING" = 0 ] || echo "pm: the pointer is pending (activate --pm-after-harness); the bus runs without its PM"
|