instar 1.3.309 → 1.3.311

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.
Files changed (34) hide show
  1. package/dist/commands/init.d.ts.map +1 -1
  2. package/dist/commands/init.js +32 -0
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +17 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/BootSelfKnowledge.d.ts +121 -0
  8. package/dist/core/BootSelfKnowledge.d.ts.map +1 -0
  9. package/dist/core/BootSelfKnowledge.js +285 -0
  10. package/dist/core/BootSelfKnowledge.js.map +1 -0
  11. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  12. package/dist/core/PostUpdateMigrator.js +104 -0
  13. package/dist/core/PostUpdateMigrator.js.map +1 -1
  14. package/dist/core/types.d.ts +26 -0
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/core/types.js.map +1 -1
  17. package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -1
  18. package/dist/monitoring/delivery-failure-sentinel.js +15 -0
  19. package/dist/monitoring/delivery-failure-sentinel.js.map +1 -1
  20. package/dist/scaffold/templates.d.ts.map +1 -1
  21. package/dist/scaffold/templates.js +8 -0
  22. package/dist/scaffold/templates.js.map +1 -1
  23. package/dist/server/routes.d.ts.map +1 -1
  24. package/dist/server/routes.js +135 -0
  25. package/dist/server/routes.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/data/builtin-manifest.json +72 -64
  28. package/src/scaffold/templates.ts +8 -0
  29. package/src/templates/scripts/secret-get.mjs +143 -0
  30. package/upgrades/1.3.310.md +20 -0
  31. package/upgrades/1.3.311.md +20 -0
  32. package/upgrades/sentinel-immediate-first-tick.eli16.md +7 -0
  33. package/upgrades/side-effects/sentinel-immediate-first-tick.md +38 -0
  34. package/upgrades/side-effects/session-boot-self-knowledge.md +78 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * BootSelfKnowledge — the "what I already have" block injected at session start.
