instar 1.3.54 → 1.3.56
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/dist/cli.js +21 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/machine.d.ts.map +1 -1
- package/dist/commands/machine.js +25 -0
- package/dist/commands/machine.js.map +1 -1
- package/dist/commands/setup.d.ts +11 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +31 -14
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/test-as-self.d.ts +41 -0
- package/dist/commands/test-as-self.d.ts.map +1 -0
- package/dist/commands/test-as-self.js +259 -0
- package/dist/commands/test-as-self.js.map +1 -0
- package/dist/commands/testAsSelfValidation.d.ts +43 -0
- package/dist/commands/testAsSelfValidation.d.ts.map +1 -0
- package/dist/commands/testAsSelfValidation.js +84 -0
- package/dist/commands/testAsSelfValidation.js.map +1 -0
- package/dist/core/GitSync.d.ts +7 -0
- package/dist/core/GitSync.d.ts.map +1 -1
- package/dist/core/GitSync.js +36 -0
- package/dist/core/GitSync.js.map +1 -1
- package/dist/core/mergeRegistry.d.ts +28 -0
- package/dist/core/mergeRegistry.d.ts.map +1 -0
- package/dist/core/mergeRegistry.js +86 -0
- package/dist/core/mergeRegistry.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +14 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/package.json +1 -1
- package/scripts/post-publish-smoke.mjs +80 -0
- package/src/data/builtin-manifest.json +31 -31
- package/src/scaffold/templates.ts +14 -0
- package/upgrades/1.3.53.md +20 -28
- package/upgrades/1.3.54.md +27 -41
- package/upgrades/1.3.56.md +35 -0
- package/upgrades/side-effects/init-join-launchagent-handoff.md +62 -0
- package/upgrades/side-effects/launchctl-test-hygiene.md +42 -0
- package/upgrades/side-effects/mesh-git-substrate-auto-reconcile.md +70 -0
- package/upgrades/side-effects/publish-completeness-smoke-gate.md +47 -0
- package/upgrades/side-effects/test-as-self-orchestrator.md +66 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* post-publish-smoke.mjs — regression gate that a freshly-published instar
|
|
4
|
+
* tarball actually installs + runs.
|
|
5
|
+
*
|
|
6
|
+
* Track A of MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS (re-scoped). The 2026-05-27
|
|
7
|
+
* "empty dist" scare turned out to be self-inflicted (an rsync --delete), NOT a
|
|
8
|
+
* publish bug — the published tarball was complete. So this is NOT fixing an
|
|
9
|
+
* active bug; it's cheap regression insurance: if the publish pipeline EVER
|
|
10
|
+
* ships a tarball missing its compiled output, this catches it within minutes
|
|
11
|
+
* of release instead of when an agent's fresh install fails in the wild.
|
|
12
|
+
*
|
|
13
|
+
* What it does (in CI, right after `npm publish`):
|
|
14
|
+
* 1. Wait for npm to propagate the just-published version (bounded retry).
|
|
15
|
+
* 2. `npm install instar@<version>` into a throwaway prefix.
|
|
16
|
+
* 3. Run the installed `dist/cli.js --version`.
|
|
17
|
+
* 4. Assert it reports <version>. Exit 1 (fail the release workflow) otherwise.
|
|
18
|
+
*
|
|
19
|
+
* Usage: node scripts/post-publish-smoke.mjs <version>
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { execFileSync } from 'node:child_process';
|
|
23
|
+
import { mkdtempSync, existsSync } from 'node:fs';
|
|
24
|
+
import { tmpdir } from 'node:os';
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
|
|
27
|
+
/** Pure: does the `instar --version` output report the expected version? */
|
|
28
|
+
export function versionMatches(cliOutput, expected) {
|
|
29
|
+
// cli prints the bare version (commander default) possibly with surrounding whitespace/newlines.
|
|
30
|
+
return cliOutput.split(/\s+/).map((s) => s.trim()).includes(expected);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
34
|
+
|
|
35
|
+
async function waitForPropagation(version, deadlineMs) {
|
|
36
|
+
const end = Date.now() + deadlineMs;
|
|
37
|
+
while (Date.now() < end) {
|
|
38
|
+
try {
|
|
39
|
+
const published = execFileSync('npm', ['view', `instar@${version}`, 'version'], { encoding: 'utf-8' }).trim();
|
|
40
|
+
if (published === version) return true;
|
|
41
|
+
} catch { /* not propagated yet */ }
|
|
42
|
+
await sleep(10_000);
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function main() {
|
|
48
|
+
const version = process.argv[2];
|
|
49
|
+
if (!version) { console.error('Usage: post-publish-smoke.mjs <version>'); process.exit(2); }
|
|
50
|
+
|
|
51
|
+
console.log(`[smoke] waiting for instar@${version} to propagate on npm…`);
|
|
52
|
+
if (!await waitForPropagation(version, 180_000)) {
|
|
53
|
+
console.error(`[smoke] instar@${version} did not appear on npm within 3m`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const prefix = mkdtempSync(path.join(tmpdir(), 'instar-smoke-'));
|
|
58
|
+
console.log(`[smoke] clean-installing instar@${version} into ${prefix}`);
|
|
59
|
+
execFileSync('npm', ['install', '--prefix', prefix, `instar@${version}`], { encoding: 'utf-8', stdio: 'inherit' });
|
|
60
|
+
|
|
61
|
+
const cli = path.join(prefix, 'node_modules', 'instar', 'dist', 'cli.js');
|
|
62
|
+
if (!existsSync(cli)) {
|
|
63
|
+
console.error(`[smoke] FAIL: ${cli} missing — the published tarball shipped without its compiled dist.`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const out = execFileSync('node', [cli, '--version'], { encoding: 'utf-8' });
|
|
68
|
+
if (!versionMatches(out, version)) {
|
|
69
|
+
console.error(`[smoke] FAIL: \`instar --version\` reported "${out.trim()}", expected "${version}".`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log(`[smoke] ✓ instar@${version} clean-installs and runs (--version → ${version}).`);
|
|
74
|
+
process.exit(0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Only run main() when invoked directly (not when imported by the unit test).
|
|
78
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
79
|
+
main().catch((err) => { console.error(`[smoke] error: ${err?.message ?? err}`); process.exit(1); });
|
|
80
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-28T07:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-05-28T07:50:52.270Z",
|
|
5
|
+
"instarVersion": "1.3.56",
|
|
6
6
|
"entryCount": 193,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -769,7 +769,7 @@
|
|
|
769
769
|
"type": "cli-command",
|
|
770
770
|
"domain": "setup",
|
|
771
771
|
"sourcePath": "src/cli.ts",
|
|
772
|
-
"contentHash": "
|
|
772
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
773
773
|
"since": "2025-01-01"
|
|
774
774
|
},
|
|
775
775
|
"cli:setup": {
|
|
@@ -777,7 +777,7 @@
|
|
|
777
777
|
"type": "cli-command",
|
|
778
778
|
"domain": "setup",
|
|
779
779
|
"sourcePath": "src/cli.ts",
|
|
780
|
-
"contentHash": "
|
|
780
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
781
781
|
"since": "2025-01-01"
|
|
782
782
|
},
|
|
783
783
|
"cli:add": {
|
|
@@ -785,7 +785,7 @@
|
|
|
785
785
|
"type": "cli-command",
|
|
786
786
|
"domain": "setup",
|
|
787
787
|
"sourcePath": "src/cli.ts",
|
|
788
|
-
"contentHash": "
|
|
788
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
789
789
|
"since": "2025-01-01"
|
|
790
790
|
},
|
|
791
791
|
"cli:backup": {
|
|
@@ -793,7 +793,7 @@
|
|
|
793
793
|
"type": "cli-command",
|
|
794
794
|
"domain": "operations",
|
|
795
795
|
"sourcePath": "src/cli.ts",
|
|
796
|
-
"contentHash": "
|
|
796
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
797
797
|
"since": "2025-01-01"
|
|
798
798
|
},
|
|
799
799
|
"cli:git": {
|
|
@@ -801,7 +801,7 @@
|
|
|
801
801
|
"type": "cli-command",
|
|
802
802
|
"domain": "coordination",
|
|
803
803
|
"sourcePath": "src/cli.ts",
|
|
804
|
-
"contentHash": "
|
|
804
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
805
805
|
"since": "2025-01-01"
|
|
806
806
|
},
|
|
807
807
|
"cli:memory": {
|
|
@@ -809,7 +809,7 @@
|
|
|
809
809
|
"type": "cli-command",
|
|
810
810
|
"domain": "memory",
|
|
811
811
|
"sourcePath": "src/cli.ts",
|
|
812
|
-
"contentHash": "
|
|
812
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
813
813
|
"since": "2025-01-01"
|
|
814
814
|
},
|
|
815
815
|
"cli:knowledge": {
|
|
@@ -817,7 +817,7 @@
|
|
|
817
817
|
"type": "cli-command",
|
|
818
818
|
"domain": "memory",
|
|
819
819
|
"sourcePath": "src/cli.ts",
|
|
820
|
-
"contentHash": "
|
|
820
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
821
821
|
"since": "2025-01-01"
|
|
822
822
|
},
|
|
823
823
|
"cli:semantic": {
|
|
@@ -825,7 +825,7 @@
|
|
|
825
825
|
"type": "cli-command",
|
|
826
826
|
"domain": "memory",
|
|
827
827
|
"sourcePath": "src/cli.ts",
|
|
828
|
-
"contentHash": "
|
|
828
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
829
829
|
"since": "2025-01-01"
|
|
830
830
|
},
|
|
831
831
|
"cli:intent": {
|
|
@@ -833,7 +833,7 @@
|
|
|
833
833
|
"type": "cli-command",
|
|
834
834
|
"domain": "intent",
|
|
835
835
|
"sourcePath": "src/cli.ts",
|
|
836
|
-
"contentHash": "
|
|
836
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
837
837
|
"since": "2025-01-01"
|
|
838
838
|
},
|
|
839
839
|
"cli:feedback": {
|
|
@@ -841,7 +841,7 @@
|
|
|
841
841
|
"type": "cli-command",
|
|
842
842
|
"domain": "feedback",
|
|
843
843
|
"sourcePath": "src/cli.ts",
|
|
844
|
-
"contentHash": "
|
|
844
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
845
845
|
"since": "2025-01-01"
|
|
846
846
|
},
|
|
847
847
|
"cli:server": {
|
|
@@ -849,7 +849,7 @@
|
|
|
849
849
|
"type": "cli-command",
|
|
850
850
|
"domain": "server",
|
|
851
851
|
"sourcePath": "src/cli.ts",
|
|
852
|
-
"contentHash": "
|
|
852
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
853
853
|
"since": "2025-01-01"
|
|
854
854
|
},
|
|
855
855
|
"cli:status": {
|
|
@@ -857,7 +857,7 @@
|
|
|
857
857
|
"type": "cli-command",
|
|
858
858
|
"domain": "monitoring",
|
|
859
859
|
"sourcePath": "src/cli.ts",
|
|
860
|
-
"contentHash": "
|
|
860
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
861
861
|
"since": "2025-01-01"
|
|
862
862
|
},
|
|
863
863
|
"cli:user": {
|
|
@@ -865,7 +865,7 @@
|
|
|
865
865
|
"type": "cli-command",
|
|
866
866
|
"domain": "users",
|
|
867
867
|
"sourcePath": "src/cli.ts",
|
|
868
|
-
"contentHash": "
|
|
868
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
869
869
|
"since": "2025-01-01"
|
|
870
870
|
},
|
|
871
871
|
"cli:relationship": {
|
|
@@ -873,7 +873,7 @@
|
|
|
873
873
|
"type": "cli-command",
|
|
874
874
|
"domain": "relationships",
|
|
875
875
|
"sourcePath": "src/cli.ts",
|
|
876
|
-
"contentHash": "
|
|
876
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
877
877
|
"since": "2025-01-01"
|
|
878
878
|
},
|
|
879
879
|
"cli:job": {
|
|
@@ -881,7 +881,7 @@
|
|
|
881
881
|
"type": "cli-command",
|
|
882
882
|
"domain": "scheduling",
|
|
883
883
|
"sourcePath": "src/cli.ts",
|
|
884
|
-
"contentHash": "
|
|
884
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
885
885
|
"since": "2025-01-01"
|
|
886
886
|
},
|
|
887
887
|
"cli:lifeline": {
|
|
@@ -889,7 +889,7 @@
|
|
|
889
889
|
"type": "cli-command",
|
|
890
890
|
"domain": "communication",
|
|
891
891
|
"sourcePath": "src/cli.ts",
|
|
892
|
-
"contentHash": "
|
|
892
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
893
893
|
"since": "2025-01-01"
|
|
894
894
|
},
|
|
895
895
|
"cli:list": {
|
|
@@ -897,7 +897,7 @@
|
|
|
897
897
|
"type": "cli-command",
|
|
898
898
|
"domain": "monitoring",
|
|
899
899
|
"sourcePath": "src/cli.ts",
|
|
900
|
-
"contentHash": "
|
|
900
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
901
901
|
"since": "2025-01-01"
|
|
902
902
|
},
|
|
903
903
|
"cli:autostart": {
|
|
@@ -905,7 +905,7 @@
|
|
|
905
905
|
"type": "cli-command",
|
|
906
906
|
"domain": "operations",
|
|
907
907
|
"sourcePath": "src/cli.ts",
|
|
908
|
-
"contentHash": "
|
|
908
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
909
909
|
"since": "2025-01-01"
|
|
910
910
|
},
|
|
911
911
|
"cli:migrate": {
|
|
@@ -913,7 +913,7 @@
|
|
|
913
913
|
"type": "cli-command",
|
|
914
914
|
"domain": "updates",
|
|
915
915
|
"sourcePath": "src/cli.ts",
|
|
916
|
-
"contentHash": "
|
|
916
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
917
917
|
"since": "2025-01-01"
|
|
918
918
|
},
|
|
919
919
|
"cli:machines": {
|
|
@@ -921,7 +921,7 @@
|
|
|
921
921
|
"type": "cli-command",
|
|
922
922
|
"domain": "coordination",
|
|
923
923
|
"sourcePath": "src/cli.ts",
|
|
924
|
-
"contentHash": "
|
|
924
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
925
925
|
"since": "2025-01-01"
|
|
926
926
|
},
|
|
927
927
|
"cli:whoami": {
|
|
@@ -929,7 +929,7 @@
|
|
|
929
929
|
"type": "cli-command",
|
|
930
930
|
"domain": "identity",
|
|
931
931
|
"sourcePath": "src/cli.ts",
|
|
932
|
-
"contentHash": "
|
|
932
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
933
933
|
"since": "2025-01-01"
|
|
934
934
|
},
|
|
935
935
|
"cli:pair": {
|
|
@@ -937,7 +937,7 @@
|
|
|
937
937
|
"type": "cli-command",
|
|
938
938
|
"domain": "coordination",
|
|
939
939
|
"sourcePath": "src/cli.ts",
|
|
940
|
-
"contentHash": "
|
|
940
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
941
941
|
"since": "2025-01-01"
|
|
942
942
|
},
|
|
943
943
|
"cli:join": {
|
|
@@ -945,7 +945,7 @@
|
|
|
945
945
|
"type": "cli-command",
|
|
946
946
|
"domain": "coordination",
|
|
947
947
|
"sourcePath": "src/cli.ts",
|
|
948
|
-
"contentHash": "
|
|
948
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
949
949
|
"since": "2025-01-01"
|
|
950
950
|
},
|
|
951
951
|
"cli:wakeup": {
|
|
@@ -953,7 +953,7 @@
|
|
|
953
953
|
"type": "cli-command",
|
|
954
954
|
"domain": "coordination",
|
|
955
955
|
"sourcePath": "src/cli.ts",
|
|
956
|
-
"contentHash": "
|
|
956
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
957
957
|
"since": "2025-01-01"
|
|
958
958
|
},
|
|
959
959
|
"cli:leave": {
|
|
@@ -961,7 +961,7 @@
|
|
|
961
961
|
"type": "cli-command",
|
|
962
962
|
"domain": "coordination",
|
|
963
963
|
"sourcePath": "src/cli.ts",
|
|
964
|
-
"contentHash": "
|
|
964
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
965
965
|
"since": "2025-01-01"
|
|
966
966
|
},
|
|
967
967
|
"cli:doctor": {
|
|
@@ -969,7 +969,7 @@
|
|
|
969
969
|
"type": "cli-command",
|
|
970
970
|
"domain": "monitoring",
|
|
971
971
|
"sourcePath": "src/cli.ts",
|
|
972
|
-
"contentHash": "
|
|
972
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
973
973
|
"since": "2025-01-01"
|
|
974
974
|
},
|
|
975
975
|
"cli:review": {
|
|
@@ -977,7 +977,7 @@
|
|
|
977
977
|
"type": "cli-command",
|
|
978
978
|
"domain": "monitoring",
|
|
979
979
|
"sourcePath": "src/cli.ts",
|
|
980
|
-
"contentHash": "
|
|
980
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
981
981
|
"since": "2025-01-01"
|
|
982
982
|
},
|
|
983
983
|
"cli:nuke": {
|
|
@@ -985,7 +985,7 @@
|
|
|
985
985
|
"type": "cli-command",
|
|
986
986
|
"domain": "operations",
|
|
987
987
|
"sourcePath": "src/cli.ts",
|
|
988
|
-
"contentHash": "
|
|
988
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
989
989
|
"since": "2025-01-01"
|
|
990
990
|
},
|
|
991
991
|
"cli:playbook": {
|
|
@@ -993,7 +993,7 @@
|
|
|
993
993
|
"type": "cli-command",
|
|
994
994
|
"domain": "context",
|
|
995
995
|
"sourcePath": "src/cli.ts",
|
|
996
|
-
"contentHash": "
|
|
996
|
+
"contentHash": "61519ff00a42e4d859ad18e6ddade404309a1e047ff33cca31693e06a05bf622",
|
|
997
997
|
"since": "2025-01-01"
|
|
998
998
|
},
|
|
999
999
|
"template:build-stop-hook.sh": {
|
|
@@ -1217,6 +1217,20 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
|
|
|
1217
1217
|
**Why:** the macOS sandbox can revoke filesystem access to anything outside the agent home mid-session, with no in-session recovery path. The agent home (\`~/.instar/agents/<agent>/\`) is the one location the sandbox cannot revoke. \`instar worktree create\` places the worktree at \`~/.instar/agents/<agent>/.worktrees/<slug>/\` and refuses any other destination. Spec: \`docs/specs/AGENT-WORKTREE-CONVENTION-SPEC.md\`.
|
|
1218
1218
|
|
|
1219
1219
|
**Caveat — git identity env vars:** the CLI sets per-worktree \`user.name\` / \`user.email\` to \`Instar Agent (<name>)\` / \`<name>@instar.local\`. \`GIT_AUTHOR_NAME\` / \`GIT_COMMITTER_EMAIL\` in the calling environment override that local config. Agents that care about commit attribution must avoid exporting those vars.
|
|
1220
|
+
|
|
1221
|
+
## Test-As-Self (Throwaway-Deploy Harness)
|
|
1222
|
+
|
|
1223
|
+
\`instar test-as-self\` deploys the CURRENT dist into a throwaway agent home, verifies it's healthy, optionally runs a real Telegram round-trip, and tears down — clean evidence instead of post-hoc log forensics. Use it BEFORE shipping a change to the deploy/lifeline/server path, AFTER landing one, or to reproduce a crash deterministically.
|
|
1224
|
+
|
|
1225
|
+
\`\`\`bash
|
|
1226
|
+
instar test-as-self --no-roundtrip # deploy + verify only (no bot needed)
|
|
1227
|
+
instar test-as-self --bot-token <secret-drop-id> # + a real Telegram round-trip via a throwaway bot
|
|
1228
|
+
instar test-as-self --keep # leave the throwaway running for inspection
|
|
1229
|
+
\`\`\`
|
|
1230
|
+
|
|
1231
|
+
**Structural guards (you cannot foot-gun these):** \`--target\` can never be your canonical agent home or a protected agent (e.g. Bob); \`--bot-token\` refuses a raw token on the command line — pass a Secret Drop ID and the token is retrieved in-memory, never via argv. It emits a single JSON report; exit 0 = all steps PASS.
|
|
1232
|
+
|
|
1233
|
+
**Proactive trigger:** when you're about to ship or just shipped a change touching the deploy/lifeline/server-startup path, run this against a throwaway home first — don't guess from logs.
|
|
1220
1234
|
`;
|
|
1221
1235
|
|
|
1222
1236
|
if (hasTelegram) {
|
package/upgrades/1.3.53.md
CHANGED
|
@@ -4,43 +4,35 @@
|
|
|
4
4
|
|
|
5
5
|
## What Changed
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`npm run lint`) bans credentialed-URL logging going forward.
|
|
15
|
-
|
|
16
|
-
Also: the outbound-message convergence-check gate now trusts the agent's own tunnel
|
|
17
|
-
domain (read live from tunnel state) + the common tunnel domains, so an agent can
|
|
18
|
-
send links to its own private views without the gate flagging them as fabricated.
|
|
7
|
+
**`instar join` now installs auto-start for the joined home (mesh bootstrap fix).**
|
|
8
|
+
Previously a joined mesh agent had no LaunchAgent/systemd unit, so it never
|
|
9
|
+
auto-started — and a stale auto-start entry from a prior `instar init` of the same
|
|
10
|
+
name (at a different directory) would keep respawning a server against the WRONG
|
|
11
|
+
home, fighting the joined one for the port. join now installs auto-start for its
|
|
12
|
+
own home; because the unit is keyed on the agent name, this cleanly replaces any
|
|
13
|
+
stale same-name unit. One unit, pointing at the right home.
|
|
19
14
|
|
|
20
15
|
## What to Tell Your User
|
|
21
16
|
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
agent
|
|
26
|
-
|
|
27
|
-
pages without my safety gate mistakenly treating my own tunnel address as suspicious.
|
|
17
|
+
- Joining a second machine to your agent's mesh now "just works" for staying alive
|
|
18
|
+
across reboots — the joined machine sets up its own background auto-start, and it
|
|
19
|
+
won't collide with leftovers from an earlier setup attempt of the same agent. You
|
|
20
|
+
no longer have to hand-start the joined agent or manually clean up a stale startup
|
|
21
|
+
entry.
|
|
28
22
|
|
|
29
23
|
## Summary of New Capabilities
|
|
30
24
|
|
|
31
25
|
| Capability | How to Use |
|
|
32
26
|
|-----------|-----------|
|
|
33
|
-
|
|
|
34
|
-
| `lint-no-direct-url-log` | Automatic in `npm run lint` / CI — fails the build if a credentialed URL is logged without redaction. |
|
|
35
|
-
| Convergence-check own-tunnel trust | Automatic — the message gate no longer flags the agent's own tunnel URLs as unfamiliar. |
|
|
27
|
+
| join installs auto-start | Automatic — `instar join` now registers the joined home's background auto-start (LaunchAgent on macOS, systemd on Linux), replacing any stale same-name unit. |
|
|
36
28
|
|
|
37
29
|
## Evidence
|
|
38
30
|
|
|
39
|
-
**
|
|
40
|
-
`tests/unit/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`upgrades/side-effects/
|
|
31
|
+
**Small, contained join-flow addition; no change to init.** Unit test
|
|
32
|
+
`tests/unit/init-join-launchd-handoff.test.ts` (2 cases, darwin-gated, sandboxed
|
|
33
|
+
$HOME) proves the Label-keyed replace: two installs for the same name + different
|
|
34
|
+
dirs leave ONE plist pointing at the second (joined) dir; standby install writes
|
|
35
|
+
server-start (not lifeline) args. `tsc --noEmit` clean. The autostart install is
|
|
36
|
+
try/catch-wrapped so a failure never fails the join. Side-effects review:
|
|
37
|
+
`upgrades/side-effects/init-join-launchagent-handoff.md`. Spec: Track C of
|
|
46
38
|
`docs/specs/MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS-SPEC.md`.
|
package/upgrades/1.3.54.md
CHANGED
|
@@ -1,57 +1,43 @@
|
|
|
1
1
|
# Instar Upgrade Guide — NEXT
|
|
2
2
|
|
|
3
|
-
<!-- bump:
|
|
3
|
+
<!-- bump: patch -->
|
|
4
4
|
|
|
5
5
|
## What Changed
|
|
6
6
|
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
handler lived only on the mentor-BOT adapter (Telegram polling), so a reply
|
|
17
|
-
arriving via `/a2a/inbox` had nowhere to land. Now Echo's primary adapter
|
|
18
|
-
persists mentee replies to `mentor-replies.jsonl` (finding-emission-only,
|
|
19
|
-
capability-handle path per spec §250).
|
|
20
|
-
|
|
21
|
-
2. **`deliverA2aMessage` unified transport helper.** Both directions
|
|
22
|
-
(mentor→mentee `deliverToMentee` and mentee→mentor reply) now route through
|
|
23
|
-
one helper: same-machine peers get an HTTP POST to `/a2a/inbox`; cross-
|
|
24
|
-
machine falls back to the Telegram bot path. Fixes the **`\n\n` marker bug**
|
|
25
|
-
from #466 (`deliverToMentee` built the marker with a single `\n`; the parser
|
|
26
|
-
requires `\n\n` between marker and body — single-newline markers were
|
|
27
|
-
silently dropped as `agent-marker-malformed`).
|
|
28
|
-
|
|
29
|
-
3. **Mentee reply-capture race fix.** The mentee role-handler captured the
|
|
30
|
-
tmux pane AFTER the session completed — but the reaper removes the pane
|
|
31
|
-
first, so `captureOutput` returned empty ("mentee session produced empty
|
|
32
|
-
reply"). Now it captures the last non-empty snapshot WHILE the session is
|
|
33
|
-
alive, so a completed-then-reaped session still yields its output.
|
|
7
|
+
**Mesh registry conflicts now auto-merge deterministically (multi-machine
|
|
8
|
+
robustness).** When two machines concurrently update the shared mesh state — e.g.
|
|
9
|
+
one bumps the awake-lease while another joins — their `machines/registry.json`
|
|
10
|
+
commits can collide on rebase. GitSync's conflict resolver previously had no case
|
|
11
|
+
for the registry, so such a conflict fell to LLM/manual and the mesh could stay
|
|
12
|
+
split (one machine seeing a different roster than the other). New `mergeRegistry`
|
|
13
|
+
merges them losslessly: union the machines (fresher `lastSeen` wins per machine,
|
|
14
|
+
revocations sticky), keep the higher-epoch lease. Both machines compute the
|
|
15
|
+
identical result, so the mesh converges on its own.
|
|
34
16
|
|
|
35
17
|
## What to Tell Your User
|
|
36
18
|
|
|
37
|
-
|
|
38
|
-
a
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
changes needed.
|
|
19
|
+
- Running your agent across two machines is now more robust: if both machines
|
|
20
|
+
record a change to the shared roster at the same moment, they'll automatically
|
|
21
|
+
reconcile to the same view instead of disagreeing about who's awake or which
|
|
22
|
+
machines are in the mesh. Nothing for you to do — it just self-heals.
|
|
42
23
|
|
|
43
24
|
## Summary of New Capabilities
|
|
44
25
|
|
|
45
26
|
| Capability | How to Use |
|
|
46
27
|
|-----------|-----------|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
| Mentee reply capture-while-alive | Survives the session-reap race so the mentee's output is actually captured + replied. |
|
|
28
|
+
| `mergeRegistry(ours, theirs)` | Internal — deterministic semantic merge of two mesh registries (union machines, higher-epoch lease). |
|
|
29
|
+
| GitSync registry conflict auto-resolve | Automatic — a `machines/registry.json` rebase conflict now merges deterministically instead of escalating to LLM/manual. |
|
|
50
30
|
|
|
51
31
|
## Evidence
|
|
52
32
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
`
|
|
56
|
-
|
|
57
|
-
|
|
33
|
+
**Small, precise fix — NOT the spec's drafted sync() rewrite (sync() is already
|
|
34
|
+
mature; the real gap was a missing conflict-resolution case).** Unit test
|
|
35
|
+
`tests/unit/mergeRegistry.test.ts` (6 cases) covers the exact 2026-05-27
|
|
36
|
+
divergence (concurrent lease-bump + join → both machines + higher epoch survive),
|
|
37
|
+
order-independence, same-epoch tiebreak, sticky revocation, missing lease, and
|
|
38
|
+
syncSequence tiebreak. `tsc --noEmit` + destructive-lint clean. The fix slots into
|
|
39
|
+
GitSync's existing Tier-0 `tryAutoResolve` (same wiring as relationships/jobs/
|
|
40
|
+
evolution) and is try/catch fail-safe (falls back to the prior LLM/manual tier on
|
|
41
|
+
any error). Side-effects review:
|
|
42
|
+
`upgrades/side-effects/mesh-git-substrate-auto-reconcile.md`. Spec: Track D of
|
|
43
|
+
`docs/specs/MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS-SPEC.md`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Instar Upgrade Guide — NEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**Test-hygiene: unit tests no longer load plists into the real launchd.** The
|
|
8
|
+
auto-start installer (`installMacOSLaunchAgent` / fleet-watchdog) did a real
|
|
9
|
+
`launchctl bootstrap` after writing a plist — so a unit test exercising the
|
|
10
|
+
plist-writing path loaded tmpdir-pointed plists into the operator's real launchd,
|
|
11
|
+
leaving inert stale entries behind. New `launchctlLoadAllowed()` gate skips the
|
|
12
|
+
live load under a test runner (vitest sets `VITEST`) or when
|
|
13
|
+
`INSTAR_SKIP_LAUNCHCTL_LOAD` is set. Production behavior is unchanged.
|
|
14
|
+
|
|
15
|
+
## What to Tell Your User
|
|
16
|
+
|
|
17
|
+
- Internal test-hygiene fix: my test suite no longer accidentally registers
|
|
18
|
+
throwaway background-service entries on the machine it runs on. Nothing
|
|
19
|
+
user-facing; production startup is unchanged.
|
|
20
|
+
|
|
21
|
+
## Summary of New Capabilities
|
|
22
|
+
|
|
23
|
+
| Capability | How to Use |
|
|
24
|
+
|-----------|-----------|
|
|
25
|
+
| `launchctlLoadAllowed()` gate | Automatic — skips the live `launchctl bootstrap` under VITEST / `INSTAR_SKIP_LAUNCHCTL_LOAD`; production loads normally. |
|
|
26
|
+
|
|
27
|
+
## Evidence
|
|
28
|
+
|
|
29
|
+
**One helper + two install-path wraps; production load path unchanged.** Unit
|
|
30
|
+
test `tests/unit/launchctl-load-guard.test.ts` (3): false under VITEST, false
|
|
31
|
+
under the explicit opt-out, true in production. Verified the merged Track C test
|
|
32
|
+
now runs with NO real-launchd pollution (no stale mmtest* entries) while still
|
|
33
|
+
passing. `tsc` clean. Side-effects review:
|
|
34
|
+
`upgrades/side-effects/launchctl-test-hygiene.md`. Follow-up to Track C of
|
|
35
|
+
`docs/specs/MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS-SPEC.md`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Side-Effects Review — Init→Join LaunchAgent handoff (MM-Bootstrap Track C)
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MULTI-MACHINE-BOOTSTRAP-ROBUSTNESS-SPEC.md` §Track C (approved PR #465).
|
|
4
|
+
|
|
5
|
+
**Scope.** `src/commands/machine.ts` (joinMesh — add Step 6: install auto-start
|
|
6
|
+
for the joined home), `tests/unit/init-join-launchd-handoff.test.ts` (new).
|
|
7
|
+
|
|
8
|
+
**Problem.** `instar join` never installed an auto-start plist for the joined
|
|
9
|
+
home. So a joined agent had no LaunchAgent/systemd unit (operator had to
|
|
10
|
+
hand-start it), and — worse — a stale `ai.instar.<projectName>` plist left by a
|
|
11
|
+
prior `instar init` of the SAME name at a DIFFERENT home kept respawning a
|
|
12
|
+
server against the wrong directory, fighting the joined one for the port +
|
|
13
|
+
identity (observed live 2026-05-27 during the mesh bring-up).
|
|
14
|
+
|
|
15
|
+
**Fix.** joinMesh now calls `installAutoStart(projectName, joinedProjectDir,
|
|
16
|
+
hasTelegram)` after the gitignore step. Because the auto-start plist Label is
|
|
17
|
+
keyed on `projectName` (`ai.instar.<name>`), installing for the joined dir
|
|
18
|
+
cleanly REPLACES any stale same-name plist — one unit, pointing at the joined
|
|
19
|
+
home, zero orphans.
|
|
20
|
+
|
|
21
|
+
**Design note (supersedes the spec's drafted pointer-file C-2).** The spec
|
|
22
|
+
drafted a pointer-file (`active-home`) + plist-wrapper approach. Implementation
|
|
23
|
+
found that unnecessary: the Label is already keyed on projectName, so a
|
|
24
|
+
re-install naturally replaces. The simpler fix (join calls installAutoStart) is
|
|
25
|
+
less code, no new mechanism, same guarantee. Flagged to Justin via Telegram.
|
|
26
|
+
|
|
27
|
+
**Side-effects review.**
|
|
28
|
+
- **No change to `instar init`'s behavior** — init still installs its plist as
|
|
29
|
+
before. Only join now ALSO installs (for its own home).
|
|
30
|
+
- **hasTelegram=false-derived-from-config for the standby** — a joined standby
|
|
31
|
+
installs a server-start unit (ready to take over), not a lifeline. The shipped
|
|
32
|
+
poll-ownership lease prevents dual-poll if telegram is configured on both ends,
|
|
33
|
+
so even if a future config sets hasTelegram=true the 409 class can't recur.
|
|
34
|
+
- **Idempotent + safe** — installAutoStart overwrites the same Label; re-running
|
|
35
|
+
join is harmless. The call is wrapped in try/catch (@silent-fallback-ok): a
|
|
36
|
+
failed auto-start install does NOT fail the join (join still succeeds; operator
|
|
37
|
+
can hand-start).
|
|
38
|
+
- **No new orphans** — the replace property is the whole point; verified by test.
|
|
39
|
+
|
|
40
|
+
**Test coverage.**
|
|
41
|
+
- Unit `tests/unit/init-join-launchd-handoff.test.ts` (2 cases, darwin-gated,
|
|
42
|
+
sandboxed $HOME so it never touches the real LaunchAgents dir): (1) two installs
|
|
43
|
+
same-name + different-dir → ONE plist pointing at the second (joined) dir, init
|
|
44
|
+
dir gone; (2) standby install (hasTelegram=false) writes server-start args, not
|
|
45
|
+
lifeline.
|
|
46
|
+
- E2E launchd lifecycle is quarantined per spec (INSTAR_E2E_LAUNCHD) — macOS-only,
|
|
47
|
+
not run in CI.
|
|
48
|
+
|
|
49
|
+
**Deferred (own follow-up, noted not silently dropped).** The join config-creation
|
|
50
|
+
sub-gap (joined home lacks config.json because it's gitignored; a config.json.bak
|
|
51
|
+
is committed) is a SEPARATE bootstrap gap surfaced the same night. Out of Track C's
|
|
52
|
+
tight autostart scope; tracked for a follow-up so it isn't lost.
|
|
53
|
+
|
|
54
|
+
**Migration parity.** Server source — existing agents pick up the fix on
|
|
55
|
+
auto-update. New joins get the behavior immediately. Existing JOINED agents (rare,
|
|
56
|
+
since join didn't install autostart before) won't have a plist; the forward fix
|
|
57
|
+
covers all new joins, and `instar server start` self-heals an autostart install at
|
|
58
|
+
boot (server.ts autostart-check), so an existing joined agent gets a plist the next
|
|
59
|
+
time its server starts anyway.
|
|
60
|
+
|
|
61
|
+
**Rollback.** Revert the PR. join stops installing autostart (prior behavior).
|
|
62
|
+
No migration to reverse, no data change.
|