instar 1.3.427 → 1.3.429
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/dashboard/subscriptions.js +5 -0
- package/dist/core/EnrollmentWizard.d.ts +11 -0
- package/dist/core/EnrollmentWizard.d.ts.map +1 -1
- package/dist/core/EnrollmentWizard.js +19 -0
- package/dist/core/EnrollmentWizard.js.map +1 -1
- package/dist/core/PendingLoginStore.d.ts +6 -0
- package/dist/core/PendingLoginStore.d.ts.map +1 -1
- package/dist/core/PendingLoginStore.js +1 -0
- package/dist/core/PendingLoginStore.js.map +1 -1
- package/dist/core/PostUpdateMigrator.js +1 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionRefresh.d.ts +1 -0
- package/dist/core/SessionRefresh.d.ts.map +1 -1
- package/dist/core/SessionRefresh.js +78 -0
- package/dist/core/SessionRefresh.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +20 -20
- package/src/templates/scripts/convergence-check.sh +1 -1
- package/upgrades/1.3.428.md +47 -0
- package/upgrades/1.3.429.md +81 -0
- package/upgrades/side-effects/claude-com-url-allowlist.md +41 -0
- package/upgrades/side-effects/enroll-two-code-warning.md +42 -0
- package/upgrades/side-effects/subscription-swap-transcript-continuity.md +55 -0
|
@@ -28,6 +28,7 @@ import type { SessionManager } from './SessionManager.js';
|
|
|
28
28
|
import type { StateManager } from './StateManager.js';
|
|
29
29
|
import type { TelegramAdapter } from '../messaging/TelegramAdapter.js';
|
|
30
30
|
import type { TopicResumeMap } from './TopicResumeMap.js';
|
|
31
|
+
export declare function ensureResumeTranscriptInConfigHome(uuid: string, targetConfigHome: string): boolean;
|
|
31
32
|
export interface SessionRefreshDeps {
|
|
32
33
|
sessionManager: SessionManager;
|
|
33
34
|
state: StateManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRefresh.d.ts","sourceRoot":"","sources":["../../src/core/SessionRefresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"SessionRefresh.d.ts","sourceRoot":"","sources":["../../src/core/SessionRefresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA2B1D,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CA8BlG;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC;;;;;;;;;;;;;;OAcG;IACH,SAAS,EAAE,CACT,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GAAG,SAAS;IAClC;8EAC0E;IAC1E,WAAW,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACtD,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,6EAA6E;IAC7E,SAAS,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IACpE;;oDAEgD;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,IAAI,EAAE,kBAAkB;IAOpC;;;;;;;;;;OAUG;IACG,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAkIlE;;;OAGG;IACH,OAAO,CAAC,cAAc;IAWtB,iEAAiE;IACjE,OAAO,CAAC,aAAa;IAOrB;;;;OAIG;IACH,OAAO,CAAC,YAAY;CAKrB"}
|
|
@@ -24,6 +24,69 @@
|
|
|
24
24
|
* non-Telegram-bound sessions (Slack, iMessage, headless) return
|
|
25
25
|
* { ok: false, code: 'not_telegram_bound' } and remain a follow-up.
|
|
26
26
|
*/
|
|
27
|
+
import fs from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
/**
|
|
30
|
+
* Account-swap conversation continuity. Claude stores conversation transcripts
|
|
31
|
+
* PER CONFIG HOME (`<CLAUDE_CONFIG_DIR>/projects/<projectDir>/<uuid>.jsonl`), so a
|
|
32
|
+
* quota swap that changes CLAUDE_CONFIG_DIR and then runs `claude --resume <uuid>`
|
|
33
|
+
* finds "No conversation found" — the transcript is still in the OLD account's
|
|
34
|
+
* config home. (The resume UUID is account-agnostic, but the transcript STORAGE
|
|
35
|
+
* is config-home-local — the gap a mocked refresh test can't see.) Before the
|
|
36
|
+
* respawn, copy the transcript into the target config home so --resume succeeds.
|
|
37
|
+
*
|
|
38
|
+
* Self-contained: finds the transcript by uuid across the user's `~/.claude*`
|
|
39
|
+
* config homes (default + enrollment-wizard slots) and copies it, preserving the
|
|
40
|
+
* `projects/<projectDir>/` relative path. Idempotent (no-op if already present),
|
|
41
|
+
* best-effort (never throws). Returns true if the transcript is in the target
|
|
42
|
+
* afterward.
|
|
43
|
+
*/
|
|
44
|
+
function transcriptRelPath(projectsDir, uuid) {
|
|
45
|
+
try {
|
|
46
|
+
for (const proj of fs.readdirSync(projectsDir)) {
|
|
47
|
+
const f = path.join(projectsDir, proj, `${uuid}.jsonl`);
|
|
48
|
+
if (fs.existsSync(f))
|
|
49
|
+
return path.join(proj, `${uuid}.jsonl`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { /* @silent-fallback-ok: missing/unreadable projects dir */ }
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
export function ensureResumeTranscriptInConfigHome(uuid, targetConfigHome) {
|
|
56
|
+
try {
|
|
57
|
+
const home = process.env.HOME || '';
|
|
58
|
+
const target = targetConfigHome.startsWith('~')
|
|
59
|
+
? path.join(home, targetConfigHome.slice(1))
|
|
60
|
+
: targetConfigHome;
|
|
61
|
+
const targetProjects = path.join(target, 'projects');
|
|
62
|
+
if (transcriptRelPath(targetProjects, uuid))
|
|
63
|
+
return true; // already there → no-op
|
|
64
|
+
let homes = [];
|
|
65
|
+
try {
|
|
66
|
+
homes = fs.readdirSync(home)
|
|
67
|
+
.filter((n) => n === '.claude' || n.startsWith('.claude-'))
|
|
68
|
+
.map((n) => path.join(home, n));
|
|
69
|
+
}
|
|
70
|
+
catch { /* @silent-fallback-ok: HOME unreadable */ }
|
|
71
|
+
for (const ch of homes) {
|
|
72
|
+
if (path.resolve(ch) === path.resolve(target))
|
|
73
|
+
continue;
|
|
74
|
+
const rel = transcriptRelPath(path.join(ch, 'projects'), uuid);
|
|
75
|
+
if (rel) {
|
|
76
|
+
const dst = path.join(targetProjects, rel);
|
|
77
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
78
|
+
fs.copyFileSync(path.join(ch, 'projects', rel), dst);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// @silent-fallback-ok: continuity-copy is best-effort; a failure means the
|
|
86
|
+
// swap may start fresh (logged by the caller), not crash the refresh.
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
27
90
|
const DEFAULT_MAX_PER_WINDOW = 5;
|
|
28
91
|
const DEFAULT_WINDOW_MS = 10 * 60 * 1000;
|
|
29
92
|
export class SessionRefresh {
|
|
@@ -144,6 +207,21 @@ export class SessionRefresh {
|
|
|
144
207
|
const accountSwap = (opts.configHome || opts.accountId)
|
|
145
208
|
? { configHome: opts.configHome, accountId: opts.accountId }
|
|
146
209
|
: undefined;
|
|
210
|
+
// Account-swap continuity: claude stores transcripts per config home, so a
|
|
211
|
+
// swap to a new CLAUDE_CONFIG_DIR must carry the conversation transcript
|
|
212
|
+
// across or `--resume` finds nothing. Skip on `fresh` (we intentionally
|
|
213
|
+
// start a new conversation then). Best-effort: a miss just means the
|
|
214
|
+
// resumed session starts fresh — logged, never fatal.
|
|
215
|
+
if (accountSwap?.configHome && !fresh) {
|
|
216
|
+
const resumeUuid = stateSession.claudeSessionId;
|
|
217
|
+
if (resumeUuid) {
|
|
218
|
+
const ok = ensureResumeTranscriptInConfigHome(resumeUuid, accountSwap.configHome);
|
|
219
|
+
console.log(`[SessionRefresh] account-swap continuity: transcript ${ok ? 'ensured in' : 'NOT found for'} ${accountSwap.configHome} (uuid=${resumeUuid}, sessionName=${sessionName})`);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
console.log(`[SessionRefresh] account-swap continuity: no claudeSessionId on session "${sessionName}" — cannot pre-copy transcript; resumed session may start fresh`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
147
225
|
const newSessionName = await this.deps.respawner(sessionName, topicId, followUpPrompt, accountSwap);
|
|
148
226
|
// ── verify + finalize ────────────────────────────────────────────
|
|
149
227
|
console.log(`[SessionRefresh] Refreshed "${sessionName}" → "${newSessionName}" (topic ${topicId})${reason ? ` reason="${reason}"` : ''}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRefresh.js","sourceRoot":"","sources":["../../src/core/SessionRefresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"SessionRefresh.js","sourceRoot":"","sources":["../../src/core/SessionRefresh.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-08T06:55:11.189Z",
|
|
5
|
+
"instarVersion": "1.3.429",
|
|
6
6
|
"entryCount": 199,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"domain": "identity",
|
|
12
12
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
13
13
|
"installedPath": ".instar/hooks/instar/session-start.sh",
|
|
14
|
-
"contentHash": "
|
|
14
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
15
15
|
"since": "2025-01-01"
|
|
16
16
|
},
|
|
17
17
|
"hook:dangerous-command-guard": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"domain": "safety",
|
|
21
21
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
22
22
|
"installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
|
|
23
|
-
"contentHash": "
|
|
23
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
24
24
|
"since": "2025-01-01"
|
|
25
25
|
},
|
|
26
26
|
"hook:grounding-before-messaging": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"domain": "safety",
|
|
30
30
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
31
31
|
"installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
|
|
32
|
-
"contentHash": "
|
|
32
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
33
33
|
"since": "2025-01-01"
|
|
34
34
|
},
|
|
35
35
|
"hook:compaction-recovery": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"domain": "identity",
|
|
39
39
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
40
40
|
"installedPath": ".instar/hooks/instar/compaction-recovery.sh",
|
|
41
|
-
"contentHash": "
|
|
41
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
42
42
|
"since": "2025-01-01"
|
|
43
43
|
},
|
|
44
44
|
"hook:external-operation-gate": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"domain": "safety",
|
|
48
48
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
49
49
|
"installedPath": ".instar/hooks/instar/external-operation-gate.js",
|
|
50
|
-
"contentHash": "
|
|
50
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
51
51
|
"since": "2025-01-01"
|
|
52
52
|
},
|
|
53
53
|
"hook:deferral-detector": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"domain": "safety",
|
|
57
57
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
58
58
|
"installedPath": ".instar/hooks/instar/deferral-detector.js",
|
|
59
|
-
"contentHash": "
|
|
59
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
60
60
|
"since": "2025-01-01"
|
|
61
61
|
},
|
|
62
62
|
"hook:self-stop-guard": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"domain": "coherence",
|
|
66
66
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
67
67
|
"installedPath": ".instar/hooks/instar/self-stop-guard.js",
|
|
68
|
-
"contentHash": "
|
|
68
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
69
69
|
"since": "2025-01-01"
|
|
70
70
|
},
|
|
71
71
|
"hook:post-action-reflection": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"domain": "evolution",
|
|
75
75
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
76
76
|
"installedPath": ".instar/hooks/instar/post-action-reflection.js",
|
|
77
|
-
"contentHash": "
|
|
77
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
78
78
|
"since": "2025-01-01"
|
|
79
79
|
},
|
|
80
80
|
"hook:external-communication-guard": {
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"domain": "safety",
|
|
84
84
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
85
85
|
"installedPath": ".instar/hooks/instar/external-communication-guard.js",
|
|
86
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
87
87
|
"since": "2025-01-01"
|
|
88
88
|
},
|
|
89
89
|
"hook:scope-coherence-collector": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"domain": "coherence",
|
|
93
93
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
94
94
|
"installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
|
|
95
|
-
"contentHash": "
|
|
95
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
96
96
|
"since": "2025-01-01"
|
|
97
97
|
},
|
|
98
98
|
"hook:scope-coherence-checkpoint": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"domain": "coherence",
|
|
102
102
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
103
103
|
"installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
|
|
104
|
-
"contentHash": "
|
|
104
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
105
105
|
"since": "2025-01-01"
|
|
106
106
|
},
|
|
107
107
|
"hook:free-text-guard": {
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"domain": "safety",
|
|
111
111
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
112
112
|
"installedPath": ".instar/hooks/instar/free-text-guard.sh",
|
|
113
|
-
"contentHash": "
|
|
113
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
114
114
|
"since": "2025-01-01"
|
|
115
115
|
},
|
|
116
116
|
"hook:claim-intercept": {
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"domain": "coherence",
|
|
120
120
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
121
121
|
"installedPath": ".instar/hooks/instar/claim-intercept.js",
|
|
122
|
-
"contentHash": "
|
|
122
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
123
123
|
"since": "2025-01-01"
|
|
124
124
|
},
|
|
125
125
|
"hook:claim-intercept-response": {
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"domain": "coherence",
|
|
129
129
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
130
130
|
"installedPath": ".instar/hooks/instar/claim-intercept-response.js",
|
|
131
|
-
"contentHash": "
|
|
131
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
132
132
|
"since": "2025-01-01"
|
|
133
133
|
},
|
|
134
134
|
"hook:stop-gate-router": {
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"domain": "safety",
|
|
138
138
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
139
139
|
"installedPath": ".instar/hooks/instar/stop-gate-router.js",
|
|
140
|
-
"contentHash": "
|
|
140
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
141
141
|
"since": "2025-01-01"
|
|
142
142
|
},
|
|
143
143
|
"hook:auto-approve-permissions": {
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"domain": "safety",
|
|
147
147
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
148
148
|
"installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
|
|
149
|
-
"contentHash": "
|
|
149
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
150
150
|
"since": "2025-01-01"
|
|
151
151
|
},
|
|
152
152
|
"job:health-check": {
|
|
@@ -1122,7 +1122,7 @@
|
|
|
1122
1122
|
"type": "template",
|
|
1123
1123
|
"domain": "operations",
|
|
1124
1124
|
"sourcePath": "src/templates/scripts/convergence-check.sh",
|
|
1125
|
-
"contentHash": "
|
|
1125
|
+
"contentHash": "4c67cf4d7dc23ac21a1b658e8acf3d3f925c1610afab9291d2cff8d48920fc33",
|
|
1126
1126
|
"since": "2025-01-01"
|
|
1127
1127
|
},
|
|
1128
1128
|
"template:emit-session-clock.sh": {
|
|
@@ -1538,7 +1538,7 @@
|
|
|
1538
1538
|
"type": "subsystem",
|
|
1539
1539
|
"domain": "updates",
|
|
1540
1540
|
"sourcePath": "src/core/PostUpdateMigrator.ts",
|
|
1541
|
-
"contentHash": "
|
|
1541
|
+
"contentHash": "58ca88e808087ef78a28a17ac93387acfa661a4e66a152197bb043218465f85f",
|
|
1542
1542
|
"since": "2025-01-01"
|
|
1543
1543
|
},
|
|
1544
1544
|
"subsystem:scheduler": {
|
|
@@ -132,7 +132,7 @@ PY
|
|
|
132
132
|
continue
|
|
133
133
|
fi
|
|
134
134
|
# Skip well-known service domains + common agent tunnel domains.
|
|
135
|
-
if echo "$url" | grep -qE '(github\.com|vercel\.app|vercel\.com|netlify\.app|netlify\.com|npmjs\.com|npmjs\.org|cloudflare\.com|google\.com|twitter\.com|x\.com|youtube\.com|reddit\.com|discord\.com|discord\.gg|telegram\.org|t\.me|localhost|127\.0\.0\.1|stackoverflow\.com|developer\.mozilla\.org|docs\.anthropic\.com|anthropic\.com|openai\.com|claude\.ai|notion\.so|linear\.app|fly\.io|render\.com|railway\.app|heroku\.com|amazonaws\.com|azure\.com|gitlab\.com|bitbucket\.org|docker\.com|hub\.docker\.com|pypi\.org|crates\.io|rubygems\.org|pkg\.go\.dev|wikipedia\.org|medium\.com|substack\.com|circle\.so|ghost\.io|telegraph\.ph)'; then
|
|
135
|
+
if echo "$url" | grep -qE '(github\.com|vercel\.app|vercel\.com|netlify\.app|netlify\.com|npmjs\.com|npmjs\.org|cloudflare\.com|google\.com|twitter\.com|x\.com|youtube\.com|reddit\.com|discord\.com|discord\.gg|telegram\.org|t\.me|localhost|127\.0\.0\.1|stackoverflow\.com|developer\.mozilla\.org|docs\.anthropic\.com|anthropic\.com|openai\.com|claude\.ai|claude\.com|notion\.so|linear\.app|fly\.io|render\.com|railway\.app|heroku\.com|amazonaws\.com|azure\.com|gitlab\.com|bitbucket\.org|docker\.com|hub\.docker\.com|pypi\.org|crates\.io|rubygems\.org|pkg\.go\.dev|wikipedia\.org|medium\.com|substack\.com|circle\.so|ghost\.io|telegraph\.ph)'; then
|
|
136
136
|
continue
|
|
137
137
|
fi
|
|
138
138
|
UNFAMILIAR_URLS="$UNFAMILIAR_URLS $url\n"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Fixes a gap in the quota-swap continuity guarantee: Claude stores conversation
|
|
9
|
+
transcripts per config home, so a swap that changed `CLAUDE_CONFIG_DIR` and then
|
|
10
|
+
ran `claude --resume <uuid>` found "no conversation" — the transcript was still in
|
|
11
|
+
the OLD account's config home, so the conversation was lost (resume → fresh start).
|
|
12
|
+
`SessionRefresh.refreshSession` now copies the transcript into the target account's
|
|
13
|
+
config home (via `ensureResumeTranscriptInConfigHome`) before the `--resume`
|
|
14
|
+
respawn. Best-effort + idempotent; only runs on an account swap; skipped on a
|
|
15
|
+
`fresh` respawn; never throws (a miss falls back to today's fresh-start behavior).
|
|
16
|
+
|
|
17
|
+
## What to Tell Your User
|
|
18
|
+
|
|
19
|
+
When I balance a session across your subscription accounts and one account hits
|
|
20
|
+
its limit, the session now moves to another account AND keeps its conversation —
|
|
21
|
+
it picks up exactly where it left off instead of starting blank. Earlier, the
|
|
22
|
+
move worked but the conversation history didn't follow it across, so a swapped
|
|
23
|
+
session would have lost its context. That gap is closed.
|
|
24
|
+
|
|
25
|
+
## Summary of New Capabilities
|
|
26
|
+
|
|
27
|
+
- **Conversation survives an account swap** — the transcript is carried into the new
|
|
28
|
+
account's config home before resume, so a swapped session continues intact instead
|
|
29
|
+
of starting fresh.
|
|
30
|
+
|
|
31
|
+
## Evidence
|
|
32
|
+
|
|
33
|
+
Caught by live testing (topic 20905) — the merged e2e passed only because it mocked
|
|
34
|
+
the refresh and never moved a real conversation between real config homes.
|
|
35
|
+
|
|
36
|
+
Reproduction (real accounts):
|
|
37
|
+
- Started a conversation under the SageMind config home (it recalled a test marker).
|
|
38
|
+
- Tried to resume that session id under the Justin config home (as a swap would):
|
|
39
|
+
**Before:** `claude --resume <uuid>` → "No conversation found with session ID …"
|
|
40
|
+
— the conversation is lost.
|
|
41
|
+
**After:** the shipped `ensureResumeTranscriptInConfigHome` copies the transcript
|
|
42
|
+
into the Justin config home, then `claude --resume <uuid>` → succeeds and correctly
|
|
43
|
+
recalls the marker (verified end-to-end with marker SWAP-FIX-VERIFY-8852).
|
|
44
|
+
|
|
45
|
+
Confirmed transcripts are config-home-local: a conversation run under
|
|
46
|
+
`~/.claude-echo-sagemind` wrote to `~/.claude-echo-sagemind/projects/…`, not the
|
|
47
|
+
default `~/.claude/projects`.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The pre-messaging convergence check's `url_provenance` allowlist now trusts
|
|
9
|
+
`claude.com` alongside the already-listed `claude.ai`, `anthropic.com`, and
|
|
10
|
+
`docs.anthropic.com`. The same domain was added to both copies that must agree:
|
|
11
|
+
the primary script (`src/templates/scripts/convergence-check.sh`) and the
|
|
12
|
+
can't-find-template fallback in `PostUpdateMigrator.getConvergenceCheckInline()`.
|
|
13
|
+
This stops the grounding-before-messaging hook from false-flagging Claude
|
|
14
|
+
subscription OAuth login links (which live on `claude.com`) as possibly-fabricated.
|
|
15
|
+
|
|
16
|
+
The enrollment wizard now attaches an operator-facing heads-up to a pending Claude
|
|
17
|
+
login, warning that a brand-new Claude account login asks for TWO codes in sequence
|
|
18
|
+
— an email-verification code first, then the sign-in code. `PendingLogin` gains an
|
|
19
|
+
optional `notice` field; `EnrollmentWizard.flowNotice(kind)` produces the warning
|
|
20
|
+
for the `url-code-paste` (Claude) flow and nothing for `device-code` (Codex); the
|
|
21
|
+
dashboard's Pending Logins panel renders it above the code. Codex enrollment is
|
|
22
|
+
unchanged.
|
|
23
|
+
|
|
24
|
+
## What to Tell Your User
|
|
25
|
+
|
|
26
|
+
When I send you a Claude sign-in link to enroll a subscription account, it now goes
|
|
27
|
+
to you directly. Before, my own link-safety check mistook the official claude.com
|
|
28
|
+
sign-in page for a possibly-made-up address and made me wrap it in a private page
|
|
29
|
+
first — that false alarm is gone.
|
|
30
|
+
|
|
31
|
+
When I set up a new Claude account for you, the login card now warns you up front
|
|
32
|
+
that Claude will ask for two codes in a row — the email-verification code first,
|
|
33
|
+
then the sign-in code. No more being surprised by the second prompt.
|
|
34
|
+
|
|
35
|
+
## Summary of New Capabilities
|
|
36
|
+
|
|
37
|
+
- **claude.com is a trusted domain** in the pre-messaging link-safety check — Claude
|
|
38
|
+
OAuth login links deliver directly instead of being flagged as unfamiliar.
|
|
39
|
+
- Existing agents get it automatically (the updater re-writes the deployed script
|
|
40
|
+
from the template on every update); no separate migration.
|
|
41
|
+
|
|
42
|
+
- **Two-code heads-up on Claude enrollment** — the pending-login card explains the
|
|
43
|
+
email-code-then-sign-in-code sequence before you start.
|
|
44
|
+
- **`PendingLogin.notice`** — an optional, sanitized, operator-facing flow heads-up
|
|
45
|
+
(extensible to other flow quirks later); Codex/device-code flows carry none.
|
|
46
|
+
- Ships with the normal instar update (server + dashboard); no migration needed.
|
|
47
|
+
|
|
48
|
+
## Evidence
|
|
49
|
+
|
|
50
|
+
Found during live subscription enrollment (topic 20905): driving a fresh Claude
|
|
51
|
+
login produces a sign-in URL on `claude.com`, and delivering it tripped the
|
|
52
|
+
`URL_PROVENANCE` gate because `claude.com` was absent from the allowlist while its
|
|
53
|
+
sibling `claude.ai` was present.
|
|
54
|
+
|
|
55
|
+
Reproduction — pipe an outbound message containing a `claude.com` link through the
|
|
56
|
+
gate:
|
|
57
|
+
- **Before:** `echo 'Sign in: https://claude.com/oauth/authorize?code=abc' | bash
|
|
58
|
+
.instar/scripts/convergence-check.sh` → exit 1, output contains `URL_PROVENANCE`
|
|
59
|
+
(so the link had to be wrapped in a private view to be sent).
|
|
60
|
+
- **After:** same input → exit 0, no `URL_PROVENANCE` flag.
|
|
61
|
+
|
|
62
|
+
A sibling test still proves a genuinely fabricated domain (`fabricated-domain.xyz`)
|
|
63
|
+
is flagged, so only this one first-party domain was loosened. Locked in by a new
|
|
64
|
+
`convergence-check.test.ts` case.
|
|
65
|
+
|
|
66
|
+
Found during live enrollment (topic 20905): enrolling a fresh Claude account, the
|
|
67
|
+
operator was asked for an email-verification code first and then a separate sign-in
|
|
68
|
+
code, with nothing explaining the second prompt — reported as confusing.
|
|
69
|
+
|
|
70
|
+
Reproduction / before-after:
|
|
71
|
+
- **Before:** starting a `url-code-paste` enrollment produced a pending login with
|
|
72
|
+
only a code + URL; the two-code sequence was undocumented, so the operator hit an
|
|
73
|
+
unexplained second code prompt.
|
|
74
|
+
- **After:** the same enrollment produces a pending login whose `notice` reads
|
|
75
|
+
"a brand-new Claude login often asks for TWO codes in order — first an
|
|
76
|
+
email-verification code … then the sign-in code …", shown on the dashboard card.
|
|
77
|
+
A `device-code` (Codex) enrollment still carries no notice.
|
|
78
|
+
|
|
79
|
+
Locked in by new `enrollment-wizard.test.ts`, `pending-login-store.test.ts`, and
|
|
80
|
+
`subscriptions-render.test.ts` cases (notice present for Claude / absent for Codex;
|
|
81
|
+
rendered when present / element omitted when not).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Side-effects review — claude.com in the URL-provenance allowlist
|
|
2
|
+
|
|
3
|
+
## Change
|
|
4
|
+
|
|
5
|
+
Adds `claude.com` to the `url_provenance` allowlist of the pre-messaging
|
|
6
|
+
convergence check, in BOTH copies that must stay in sync:
|
|
7
|
+
- `src/templates/scripts/convergence-check.sh` (the primary script, read at runtime)
|
|
8
|
+
- `src/core/PostUpdateMigrator.ts` → `getConvergenceCheckInline()` (the fallback
|
|
9
|
+
emitted only when the template file can't be found)
|
|
10
|
+
|
|
11
|
+
It sits next to the already-present `claude.ai` and `anthropic.com` entries.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
The Claude subscription OAuth login link lives on `claude.com` (Anthropic
|
|
16
|
+
consolidated the sign-in surface there; `claude.ai` is the sibling already on the
|
|
17
|
+
list). During live enrollment testing (topic 20905) the grounding-before-messaging
|
|
18
|
+
hook false-flagged the login link as `URL_PROVENANCE` (a possibly-fabricated
|
|
19
|
+
domain), which forced wrapping every OAuth link in a private view before it could
|
|
20
|
+
be sent to the operator. Allowlisting `claude.com` lets enrollment links be
|
|
21
|
+
delivered directly.
|
|
22
|
+
|
|
23
|
+
## Side effects considered
|
|
24
|
+
|
|
25
|
+
- **Weakens the provenance gate for claude.com?** Marginally and acceptably:
|
|
26
|
+
`claude.com` is Anthropic's official first-party domain (same trust class as the
|
|
27
|
+
already-listed `claude.ai`, `anthropic.com`, `docs.anthropic.com`). The allowlist
|
|
28
|
+
exists precisely to stop second-guessing well-known service domains. The gate
|
|
29
|
+
still flags every genuinely unfamiliar/fabricated domain — the regression test
|
|
30
|
+
keeps `fabricated-domain.xyz` flagged.
|
|
31
|
+
- **Drift between the two copies.** Both are edited identically in this change. The
|
|
32
|
+
template is authoritative; the inline is a can't-find-template fallback. No new
|
|
33
|
+
divergence introduced.
|
|
34
|
+
- **Migration parity.** Existing agents receive the updated allowlist because
|
|
35
|
+
`PostUpdateMigrator` re-writes `.instar/scripts/convergence-check.sh` from the
|
|
36
|
+
template on every update run (built-in script, always overwritten) — no separate
|
|
37
|
+
migration needed; the edit to the template IS the migration path.
|
|
38
|
+
- **No API, config, schema, or route surface touched.** Behavior-only change to a
|
|
39
|
+
heuristic gate. No new dependencies. Idempotent.
|
|
40
|
+
- **Blast radius:** one extra alternation in one regex, in two places. Reversible
|
|
41
|
+
by removing the `claude\.com` token.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Side-effects review — enrollment two-code heads-up
|
|
2
|
+
|
|
3
|
+
## Change
|
|
4
|
+
|
|
5
|
+
Surfaces an operator-facing heads-up on a pending login about the Claude
|
|
6
|
+
url-code-paste flow's two-code sequence (email-verification code first, then the
|
|
7
|
+
sign-in code). Three pieces:
|
|
8
|
+
- `PendingLoginStore`: new optional `notice?: string` on `PendingLogin` +
|
|
9
|
+
`IssueLoginInput`; `issue()` persists it when present (omitted otherwise).
|
|
10
|
+
- `EnrollmentWizard`: new `static flowNotice(kind)` returns the two-code warning
|
|
11
|
+
for `url-code-paste` and `undefined` for `device-code`; `start()` attaches it.
|
|
12
|
+
- `dashboard/subscriptions.js`: `renderPendingLogins` shows a `sub-pending-notice`
|
|
13
|
+
row (sanitized text) when a notice is present.
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
Live enrollment testing (topic 20905): enrolling a fresh Claude account makes
|
|
18
|
+
Anthropic ask for TWO codes in sequence — an email-verification code, then the
|
|
19
|
+
sign-in code — and the operator found the unexplained second prompt confusing. The
|
|
20
|
+
wizard now tells them what to expect up front.
|
|
21
|
+
|
|
22
|
+
## Side effects considered
|
|
23
|
+
|
|
24
|
+
- **Backward compatibility / persistence.** `notice` is optional and omitted when
|
|
25
|
+
absent, so existing pending-login JSON records (written before this change) load
|
|
26
|
+
unchanged — no migration. `issue()` only adds the key when a non-empty notice is
|
|
27
|
+
passed, matching the file's existing `...(x ? {x} : {})` style.
|
|
28
|
+
- **Not a secret.** The notice is static guidance text — never a credential, code,
|
|
29
|
+
or URL. It passes the store's `assertNoCredentialFields` (it's a fixed string set
|
|
30
|
+
by the wizard, not derived from login input).
|
|
31
|
+
- **XSS / display safety.** Rendered through the existing `sanitizeForDisplay`
|
|
32
|
+
(NFKC + control/bidi strip + grapheme cap) as inert text in a `div` — never an
|
|
33
|
+
href or innerHTML. Covered by the render tests (notice present → shown; absent →
|
|
34
|
+
element omitted) alongside the existing javascript:-URL inertness test.
|
|
35
|
+
- **device-code (Codex) flows are unchanged** — `flowNotice('device-code')` is
|
|
36
|
+
undefined, so no notice is attached and the row renders exactly as before.
|
|
37
|
+
- **Reach to existing agents.** Server code (PendingLoginStore/EnrollmentWizard)
|
|
38
|
+
and the dashboard asset ship with the instar package, so agents get this on the
|
|
39
|
+
normal package update — no `.instar/`-copied file and no PostUpdateMigrator entry
|
|
40
|
+
required.
|
|
41
|
+
- **Blast radius:** one optional field + one pure static method + one conditional
|
|
42
|
+
render row. Reversible by dropping the field.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Side-Effects Review — account-swap conversation continuity (transcript copy)
|
|
2
|
+
|
|
3
|
+
## Scope of change
|
|
4
|
+
|
|
5
|
+
- `src/core/SessionRefresh.ts` — new exported `ensureResumeTranscriptInConfigHome(uuid,
|
|
6
|
+
targetConfigHome)` + a guarded call in `refreshSession`, just before the respawner,
|
|
7
|
+
when `accountSwap.configHome` is set and not a `fresh` respawn. Copies the conversation
|
|
8
|
+
transcript into the target account's config home so `claude --resume` finds it.
|
|
9
|
+
|
|
10
|
+
## The gap (caught by live testing, not the mocked e2e)
|
|
11
|
+
|
|
12
|
+
Claude stores transcripts PER CONFIG HOME: `<CLAUDE_CONFIG_DIR>/projects/<projectDir>/
|
|
13
|
+
<uuid>.jsonl`. The P1.3 swap changes `CLAUDE_CONFIG_DIR` to the new account then runs
|
|
14
|
+
`claude --resume <uuid>` — which looks in the NEW config home and finds nothing, because
|
|
15
|
+
the transcript is still in the OLD account's config home. So the "continuity guarantee"
|
|
16
|
+
(the headline feature) would silently LOSE the conversation (resume → fresh start). The
|
|
17
|
+
P1.3 comment "the resume UUID is account-agnostic" was right about the UUID but missed
|
|
18
|
+
that transcript STORAGE is config-home-local. The merged e2e passed only because it
|
|
19
|
+
mocked the refresh — it never moved a real conversation between real config homes.
|
|
20
|
+
|
|
21
|
+
## The fix
|
|
22
|
+
|
|
23
|
+
Before the `--resume` respawn under the new config home, find the transcript by uuid
|
|
24
|
+
across the user's `~/.claude*` config homes (default + enrollment-wizard slots) and copy
|
|
25
|
+
it into the target config home, preserving the `projects/<projectDir>/` relative path.
|
|
26
|
+
Idempotent (no-op if already present), best-effort (never throws — a miss is logged and
|
|
27
|
+
the session simply starts fresh, the prior behavior).
|
|
28
|
+
|
|
29
|
+
## Authority / autonomy
|
|
30
|
+
|
|
31
|
+
No new authority. Only runs on an account swap (`accountSwap.configHome` set), which is
|
|
32
|
+
itself opt-in/dark. Touches only the per-account `projects/` transcript files (copy, never
|
|
33
|
+
delete). When no swap is requested — every existing refresh/recovery — this code does not
|
|
34
|
+
run; behaviour is byte-for-byte unchanged.
|
|
35
|
+
|
|
36
|
+
## Framework generality
|
|
37
|
+
|
|
38
|
+
Claude-code-specific by nature (the `<CLAUDE_CONFIG_DIR>/projects/.../<uuid>.jsonl` layout
|
|
39
|
+
is Claude's), matching the standard's Claude-first scope. The account-swap path is only
|
|
40
|
+
taken for claude-code sessions; other frameworks don't set `configHome`.
|
|
41
|
+
|
|
42
|
+
## Failure modes considered
|
|
43
|
+
|
|
44
|
+
- `fresh` respawn → skipped (we intentionally start a new conversation).
|
|
45
|
+
- No `claudeSessionId` on the session → logged, skipped (can't know the uuid); resumed
|
|
46
|
+
session may start fresh — same as today, not a regression.
|
|
47
|
+
- Transcript exists nowhere / unreadable → returns false, logged; respawn proceeds (fresh).
|
|
48
|
+
- Already in the target → no-op (idempotent).
|
|
49
|
+
- Config home outside `~/.claude*` → not found by the search (documented limitation; all
|
|
50
|
+
current config homes — default + wizard slots — live under HOME).
|
|
51
|
+
|
|
52
|
+
## Migration / parity
|
|
53
|
+
|
|
54
|
+
Pure additive logic on files claude already writes — no migration, no config, no stored
|
|
55
|
+
shape change. Ships via dist.
|