3
+ *
4
+ * Spec: docs/specs/session-boot-self-knowledge.md (converged 2026-06-05).
5
+ *
6
+ * Composes ONE bounded markdown block from two deterministic sources:
7
+ * 1. Vault secret NAMES — the per-agent encrypted SecretStore flattened to
8
+ * dot-notation key paths via the SAME secretKeyPaths() helper that
9
+ * /secrets/sync-status uses. Values are NEVER serialized.
10
+ * 2. Operational facts — `selfKnowledge.operationalFacts` from config.json,
11
+ * self-asserted per-machine hints (e.g. the logged-in Playwright seat).
12
+ *
13
+ * This is deterministic config/capability discovery injected as boot context —
14
+ * a capability inventory, not memory, not an authority. It gates nothing.
15
+ *
16
+ * Hardening contract (every rendered name/fact is untrusted display content —
17
+ * key names are writable by peers via secret-sync, facts by the agent itself):
18
+ * - control chars + ANSI stripped, `<`/`>` HTML-escaped (envelope-breakout
19
+ * structurally impossible), names clamped to 128 chars, facts to 256;
20
+ * - key paths depth-capped at 2 (`parent.child (+N nested)`) so structured
21
+ * credentials never leak their internal shape;
22
+ * - alphabetical ordering, 50-name cap, byte-bounded block with an
23
+ * actionable truncation marker (never silent truncation).
24
+ *
25
+ * Vault honesty (bifurcated-master-key lesson, 2026-06-05): absent file →
26
+ * vaultState 'absent' (never an error); a read that throws is retried ONCE
27
+ * (absorbs a benign master-key-rotation race) before reporting
28
+ * 'decrypt-failed' — which is rendered as an explicit hands-off warning, never
29
+ * as an empty vault.
30
+ *
31
+ * NOTE: distinct from the SelfKnowledgeTree (src/knowledge/) — that system is
32
+ * LLM-assisted search over AGENT.md; this is a deterministic boot inventory.
33
+ */
34
+ /** A stored operational fact. The writer route stamps updatedAt + machine; bare strings (hand-authored/legacy) are accepted too. */
35
+ export interface OperationalFact {
36
+ fact: string;
37
+ updatedAt?: string;
38
+ machine?: string;
39
+ }
40
+ export interface BootSelfKnowledgeResult {
41
+ present: boolean;
42
+ block: string;
43
+ names: string[];
44
+ factCount: number;
45
+ vaultState: 'ok' | 'absent' | 'decrypt-failed';
46
+ }
47
+ export interface BootSelfKnowledgeOptions {
48
+ /** The agent's state dir (.instar) — locates the vault. */
49
+ stateDir: string;
50
+ /** Path to .instar/config.json — read FRESH per call (deliberate divergence
51
+ * from boot-frozen ctx.config: flag/fact edits take effect without a server
52
+ * restart — do not "consistency-fix" this back). */
53
+ configPath: string;
54
+ }
55
+ /** Rendering caps (spec §Rendering hardening). */
56
+ export declare const MAX_NAME_CHARS = 128;
57
+ export declare const MAX_FACT_CHARS = 256;
58
+ export declare const MAX_NAMES_RENDERED = 50;
59
+ export declare const MAX_FACTS_STORED = 50;
60
+ export declare const DEFAULT_MAX_BYTES = 2000;
61
+ /** Test seam: clear the module-level cache between tests. */
62
+ export declare function clearBootSelfKnowledgeCache(): void;
63
+ /** Fresh-read the selfKnowledge.sessionContext flags from config.json (never ctx.config — see configPath doc). */
64
+ export declare function readSelfKnowledgeFlags(configPath: string): {
65
+ enabled?: boolean;
66
+ maxInjectedBytes?: number;
67
+ };
68
+ /**
69
+ * Atomic config.json read-mutate-write for the facts writer routes: re-read
70
+ * from disk inside the call (bounding the lost-update window vs the other,
71
+ * pre-existing NON-atomic config writers to this function's own microseconds —
72
+ * last-writer-wins semantics, spec §Writer path), apply the mutator, write to
73
+ * a temp file, rename into place. The mutator returns either {value} (commit)
74
+ * or {error} (abort — nothing is written).
75
+ */
76
+ export declare function writeConfigAtomic<T>(configPath: string, mutate: (cfg: Record<string, unknown>) => {
77
+ value?: T;
78
+ error?: {
79
+ status: number;
80
+ message: string;
81
+ };
82
+ }): {
83
+ value?: T;
84
+ error?: {
85
+ status: number;
86
+ message: string;
87
+ };
88
+ };
89
+ /** Strip control chars + ANSI escapes, HTML-escape angle brackets, clamp length. */
90
+ export declare function sanitizeForBlock(input: string, maxChars: number): string;
91
+ /**
92
+ * Collapse flat dot-notation leaf paths (secretKeyPaths output — the SAME
93
+ * derivation sync-status uses; this is a post-process, never a re-derivation)
94
+ * to depth-2 prefixes. N = count of distinct leaf paths collapsed under the
95
+ * prefix. `telegram.bot.token` + `telegram.bot.chatId` → `telegram.bot (+2 nested)`.
96
+ */
97
+ export declare function collapseToDepth2(leafPaths: string[]): string[];
98
+ export declare class BootSelfKnowledge {
99
+ private readonly stateDir;
100
+ private readonly configPath;
101
+ constructor(opts: BootSelfKnowledgeOptions);
102
+ private vaultPath;
103
+ /**
104
+ * Vault key NAMES + state, via the module cache. Production read path is
105
+ * keychain-backed by default — NO hardcoded forceFileKey (a file-key here
106
+ * would read a different/empty vault in production and recreate the exact
107
+ * "vault looks empty" confusion this module exists to kill; test-safety
108
+ * comes ONLY from the MasterKeyManager VITEST constructor guard).
109
+ */
110
+ private readNames;
111
+ /** Operational facts, read FRESH from config.json (see configPath doc). */
112
+ readFacts(): OperationalFact[];
113
+ /**
114
+ * Build the boot block. `full` bypasses the name-count cap and byte bound
115
+ * (the `?full=1` recovery path the truncation marker points at).
116
+ */
117
+ sessionContext(maxBytes?: number, opts?: {
118
+ full?: boolean;
119
+ }): BootSelfKnowledgeResult;
120
+ }
121
+ //# sourceMappingURL=BootSelfKnowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BootSelfKnowledge.d.ts","sourceRoot":"","sources":["../../src/core/BootSelfKnowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAQH,oIAAoI;AACpI,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,gBAAgB,CAAC;CAChD;AAED,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB;;yDAEqD;IACrD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,kDAAkD;AAClD,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAgBtC,6DAA6D;AAC7D,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,kHAAkH;AAClH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,CAU3G;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK;IAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACnG;IAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAW5D;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAc9D;AAYD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,IAAI,EAAE,wBAAwB;IAK1C,OAAO,CAAC,SAAS;IAIjB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IAgDjB,2EAA2E;IAC3E,SAAS,IAAI,eAAe,EAAE;IAa9B;;;OAGG;IACH,cAAc,CAAC,QAAQ,GAAE,MAA0B,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,uBAAuB;CA4E7G"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * BootSelfKnowledge — the "what I already have" block injected at session start.
3
+ *
4
+ * Spec: docs/specs/session-boot-self-knowledge.md (converged 2026-06-05).
5
+ *
6
+ * Composes ONE bounded markdown block from two deterministic sources:
7
+ * 1. Vault secret NAMES — the per-agent encrypted SecretStore flattened to
8
+ * dot-notation key paths via the SAME secretKeyPaths() helper that
9
+ * /secrets/sync-status uses. Values are NEVER serialized.
10
+ * 2. Operational facts — `selfKnowledge.operationalFacts` from config.json,
11
+ * self-asserted per-machine hints (e.g. the logged-in Playwright seat).
12
+ *
13
+ * This is deterministic config/capability discovery injected as boot context —
14
+ * a capability inventory, not memory, not an authority. It gates nothing.
15
+ *
16
+ * Hardening contract (every rendered name/fact is untrusted display content —
17
+ * key names are writable by peers via secret-sync, facts by the agent itself):
18
+ * - control chars + ANSI stripped, `<`/`>` HTML-escaped (envelope-breakout
19
+ * structurally impossible), names clamped to 128 chars, facts to 256;
20
+ * - key paths depth-capped at 2 (`parent.child (+N nested)`) so structured
21
+ * credentials never leak their internal shape;
22
+ * - alphabetical ordering, 50-name cap, byte-bounded block with an
23
+ * actionable truncation marker (never silent truncation).
24
+ *
25
+ * Vault honesty (bifurcated-master-key lesson, 2026-06-05): absent file →
26
+ * vaultState 'absent' (never an error); a read that throws is retried ONCE
27
+ * (absorbs a benign master-key-rotation race) before reporting
28
+ * 'decrypt-failed' — which is rendered as an explicit hands-off warning, never
29
+ * as an empty vault.
30
+ *
31
+ * NOTE: distinct from the SelfKnowledgeTree (src/knowledge/) — that system is
32
+ * LLM-assisted search over AGENT.md; this is a deterministic boot inventory.
33
+ */
34
+ import fs from 'node:fs';
35
+ import path from 'node:path';
36
+ import os from 'node:os';
37
+ import { SecretStore } from './SecretStore.js';
38
+ import { secretKeyPaths } from './SecretSync.js';
39
+ /** Rendering caps (spec §Rendering hardening). */
40
+ export const MAX_NAME_CHARS = 128;
41
+ export const MAX_FACT_CHARS = 256;
42
+ export const MAX_NAMES_RENDERED = 50;
43
+ export const MAX_FACTS_STORED = 50;
44
+ export const DEFAULT_MAX_BYTES = 2000;
45
+ const KEY_PATH_DEPTH = 2;
46
+ /**
47
+ * Module-level names cache — survives across requests (the per-request
48
+ * BootSelfKnowledge instance reads through it; precedent: Config.ts
49
+ * _frameworkBinaryCache). Keyed on the VAULT FILE'S ABSOLUTE PATH so distinct
50
+ * vaults (parallel AgentServer instances in tests) can never collide; entries
51
+ * are validated against (mtimeMs, size) — never bare mtime — so a restored
52
+ * backup with an older mtime still invalidates on size. Names only, never values.
53
+ */
54
+ const namesCache = new Map();
55
+ /** Test seam: clear the module-level cache between tests. */
56
+ export function clearBootSelfKnowledgeCache() {
57
+ namesCache.clear();
58
+ }
59
+ /** Fresh-read the selfKnowledge.sessionContext flags from config.json (never ctx.config — see configPath doc). */
60
+ export function readSelfKnowledgeFlags(configPath) {
61
+ try {
62
+ const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));
63
+ return raw.selfKnowledge?.sessionContext ?? {};
64
+ }
65
+ catch {
66
+ // @silent-fallback-ok — unreadable/absent config means no flags set; the route then resolves the developmentAgent gate default
67
+ return {};
68
+ }
69
+ }
70
+ /**
71
+ * Atomic config.json read-mutate-write for the facts writer routes: re-read
72
+ * from disk inside the call (bounding the lost-update window vs the other,
73
+ * pre-existing NON-atomic config writers to this function's own microseconds —
74
+ * last-writer-wins semantics, spec §Writer path), apply the mutator, write to
75
+ * a temp file, rename into place. The mutator returns either {value} (commit)
76
+ * or {error} (abort — nothing is written).
77
+ */
78
+ export function writeConfigAtomic(configPath, mutate) {
79
+ let cfg = {};
80
+ if (fs.existsSync(configPath)) {
81
+ cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
82
+ }
83
+ const outcome = mutate(cfg);
84
+ if (outcome.error)
85
+ return outcome;
86
+ const tmp = `${configPath}.tmp.${process.pid}.${Date.now()}`;
87
+ fs.writeFileSync(tmp, JSON.stringify(cfg, null, 2) + '\n');
88
+ fs.renameSync(tmp, configPath);
89
+ return outcome;
90
+ }
91
+ /** Strip control chars + ANSI escapes, HTML-escape angle brackets, clamp length. */
92
+ export function sanitizeForBlock(input, maxChars) {
93
+ let s = String(input)
94
+ // eslint-disable-next-line no-control-regex
95
+ .replace(/\u001b\[[0-9;]*[A-Za-z]/g, '') // ANSI CSI sequences
96
+ // eslint-disable-next-line no-control-regex
97
+ .replace(/[\u0000-\u001f\u007f]/g, ' ') // control chars (incl. newlines) -> space
98
+ .replace(/[\u0060]/g, '\u02cb') // backticks -> modifier-letter grave: a hostile name cannot break the inline-code span
99
+ .replace(/</g, '&lt;')
100
+ .replace(/>/g, '&gt;')
101
+ .trim();
102
+ if (s.length > maxChars)
103
+ s = `${s.slice(0, maxChars - 1)}\u2026`;
104
+ return s;
105
+ }
106
+ /**
107
+ * Collapse flat dot-notation leaf paths (secretKeyPaths output — the SAME
108
+ * derivation sync-status uses; this is a post-process, never a re-derivation)
109
+ * to depth-2 prefixes. N = count of distinct leaf paths collapsed under the
110
+ * prefix. `telegram.bot.token` + `telegram.bot.chatId` → `telegram.bot (+2 nested)`.
111
+ */
112
+ export function collapseToDepth2(leafPaths) {
113
+ const collapsed = new Map(); // prefix → collapsed-leaf count (0 = the leaf itself)
114
+ for (const p of leafPaths) {
115
+ const segs = p.split('.');
116
+ if (segs.length <= KEY_PATH_DEPTH) {
117
+ if (!collapsed.has(p))
118
+ collapsed.set(p, 0);
119
+ }
120
+ else {
121
+ const prefix = segs.slice(0, KEY_PATH_DEPTH).join('.');
122
+ collapsed.set(prefix, (collapsed.get(prefix) ?? 0) + 1);
123
+ }
124
+ }
125
+ return [...collapsed.entries()]
126
+ .map(([prefix, n]) => (n > 0 ? `${prefix} (+${n} nested)` : prefix))
127
+ .sort((a, b) => a.localeCompare(b));
128
+ }
129
+ /** Parse a raw config entry into an OperationalFact (bare strings accepted). */
130
+ function toFact(raw) {
131
+ if (typeof raw === 'string' && raw.trim())
132
+ return { fact: raw };
133
+ if (raw && typeof raw === 'object' && typeof raw.fact === 'string' && raw.fact.trim()) {
134
+ const f = raw;
135
+ return { fact: f.fact, updatedAt: f.updatedAt, machine: f.machine };
136
+ }
137
+ return null;
138
+ }
139
+ export class BootSelfKnowledge {
140
+ stateDir;
141
+ configPath;
142
+ constructor(opts) {
143
+ this.stateDir = opts.stateDir;
144
+ this.configPath = opts.configPath;
145
+ }
146
+ vaultPath() {
147
+ return path.resolve(path.join(this.stateDir, 'secrets', 'config.secrets.enc'));
148
+ }
149
+ /**
150
+ * Vault key NAMES + state, via the module cache. Production read path is
151
+ * keychain-backed by default — NO hardcoded forceFileKey (a file-key here
152
+ * would read a different/empty vault in production and recreate the exact
153
+ * "vault looks empty" confusion this module exists to kill; test-safety
154
+ * comes ONLY from the MasterKeyManager VITEST constructor guard).
155
+ */
156
+ readNames() {
157
+ const vaultPath = this.vaultPath();
158
+ if (!fs.existsSync(vaultPath))
159
+ return { names: [], vaultState: 'absent' };
160
+ let stat;
161
+ try {
162
+ stat = fs.statSync(vaultPath);
163
+ }
164
+ catch {
165
+ // @silent-fallback-ok — vault file raced away between existsSync and stat; absent is the truthful state
166
+ return { names: [], vaultState: 'absent' };
167
+ }
168
+ const cached = namesCache.get(vaultPath);
169
+ if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {
170
+ return { names: cached.names, vaultState: cached.vaultState };
171
+ }
172
+ const store = new SecretStore({ stateDir: this.stateDir });
173
+ let names = null;
174
+ let vaultState = 'ok';
175
+ for (let attempt = 0; attempt < 2; attempt++) {
176
+ try {
177
+ // The decrypted object is not retained beyond this traversal.
178
+ names = secretKeyPaths(store.read());
179
+ break;
180
+ }
181
+ catch {
182
+ // @silent-fallback-ok — NOT silent at the surface: a second failure becomes vaultState decrypt-failed, rendered as the explicit hands-off warning block
183
+ // One retry absorbs a benign mid-rotation race (key swapped between
184
+ // file read and key fetch). A second failure is a real decrypt failure.
185
+ }
186
+ }
187
+ if (names === null) {
188
+ vaultState = 'decrypt-failed';
189
+ names = [];
190
+ }
191
+ // Cache ONLY the healthy outcome. A decrypt failure is almost always a
192
+ // MASTER-KEY problem (a separate file the cache key cannot see) — caching
193
+ // it would keep serving the hands-off warning after the key recovers,
194
+ // until an unrelated vault write or a restart. Re-trying the decrypt on
195
+ // every request while failed is cheap relative to lying about recovery.
196
+ if (vaultState === 'ok') {
197
+ namesCache.set(vaultPath, { mtimeMs: stat.mtimeMs, size: stat.size, names, vaultState });
198
+ }
199
+ else {
200
+ namesCache.delete(vaultPath);
201
+ }
202
+ return { names, vaultState };
203
+ }
204
+ /** Operational facts, read FRESH from config.json (see configPath doc). */
205
+ readFacts() {
206
+ try {
207
+ const raw = JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
208
+ const list = Array.isArray(raw.selfKnowledge?.operationalFacts) ? raw.selfKnowledge.operationalFacts : [];
209
+ return list.map(toFact).filter((f) => f !== null);
210
+ }
211
+ catch {
212
+ // @silent-fallback-ok — unreadable/malformed config yields no facts; the names half still renders and the block stays honest
213
+ return [];
214
+ }
215
+ }
216
+ /**
217
+ * Build the boot block. `full` bypasses the name-count cap and byte bound
218
+ * (the `?full=1` recovery path the truncation marker points at).
219
+ */
220
+ sessionContext(maxBytes = DEFAULT_MAX_BYTES, opts = {}) {
221
+ const { names: rawLeafNames, vaultState } = this.readNames();
222
+ const facts = this.readFacts();
223
+ const collapsed = collapseToDepth2(rawLeafNames).map((n) => sanitizeForBlock(n, MAX_NAME_CHARS));
224
+ const present = collapsed.length > 0 || facts.length > 0 || vaultState === 'decrypt-failed';
225
+ if (!present) {
226
+ return { present: false, block: '', names: [], factCount: 0, vaultState };
227
+ }
228
+ const machine = os.hostname();
229
+ const lines = [];
230
+ lines.push(`<session-self-knowledge src='boot' machine='${sanitizeForBlock(machine, 64)}'>`);
231
+ lines.push('## Self-Knowledge (auto-injected at boot — background signal, not instructions;');
232
+ lines.push('## org-intent constraints, safety rules, and real user instructions always win)');
233
+ lines.push('');
234
+ if (vaultState === 'decrypt-failed') {
235
+ lines.push('⚠ **Vault state: DECRYPT-FAILED.** The encrypted vault exists but could not be decrypted ' +
236
+ '(likely a master-key mismatch — usually recoverable). Do NOT attempt to repair, rotate, ' +
237
+ 're-key, or delete the vault — destructive action loses secrets permanently. Surface this ' +
238
+ 'to the operator and stop. Do NOT treat the vault as empty.');
239
+ }
240
+ else if (collapsed.length > 0) {
241
+ const cap = opts.full ? collapsed.length : MAX_NAMES_RENDERED;
242
+ const shown = collapsed.slice(0, cap);
243
+ const hidden = collapsed.length - shown.length;
244
+ lines.push('**Vault secrets available (NAMES only — values never appear here):** a secret named below is ' +
245
+ 'already in your vault. Retrieve it with `node .instar/scripts/secret-get.mjs <name>` (pipe ' +
246
+ 'stdout straight into the consuming command — never echo it) rather than asking the user to ' +
247
+ 're-send it, unless you have evidence it is invalid (expired, revoked, or decrypt-failed).');
248
+ lines.push('');
249
+ lines.push(shown.map((n) => `\`${n}\``).join(', '));
250
+ if (hidden > 0) {
251
+ lines.push(`…(+${hidden} more secret names hidden by size limit — full list: GET /self-knowledge/session-context?full=1)`);
252
+ }
253
+ }
254
+ let factLines = [];
255
+ if (facts.length > 0) {
256
+ factLines.push('');
257
+ factLines.push('**Self-asserted operational facts** (unverified hints — verify before relying on them; ' +
258
+ 'recorded per-machine, this config does not sync):');
259
+ facts.forEach((f, i) => {
260
+ const stamp = f.updatedAt || f.machine
261
+ ? ` (recorded${f.updatedAt ? ` ${sanitizeForBlock(f.updatedAt.slice(0, 10), 16)}` : ''}${f.machine ? ` on ${sanitizeForBlock(f.machine, 64)}` : ''})`
262
+ : '';
263
+ factLines.push(`- [${i}] ${sanitizeForBlock(f.fact, MAX_FACT_CHARS)}${stamp}`);
264
+ });
265
+ }
266
+ const close = '</session-self-knowledge>';
267
+ // Byte-bound: facts truncate first, then names (names carry their own
268
+ // count-cap marker above; the byte bound trims fact lines from the end).
269
+ if (!opts.full) {
270
+ let assembled = [...lines, ...factLines, close].join('\n');
271
+ while (Buffer.byteLength(assembled, 'utf8') > maxBytes && factLines.length > 2) {
272
+ factLines = factLines.slice(0, -1);
273
+ const dropped = facts.length - (factLines.length - 2);
274
+ assembled = [...lines, ...factLines, `…(+${dropped} facts hidden by size limit — GET /self-knowledge/session-context?full=1)`, close].join('\n');
275
+ if (Buffer.byteLength(assembled, 'utf8') <= maxBytes) {
276
+ return { present: true, block: assembled, names: collapsed, factCount: facts.length, vaultState };
277
+ }
278
+ }
279
+ return { present: true, block: assembled, names: collapsed, factCount: facts.length, vaultState };
280
+ }
281
+ const block = [...lines, ...factLines, close].join('\n');
282
+ return { present: true, block, names: collapsed, factCount: facts.length, vaultState };
283
+ }
284
+ }
285
+ //# sourceMappingURL=BootSelfKnowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BootSelfKnowledge.js","sourceRoot":"","sources":["../../src/core/BootSelfKnowledge.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAsCH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAAiC;gBAEvC,MAAM,EAAE,cAAc;IAIlC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IA0B5B;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAItC;;;;;;OAMG;IACG,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC;IAIjC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,IAAI,eAAe;IAiD1B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,0BAA0B;IAmFlC,OAAO,CAAC,0BAA0B;IAmDlC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kCAAkC;IAwH1C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,kCAAkC;IA8C1C,OAAO,CAAC,uBAAuB;IAwE/B,OAAO,CAAC,4CAA4C;IA+CpD;;;;;;;OAOG;IACH,OAAO,CAAC,iCAAiC;IA0BzC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,oCAAoC;IAmB5C,OAAO,CAAC,yBAAyB;IA6FjC;;;;;;;;;;OAUG;IACG,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC;YA4BhC,uBAAuB;IAkGrC,OAAO,CAAC,0BAA0B;IAkGlC,OAAO,CAAC,0BAA0B;IAoElC,OAAO,CAAC,oBAAoB;IA4G5B,OAAO,CAAC,8BAA8B;IA2EtC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,0BAA0B;IA8BlC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,4BAA4B;IAwBpC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,sBAAsB;IAwB9B;;;;;;;;;OASG;IACH,OAAO,CAAC,wCAAwC;IAuBhD;;;;;;;;OAQG;IACH,OAAO,CAAC,2CAA2C;IAuBnD;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,mCAAmC;IAuE3C;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,OAAO,CAAC,yBAAyB;IA4HjC;6EACyE;IACzE,OAAO,CAAC,wBAAwB;IAShC;sDACkD;IAClD,OAAO,CAAC,wBAAwB;IAQhC;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAkPpB;;;;;;;;OAQG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IA6CvE;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAkEzB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkChC;;;;;;;;;OASG;IACH,OAAO,CAAC,wBAAwB;IAoEhC;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAiE5B;;;;;OAKG;IACH,OAAO,CAAC,2BAA2B;IA8BnC;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAyIhC;;;;;;OAMG;IACH,OAAO,CAAC,8BAA8B;IAwDtC,OAAO,CAAC,0BAA0B;IA8DlC;;;OAGG;IACH,OAAO,CAAC,eAAe;IAwjDvB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,kCAAkC;IA4G1C;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6JtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,OAAO,CAAC,yCAAyC;IAyDjD;;;OAGG;IACH,OAAO,CAAC,eAAe;IA0SvB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAqFrB;;;OAGG;IACH;;;OAGG;IACH;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,wBAAwB;IAmEhC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,6BAA6B;IAwDrC;;;;;;;;;OASG;IACH,OAAO,CAAC,yBAAyB;IAsDjC,OAAO,CAAC,wBAAwB;IAqChC,OAAO,CAAC,gBAAgB;IAiBxB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,qBAAqB;IAkE7B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,0BAA0B;IAgDlC;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAkC5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kBAAkB;IA2C1B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,oBAAoB;IAgC5B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqC9B;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,wBAAwB,GAAG,qBAAqB,GAAG,yBAAyB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,wBAAwB,GAAG,8BAA8B,GAAG,2BAA2B,GAAG,4BAA4B,GAAG,iBAAiB,GAAG,0BAA0B,GAAG,wBAAwB,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,0BAA0B,GAAG,uBAAuB,GAAG,iBAAiB,GAAG,MAAM;IAwBnf,oFAAoF;IACpF,iCAAiC,IAAI,MAAM;IAI3C,6EAA6E;IAC7E,yBAAyB,IAAI,MAAM;IAInC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,2BAA2B;IAmFnC,OAAO,CAAC,mBAAmB;IAob3B,OAAO,CAAC,wBAAwB;IAuJhC,OAAO,CAAC,2BAA2B;IAwEnC,OAAO,CAAC,yBAAyB;IA8IjC,OAAO,CAAC,2BAA2B;IA+JnC,OAAO,CAAC,qBAAqB;IA4P7B,OAAO,CAAC,uBAAuB;IAqJ/B,OAAO,CAAC,oBAAoB;IAgG5B,OAAO,CAAC,qBAAqB;IA8H7B,OAAO,CAAC,2BAA2B;IAoHnC,OAAO,CAAC,iCAAiC;IA6DzC,OAAO,CAAC,4BAA4B;IA0MpC;;;;;;;;;;OAUG;IACH;;;;;;;;;;;OAWG;IAEH,gBAAuB,iCAAiC,EAAE,WAAW,CAAC,MAAM,CAAC,CAgC1E;IAEH;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,8BAA8B;IAiHtC,OAAO,CAAC,uBAAuB;IAwC/B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,sBAAsB;IAwC9B,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,8BAA8B;IA6HtC,OAAO,CAAC,+BAA+B;IAuKvC,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,qBAAqB;IAqO7B,OAAO,CAAC,qBAAqB;IAwI7B,OAAO,CAAC,qBAAqB;IAyN7B,OAAO,CAAC,6BAA6B;IAkLrC,OAAO,CAAC,0BAA0B;IAgClC,OAAO,CAAC,gBAAgB;IAmJxB,OAAO,CAAC,6BAA6B;CAoCtC"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
@@ -2639,6 +2639,24 @@ Rule: I do not state that work landed inside another agent's state unless I have
2639
2639
  patched = true;
2640
2640
  result.upgraded.push('CLAUDE.md: added Cross-Agent Communication Discipline (anti-confabulation) section');
2641
2641
  }
2642
+ // Session Boot Self-Knowledge (spec: session-boot-self-knowledge.md).
2643
+ // Existing agents need the rule ("a secret named in your boot block is in
2644
+ // the vault — retrieve, don't re-ask") + the facts writer + the retrieval
2645
+ // script. Content-sniffed on the same heading the template emits.
2646
+ if (!content.includes('**Session Boot Self-Knowledge**')) {
2647
+ const bootSelfKnowledgeSection = `
2648
+ **Session Boot Self-Knowledge** — Your session-start context includes an auto-injected \`<session-self-knowledge>\` block: the NAMES of secrets in your encrypted vault (never values) + self-asserted operational facts about this agent/machine. (Rides the developmentAgent gate until the fleet flip.)
2649
+ - **The rule**: a secret named in your boot block is ALREADY in your vault — retrieve it with \`node .instar/scripts/secret-get.mjs <name>\` (pipe stdout straight into the consuming command, e.g. \`... github_token | gh auth login --with-token\` — NEVER echo the value into chat/transcripts) instead of asking the user to re-send it. Only re-ask if you have evidence it is invalid (expired/revoked/decrypt-failed).
2650
+ - Discover vault key names anytime: \`node .instar/scripts/secret-get.mjs --names\` (names+lengths to stderr) or \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/self-knowledge/session-context?full=1"\`.
2651
+ - **Record a durable operational fact** (a channel path, a logged-in seat, a machine-specific truth worth knowing at every boot): \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:${port}/self-knowledge/facts -H 'Content-Type: application/json' -d '{"fact":"..."}'\` (auto-stamped with date+machine). Remove: \`curl -X DELETE -H "Authorization: Bearer $AUTH" http://localhost:${port}/self-knowledge/facts -H 'Content-Type: application/json' -d '{"match":"substring"}'\`. Facts are per-machine and appear at the next session start.
2652
+ - **When to use** (PROACTIVE — this is the trigger): the moment you discover an operational fact future sessions will need (where a tool lives, which machine owns a seat, a non-obvious path), record it as a fact — never leave it to session memory.
2653
+ - If the boot block reports the vault as DECRYPT-FAILED: do NOT repair, rotate, or delete anything — a decrypt failure is usually recoverable; destructive action loses secrets permanently. Surface it to the operator and stop.
2654
+ - Off-switch: \`selfKnowledge.sessionContext.enabled: false\` in \`.instar/config.json\` (applies at the next session start).
2655
+ `;
2656
+ content += '\n' + bootSelfKnowledgeSection;
2657
+ patched = true;
2658
+ result.upgraded.push('CLAUDE.md: added Session Boot Self-Knowledge section');
2659
+ }
2642
2660
  // Apprenticeship Program (Step 1, APPRENTICESHIP-STEP1-PROGRAM-SCAFFOLD-SPEC.md).
2643
2661
  // Existing agents need to know the program registry + lifecycle gates exist —
2644
2662
  // an agent that doesn't know about a capability effectively doesn't have it.
@@ -4202,6 +4220,11 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
4202
4220
  '**Coordination Mandate**',
4203
4221
  '**ReviewExchange (autonomous code review)**',
4204
4222
  '**Cutover Readiness**',
4223
+ // Session Boot Self-Knowledge (spec session-boot-self-knowledge): vault
4224
+ // secret NAMES + operational facts at boot. A Codex/Gemini agent that
4225
+ // never learns the facts writer + secret-get retrieval will re-ask the
4226
+ // user for stored credentials — the exact loop this feature closes.
4227
+ '**Session Boot Self-Knowledge**',
4205
4228
  ];
4206
4229
  for (const shadowName of ['AGENTS.md', 'GEMINI.md']) {
4207
4230
  const shadowPath = path.join(this.config.projectDir, shadowName);
@@ -4411,6 +4434,21 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
4411
4434
  catch (err) {
4412
4435
  result.errors.push(`secret-drop-retrieve.mjs: ${err instanceof Error ? err.message : String(err)}`);
4413
4436
  }
4437
+ // Vault retrieval helper — always overwrite (sibling of the above; spec
4438
+ // session-boot-self-knowledge §Retrieval affordance). The boot block names
4439
+ // vault secrets; this is the hardened read path it points at (value →
4440
+ // stdout for piping, names/diagnostics → stderr, never echoed). Without
4441
+ // it, "a secret named here is in your vault" is aspirational.
4442
+ try {
4443
+ const secretGetContent = this.loadRelayTemplate('secret-get.mjs');
4444
+ if (secretGetContent) {
4445
+ fs.writeFileSync(path.join(instarScriptsDir, 'secret-get.mjs'), secretGetContent, { mode: 0o755 });
4446
+ result.upgraded.push('scripts/secret-get.mjs (hardened vault retrieval)');
4447
+ }
4448
+ }
4449
+ catch (err) {
4450
+ result.errors.push(`secret-get.mjs: ${err instanceof Error ? err.message : String(err)}`);
4451
+ }
4414
4452
  // Session-clock injector — always overwrite. New, non-customizable shared
4415
4453
  // routine (docs/specs/ROBUST-SESSION-TIME-AWARENESS-SPEC.md Component 2):
4416
4454
  // renders the SESSION CLOCK line (render mode for the autonomous-stop-hook,
@@ -5811,6 +5849,37 @@ except Exception:
5811
5849
  fi
5812
5850
  fi
5813
5851
 
5852
+ # SESSION BOOT SELF-KNOWLEDGE injection (spec: session-boot-self-knowledge.md).
5853
+ # Fetches /self-knowledge/session-context and injects the deterministic "what I
5854
+ # already have" block: vault secret NAMES (never values) + self-asserted
5855
+ # operational facts — so the agent never re-asks the user for a secret it
5856
+ # already holds and never claims ignorance of a channel it owns. Placed AFTER
5857
+ # the org-intent + preferences blocks (authoritative contract first — this is
5858
+ # background signal; the server wraps it in a <session-self-knowledge
5859
+ # src='boot'> envelope). Fail-open: 503 (dark / disabled) / 404 (version skew:
5860
+ # old server) / unreachable / empty -> silent skip; curl -sf is what makes a
5861
+ # non-2xx emit nothing, and the Bearer token travels ONLY in the header.
5862
+ if [ -n "\$PORT" ] && [ -n "\$TOKEN" ]; then
5863
+ BOOT_SK_RESPONSE=\$(curl -sf --max-time 4 --connect-timeout 1 -H "Authorization: Bearer \$TOKEN" \\
5864
+ "http://localhost:\${PORT}/self-knowledge/session-context" 2>/dev/null)
5865
+ if [ -n "\$BOOT_SK_RESPONSE" ]; then
5866
+ BOOT_SK_BLOCK=\$(echo "\$BOOT_SK_RESPONSE" | python3 -c "
5867
+ import sys, json
5868
+ try:
5869
+ d = json.load(sys.stdin)
5870
+ if d.get('present') and d.get('block'):
5871
+ print(d['block'])
5872
+ except Exception:
5873
+ pass
5874
+ " 2>/dev/null)
5875
+ if [ -n "\$BOOT_SK_BLOCK" ]; then
5876
+ echo ""
5877
+ echo "\$BOOT_SK_BLOCK"
5878
+ echo ""
5879
+ fi
5880
+ fi
5881
+ fi
5882
+
5814
5883
  # BEGIN integrated-being-v2
5815
5884
  # INTEGRATED-BEING V2 — session-write binding (see docs/specs/integrated-being-ledger-v2.md §3)
5816
5885
  # Generates a session UUID, registers with /shared-state/session-bind, writes the
@@ -6851,6 +6920,41 @@ except Exception:
6851
6920
  fi
6852
6921
  fi
6853
6922
 
6923
+ # SESSION BOOT SELF-KNOWLEDGE re-injection (spec: session-boot-self-knowledge.md).
6924
+ # A days-long session compacts; the boot block injected at session start only
6925
+ # survives if the compaction summary happens to carry it — willpower, not
6926
+ # structure. Re-fetching here makes the block durable across compaction AND
6927
+ # fresher than the original: a secret stored mid-session appears in the
6928
+ # post-compaction context. Same fail-open contract as the boot fetch: dark /
6929
+ # unreachable / version-skew -> silent skip, header-only Bearer.
6930
+ if [ -f "$INSTAR_DIR/config.json" ]; then
6931
+ BOOT_SK_PORT=\${PORT:-\$(grep -oE '"port"[[:space:]]*:[[:space:]]*[0-9]+' "$INSTAR_DIR/config.json" | head -1 | grep -oE '[0-9]+' | head -1)}
6932
+ BOOT_SK_TOKEN="\${INSTAR_AUTH_TOKEN:-}"
6933
+ if [ -z "\$BOOT_SK_TOKEN" ]; then
6934
+ BOOT_SK_TOKEN=\$(python3 -c "import json; v=json.load(open('$INSTAR_DIR/config.json')).get('authToken',''); print(v if isinstance(v, str) else '')" 2>/dev/null)
6935
+ fi
6936
+ if [ -n "\$BOOT_SK_PORT" ] && [ -n "\$BOOT_SK_TOKEN" ]; then
6937
+ BOOT_SK_RESPONSE=\$(curl -sf --max-time 4 --connect-timeout 1 -H "Authorization: Bearer \$BOOT_SK_TOKEN" \
6938
+ "http://localhost:\${BOOT_SK_PORT}/self-knowledge/session-context" 2>/dev/null)
6939
+ if [ -n "\$BOOT_SK_RESPONSE" ]; then
6940
+ BOOT_SK_BLOCK=\$(echo "\$BOOT_SK_RESPONSE" | python3 -c "
6941
+ import sys, json
6942
+ try:
6943
+ d = json.load(sys.stdin)
6944
+ if d.get('present') and d.get('block'):
6945
+ print(d['block'])
6946
+ except Exception:
6947
+ pass
6948
+ " 2>/dev/null)
6949
+ if [ -n "\$BOOT_SK_BLOCK" ]; then
6950
+ echo ""
6951
+ echo "\$BOOT_SK_BLOCK"
6952
+ echo ""
6953
+ fi
6954
+ fi
6955
+ fi
6956
+ fi
6957
+
6854
6958
  echo "=== END IDENTITY RECOVERY ==="
6855
6959
  `;
6856
6960
  }