instar 1.3.1669 → 1.3.1671
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/commands/init.d.ts +6 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +9 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +41 -17
- package/dist/commands/server.js.map +1 -1
- package/dist/core/BackupManager.d.ts.map +1 -1
- package/dist/core/BackupManager.js +6 -0
- package/dist/core/BackupManager.js.map +1 -1
- package/dist/core/ClassReviewReplicatedStore.d.ts +13 -1
- package/dist/core/ClassReviewReplicatedStore.d.ts.map +1 -1
- package/dist/core/ClassReviewReplicatedStore.js +16 -0
- package/dist/core/ClassReviewReplicatedStore.js.map +1 -1
- package/dist/core/CodexLifecycleProductionComposition.d.ts +1 -1
- package/dist/core/CodexLifecycleProductionComposition.d.ts.map +1 -1
- package/dist/core/FileClassifier.d.ts.map +1 -1
- package/dist/core/FileClassifier.js +4 -0
- package/dist/core/FileClassifier.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +29 -7
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +127 -24
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ReplicatedPeerStreamReader.d.ts +3 -0
- package/dist/core/ReplicatedPeerStreamReader.d.ts.map +1 -1
- package/dist/core/ReplicatedPeerStreamReader.js +35 -2
- package/dist/core/ReplicatedPeerStreamReader.js.map +1 -1
- package/dist/core/SlackReplyRelayInstaller.d.ts.map +1 -1
- package/dist/core/SlackReplyRelayInstaller.js +5 -0
- package/dist/core/SlackReplyRelayInstaller.js.map +1 -1
- package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
- package/dist/core/WriteDomainRegistry.js +7 -0
- package/dist/core/WriteDomainRegistry.js.map +1 -1
- package/dist/core/linuxBrowserProvision.d.ts +93 -0
- package/dist/core/linuxBrowserProvision.d.ts.map +1 -0
- package/dist/core/linuxBrowserProvision.js +254 -0
- package/dist/core/linuxBrowserProvision.js.map +1 -0
- package/dist/core/rebalanceProof.d.ts.map +1 -1
- package/dist/core/rebalanceProof.js +3 -1
- package/dist/core/rebalanceProof.js.map +1 -1
- package/dist/data/builtinSkillContent.d.ts +7 -2
- package/dist/data/builtinSkillContent.d.ts.map +1 -1
- package/dist/data/builtinSkillContent.js +34 -12
- package/dist/data/builtinSkillContent.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/messaging/slack/SlackAdapter.d.ts +1 -0
- package/dist/messaging/slack/SlackAdapter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackAdapter.js +2 -0
- package/dist/messaging/slack/SlackAdapter.js.map +1 -1
- package/dist/messaging/slack/SlackMrkdwnFormatter.d.ts +1 -1
- package/dist/messaging/slack/SlackMrkdwnFormatter.d.ts.map +1 -1
- package/dist/messaging/slack/SlackMrkdwnFormatter.js +36 -5
- package/dist/messaging/slack/SlackMrkdwnFormatter.js.map +1 -1
- package/dist/messaging/slack/threadHistoryLabel.d.ts +1 -1
- package/dist/messaging/slack/threadHistoryLabel.d.ts.map +1 -1
- package/dist/messaging/slack/threadHistoryLabel.js +3 -1
- package/dist/messaging/slack/threadHistoryLabel.js.map +1 -1
- package/dist/messaging/telegram-origin/OriginCodexModelCanary.d.ts.map +1 -1
- package/dist/messaging/telegram-origin/OriginCodexModelCanary.js +5 -1
- package/dist/messaging/telegram-origin/OriginCodexModelCanary.js.map +1 -1
- package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
- package/dist/native/instar-desktop-host +0 -0
- package/dist/recommended/offerPrerequisites.d.ts.map +1 -1
- package/dist/recommended/offerPrerequisites.js +3 -0
- package/dist/recommended/offerPrerequisites.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +24 -1
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/SecretDrop.d.ts +19 -0
- package/dist/server/SecretDrop.d.ts.map +1 -1
- package/dist/server/SecretDrop.js +4 -0
- package/dist/server/SecretDrop.js.map +1 -1
- package/dist/server/fileRoutes.d.ts.map +1 -1
- package/dist/server/fileRoutes.js +6 -0
- package/dist/server/fileRoutes.js.map +1 -1
- package/dist/server/mobileConsolePagesRoutes.d.ts +60 -0
- package/dist/server/mobileConsolePagesRoutes.d.ts.map +1 -0
- package/dist/server/mobileConsolePagesRoutes.js +473 -0
- package/dist/server/mobileConsolePagesRoutes.js.map +1 -0
- package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
- package/dist/server/mobilePairingRoutes.js +8 -0
- package/dist/server/mobilePairingRoutes.js.map +1 -1
- package/dist/server/routes.d.ts +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +90 -14
- package/dist/server/routes.js.map +1 -1
- package/dist/testing/selfActionRegistry.d.ts.map +1 -1
- package/dist/testing/selfActionRegistry.js +31 -0
- package/dist/testing/selfActionRegistry.js.map +1 -1
- package/package.json +1 -1
- package/scripts/blocking-decision-surfaces-baseline.json +29 -9
- package/scripts/lint-blocking-decisions-declared.mjs +1 -1
- package/src/data/builtin-manifest.json +66 -66
- package/src/data/builtinSkillContent.ts +35 -12
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/data/state-coherence-registry.json +18 -0
- package/src/scaffold/templates.ts +4 -0
- package/src/templates/scripts/browser/chrome-close.sh +1 -1
- package/src/templates/scripts/browser/chrome-js.sh +1 -1
- package/src/templates/scripts/browser/chrome-launch.sh +1 -1
- package/src/templates/scripts/browser/chrome-mainworld.sh +1 -1
- package/src/templates/scripts/browser/chrome-renew.sh +1 -1
- package/src/templates/scripts/browser/chrome-unsaved.sh +1 -1
- package/src/templates/scripts/browser/ndrive.sh +1 -1
- package/src/templates/scripts/browser/x-drive.py +1594 -0
- package/src/templates/scripts/browser/xdrive-provision.sh +87 -0
- package/src/templates/scripts/browser/xdrive.sh +120 -0
- package/src/templates/scripts/secret-drop-retrieve.mjs +60 -7
- package/src/templates/scripts/slack-reply.sh +17 -1
- package/upgrades/1.3.1670.md +27 -0
- package/upgrades/1.3.1671.md +42 -0
- package/upgrades/proof-accepts-queued.eli16.md +20 -0
- package/upgrades/side-effects/codex-canary-0166.md +14 -0
- package/upgrades/side-effects/mobile-native-console-pages.md +24 -0
- package/upgrades/side-effects/normal-chrome-linux.md +84 -0
- package/upgrades/side-effects/peer-stream-read-cache.md +14 -0
- package/upgrades/side-effects/proof-accepts-queued.md +11 -0
- package/upgrades/side-effects/slack-native-reference-repair.md +74 -0
|
@@ -88,7 +88,7 @@ import { matchTestIdentity, verifyAllowTestIdentity, loadTestIdentityKey, } from
|
|
|
88
88
|
import { readRegistryHighWater, setRegistryHighWater } from './registryHighWater.js';
|
|
89
89
|
import { ITERATIVE_CONVERGING_AUDIT_SKILL_CONTENT } from '../data/builtinSkillContent.js';
|
|
90
90
|
import { SUBSCRIPTION_SIGNIN_SKILL_CONTENT } from '../data/builtinSkillContent.js';
|
|
91
|
-
import { NORMAL_CHROME_BROWSER_SKILL_CONTENT, NORMAL_CHROME_BROWSER_SKILL_WINDOWS_APPENDIX } from '../data/builtinSkillContent.js';
|
|
91
|
+
import { NORMAL_CHROME_BROWSER_LINUX_SECTION, NORMAL_CHROME_BROWSER_SKILL_CONTENT, NORMAL_CHROME_BROWSER_SKILL_WINDOWS_APPENDIX } from '../data/builtinSkillContent.js';
|
|
92
92
|
import { ensureAgentOwnedMemoryAllHomes } from './AgentOwnedMemory.js';
|
|
93
93
|
import { migrateStageBReleaseConfig, verifyBundledStageBReleaseEvidence } from './StageBActivationGate.js';
|
|
94
94
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -362,7 +362,16 @@ The Codex CLI reads ONE shared user config (\`$CODEX_HOME/config.toml\`, default
|
|
|
362
362
|
*/
|
|
363
363
|
export const NORMAL_CHROME_BROWSER_SKILL_V1_SHA256 = 'b440bad6f0d65c1c248dc9f2682183486dc118c74dd188194335ab4e0d3ecbd0';
|
|
364
364
|
/** Present only in the cross-platform skill text: the idempotency marker for migrateNormalChromeBrowserSkill. */
|
|
365
|
-
export const NORMAL_CHROME_BROWSER_SKILL_MARKER = '
|
|
365
|
+
export const NORMAL_CHROME_BROWSER_SKILL_MARKER = '### Linux (xdrive.sh, the agent display)';
|
|
366
|
+
/** The cross-platform appendix heading. An edited copy carrying it needs only its Linux subsection changed. */
|
|
367
|
+
export const NORMAL_CHROME_BROWSER_SKILL_APPENDIX_HEADING = '## Drivers by operating system';
|
|
368
|
+
/** The Linux subsection of the macOS + Windows text, before the driver existed. */
|
|
369
|
+
export const NORMAL_CHROME_BROWSER_SKILL_OLD_LINUX_HEADING = '### Linux (no Windows underneath)';
|
|
370
|
+
/**
|
|
371
|
+
* SHA-256 (LF-normalized) of the macOS + Windows SKILL.md
|
|
372
|
+
* (tests/fixtures/skills/normal-chrome-browser-v2.md pins the bytes; the unit test re-derives this).
|
|
373
|
+
*/
|
|
374
|
+
export const NORMAL_CHROME_BROWSER_SKILL_V2_SHA256 = '4577ca18462c0e7ef3f239ea8b14c55f5f3271dddd87042ecbf92ee8ad54451e';
|
|
366
375
|
/** The full heading of the retired Jev review-flag-shadow card (spec retire-staged-features-2026-10-25). */
|
|
367
376
|
export const JEV_REVIEW_FLAG_CARD_RETIRED_HEADING = '### Jev Review-Flag Shadow (log-only "does this reply need your review?" measurement)';
|
|
368
377
|
/**
|
|
@@ -462,18 +471,18 @@ Some web tasks must happen as a specific signed-in account, and account pages (s
|
|
|
462
471
|
}
|
|
463
472
|
/** The heading PR 2283 shipped (spec normal-chrome-builtin-skill); replaced in place by the heading below. */
|
|
464
473
|
export const NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V1 = '### Normal-Chrome browser (account-bound web tasks, macOS)';
|
|
465
|
-
/** The
|
|
466
|
-
export const
|
|
474
|
+
/** The macOS + Windows heading (spec normal-chrome-cross-platform); replaced in place by the heading below. */
|
|
475
|
+
export const NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2 = '### Normal-Chrome browser (account-bound web tasks, macOS + Windows)';
|
|
476
|
+
/** The current heading (spec normal-chrome-linux); the content-sniff key for migrateClaudeMd and the shadows. */
|
|
477
|
+
export const NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING = '### Normal-Chrome browser (account-bound web tasks, macOS + Windows + Linux)';
|
|
467
478
|
/**
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
* drift. Content-sniff key: NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING; a section under the v1 heading
|
|
471
|
-
* is replaced in place.
|
|
479
|
+
* The CLAUDE.md section exactly as the cross-platform release rendered it. Kept so the migration can
|
|
480
|
+
* prove the section it replaces IS the shipped text, and leave an edited one alone.
|
|
472
481
|
*/
|
|
473
|
-
export function
|
|
482
|
+
export function NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V2() {
|
|
474
483
|
return `
|
|
475
484
|
|
|
476
|
-
${
|
|
485
|
+
${NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2}
|
|
477
486
|
|
|
478
487
|
Some web tasks must happen as a specific signed-in account, and account pages (sign-in, billing, settings, usage) often refuse or behave differently for an automated browser. The \`/normal-chrome-browser\` skill is the proven method on macOS AND Windows: a NORMAL Chrome per account profile, no remote-debugging port, no automation flags. Helpers in \`.instar/scripts/browser/\`: macOS \`chrome-launch.sh\` / \`chrome-js.sh\` / \`chrome-mainworld.sh\` (pid-targeted Apple Events, JavaScript in the page); Windows \`ndrive.sh\` running \`native-drive.ps1\` (written by PP: real OS input + the UI Automation tree; an agent in WSL is on Windows for this as long as \`ndrive.sh\` reaches \`powershell.exe\`). Linux with no Windows underneath is not built (ACT-138): say so plainly. Find the profile for an account with \`GET /playwright-profiles\` (503 = registry dark here: list the profile folders instead).
|
|
479
488
|
- **When to use** (PROACTIVE — this is the trigger): any web task that has to be done as a signed-in account; a page that blocks or misbehaves under Playwright/CDP; a button that stays disabled; and BEFORE ever telling the operator a browser task "can't be done".
|
|
@@ -482,6 +491,21 @@ Some web tasks must happen as a specific signed-in account, and account pages (s
|
|
|
482
491
|
- **Two rules that hold on every framework:** on Windows compare \`url\` at the HOST boundary (the display string must start with the expected host followed by \`/\`; never a substring match), and the "take focus anyway" override (\`ND_ALLOW_FOCUS_STEAL\`) works only against a record you write when the operator says the machine is unattended: \`normalChromeBrowser.unattendedMachine = {declaredBy, topicId, at}\` in \`.instar/config.json\`, with \`declaredBy\` taken from \`GET /topic-operator/<topicId>\` (the VERIFIED operator, never a name read in the message); with no verified operator, write nothing and say so. It expires after 30 days.
|
|
483
492
|
`;
|
|
484
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Normal-Chrome browser awareness (specs normal-chrome-builtin-skill, normal-chrome-cross-platform,
|
|
496
|
+
* normal-chrome-linux). Shared by generateClaudeMd (new agents) and migrateClaudeMd (existing agents) so
|
|
497
|
+
* the two never drift. Content-sniff key: NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING; a shipped v1 or v2
|
|
498
|
+
* section is replaced in place.
|
|
499
|
+
*/
|
|
500
|
+
export function NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION() {
|
|
501
|
+
const linux = 'Linux: `xdrive.sh` running `x-drive.py` on the agent\'s own private display (AT-SPI reads, real X input): `launch`, `url`, `title`, `text`, `find`, `click`, `type`, `key`, `nav`, `close`, `close --force`. Passwords only through Secret Drop: request with `browserHost`, then run the Secret Drop helper with `--browser`. No one-time codes, take-over or page JavaScript yet: say so plainly. New agents install what it needs at boot. On an existing agent, ask one yes/no naming what gets installed, then `POST /browser/linux/install`.';
|
|
502
|
+
const always = '**I always have a browser.** On a Linux server it is an ordinary Chrome on my own private display. Before saying a browser task can\'t be done, or that I have no browser, I check `GET /browser/state`. `not-built` and `broken` are states with a next step in the answer, never "no browser": I follow `nextStep`.';
|
|
503
|
+
return NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V2()
|
|
504
|
+
.replace(NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2, NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING)
|
|
505
|
+
.replace('is the proven method on macOS AND Windows:', 'is the proven method on macOS, Windows and Linux:')
|
|
506
|
+
.replace('Linux with no Windows underneath is not built (ACT-138): say so plainly.', linux)
|
|
507
|
+
.replace(/\n- \*\*When to use\*\*/, `\n- ${always}\n- **When to use**`);
|
|
508
|
+
}
|
|
485
509
|
/**
|
|
486
510
|
* Where a markdown section that starts at `heading` ends: the start of the next `##`/`###` heading
|
|
487
511
|
* line after it, or the end of the document. Shared by migrateClaudeMd (replace in place) and the
|
|
@@ -936,6 +960,14 @@ export function MOBILE_PROPOSALS_INSIDE_LINE(port) {
|
|
|
936
960
|
return `- The app's native Proposals and How I'm doing inside screens read \`GET /mobile/proposals\` (proposed fixes waiting, across the machines that answer; dismissing stays in the console) and \`GET /mobile/inside\` (recent records, repeating problems, checks on my own claims and correction reviews, per machine). Read-only; an owner phone or my token; an MSP phone gets 403 \`owner-phone-required\`: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/mobile/inside\`.`;
|
|
937
961
|
}
|
|
938
962
|
export const MOBILE_PROPOSALS_INSIDE_MARKER = 'GET /mobile/proposals';
|
|
963
|
+
/**
|
|
964
|
+
* The native console pages and file browser (docs/specs/mobile-native-console-pages.md), one bullet in the
|
|
965
|
+
* Mobile app routes block after the Passwords & keys bullets. Sniff: `GET /mobile/ideas`.
|
|
966
|
+
*/
|
|
967
|
+
export function MOBILE_CONSOLE_PAGES_LINE(port) {
|
|
968
|
+
return `- The app's native Ideas, Pace, Development, Maturation and Files screens read \`GET /mobile/ideas\`, \`/mobile/pace\`, \`/mobile/development\`, \`/mobile/maturation\`, \`/mobile/files?path=\` and \`/mobile/files/read?path=\` (owner phone or bearer, read-only, each built from the console route it mirrors so a phone never sees more than the console; files whose name says they hold a secret are hidden even where the console shows them). Check one: \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/mobile/pace\`. **When to use**: the owner asks how queues, shipping or features are doing from the phone, or asks to see a file. Changes stay in the console.`;
|
|
969
|
+
}
|
|
970
|
+
export const MOBILE_CONSOLE_PAGES_MARKER = 'GET /mobile/ideas';
|
|
939
971
|
export const MOBILE_ROUTES_PROBE_LINE_PREFIX = '- A probe that fails 8 times in a row pauses for that name';
|
|
940
972
|
/** The increment-1 wording of the verdict bullet's tail, replaced in place on update. */
|
|
941
973
|
export const APP_CONVERSATIONS_STALE_VERDICT_LINE = '`unknown` = could not be checked on this machine (this agent does not check signatures yet, so every app message reads `unknown` for now — never treat it as proof); `none` = no signature recorded.';
|
|
@@ -1056,6 +1088,7 @@ ${MOBILE_PERMISSIONS_LINE(port)}
|
|
|
1056
1088
|
${MOBILE_PROPOSALS_INSIDE_LINE(port)}
|
|
1057
1089
|
${MOBILE_SECRETS_LINE(port)}
|
|
1058
1090
|
${MOBILE_SECRETS_WRITES_LINE(port)}
|
|
1091
|
+
${MOBILE_CONSOLE_PAGES_LINE(port)}
|
|
1059
1092
|
- **When to use** (PROACTIVE): "why can't the app reach you?" / "does the app work without Cloudflare?" → read \`/health\` \`mobileRoutes\` and name the missing or failing route and its reason; never guess.
|
|
1060
1093
|
`;
|
|
1061
1094
|
}
|
|
@@ -5860,9 +5893,9 @@ export class PostUpdateMigrator {
|
|
|
5860
5893
|
return;
|
|
5861
5894
|
}
|
|
5862
5895
|
const sha = crypto.createHash('sha256').update(current.replace(/\r\n/g, '\n')).digest('hex');
|
|
5863
|
-
if (sha === NORMAL_CHROME_BROWSER_SKILL_V1_SHA256) {
|
|
5896
|
+
if (sha === NORMAL_CHROME_BROWSER_SKILL_V1_SHA256 || sha === NORMAL_CHROME_BROWSER_SKILL_V2_SHA256) {
|
|
5864
5897
|
fs.writeFileSync(skillFile, NORMAL_CHROME_BROWSER_SKILL_CONTENT);
|
|
5865
|
-
result.upgraded.push('skills/normal-chrome-browser/SKILL.md (macOS
|
|
5898
|
+
result.upgraded.push('skills/normal-chrome-browser/SKILL.md (macOS, Windows and Linux drivers)');
|
|
5866
5899
|
return;
|
|
5867
5900
|
}
|
|
5868
5901
|
// The shipped skill is written beside the edited copy (Claude Code reads only SKILL.md, so the
|
|
@@ -5870,9 +5903,20 @@ export class PostUpdateMigrator {
|
|
|
5870
5903
|
fs.writeFileSync(path.join(path.dirname(skillFile), 'SKILL.shipped.md'), NORMAL_CHROME_BROWSER_SKILL_CONTENT);
|
|
5871
5904
|
// The appendix takes the file's own line endings (a CRLF copy stays CRLF throughout).
|
|
5872
5905
|
const crlf = current.includes('\r\n');
|
|
5906
|
+
// An edited copy that already has the appendix needs only its Linux subsection changed.
|
|
5907
|
+
if (current.includes(NORMAL_CHROME_BROWSER_SKILL_APPENDIX_HEADING)) {
|
|
5908
|
+
const lf = crlf ? current.replace(/\r\n/g, '\n') : current;
|
|
5909
|
+
const bounds = markdownSectionBounds(lf, NORMAL_CHROME_BROWSER_SKILL_OLD_LINUX_HEADING);
|
|
5910
|
+
const next = bounds
|
|
5911
|
+
? lf.slice(0, bounds.start) + NORMAL_CHROME_BROWSER_LINUX_SECTION + (lf.slice(bounds.end) ? '\n' + lf.slice(bounds.end) : '')
|
|
5912
|
+
: lf.replace(/\n*$/, '') + '\n\n' + NORMAL_CHROME_BROWSER_LINUX_SECTION;
|
|
5913
|
+
fs.writeFileSync(skillFile, crlf ? next.replace(/\n/g, '\r\n') : next);
|
|
5914
|
+
result.upgraded.push('skills/normal-chrome-browser/SKILL.md (Linux driver section added; local edits kept; shipped text in SKILL.shipped.md)');
|
|
5915
|
+
return;
|
|
5916
|
+
}
|
|
5873
5917
|
const appendix = crlf ? NORMAL_CHROME_BROWSER_SKILL_WINDOWS_APPENDIX.replace(/\n/g, '\r\n') : NORMAL_CHROME_BROWSER_SKILL_WINDOWS_APPENDIX;
|
|
5874
5918
|
fs.writeFileSync(skillFile, current.replace(/(\r?\n)*$/, '') + (crlf ? '\r\n\r\n' : '\n\n') + appendix);
|
|
5875
|
-
result.upgraded.push('skills/normal-chrome-browser/SKILL.md (appended the Windows driver
|
|
5919
|
+
result.upgraded.push('skills/normal-chrome-browser/SKILL.md (appended the Windows and Linux driver sections; local edits kept; shipped text in SKILL.shipped.md)');
|
|
5876
5920
|
// The kept text may still teach what the shipped rules forbid (the predecessor method's synthetic
|
|
5877
5921
|
// focus-event step). That is surfaced as a signal for the operator, never rewritten.
|
|
5878
5922
|
if (/FocusEvent|fire events|dispatchEvent\(new (Focus|Mouse|Pointer)Event/.test(current)) {
|
|
@@ -8334,17 +8378,33 @@ setTimeout(() => process.exit(0), 2000);
|
|
|
8334
8378
|
patched = true;
|
|
8335
8379
|
result.upgraded.push('CLAUDE.md: added Memory privacy recovery');
|
|
8336
8380
|
}
|
|
8381
|
+
// Registry First: the browser's state is a question with a place to look (normal-chrome-linux).
|
|
8382
|
+
if (!content.includes('| Can I use a browser?') && content.includes('| What can I do?')) {
|
|
8383
|
+
const row = `| Can I use a browser? / can this be done on a website? | \`curl -H "Authorization: Bearer $AUTH" http://localhost:${port}/browser/state\` |`;
|
|
8384
|
+
content = content.replace(/^(\| What can I do\?.*)$/gm, `$1\n${row}`);
|
|
8385
|
+
patched = true;
|
|
8386
|
+
result.upgraded.push('CLAUDE.md: added the browser state to Registry First');
|
|
8387
|
+
}
|
|
8337
8388
|
// Replace a shipped legacy section before any missing capability bullets
|
|
8338
8389
|
// are appended. An appended bullet at EOF would otherwise become part of
|
|
8339
8390
|
// that section and make its exact-text migration refuse the replacement.
|
|
8340
8391
|
{
|
|
8341
|
-
|
|
8342
|
-
|
|
8392
|
+
// The section actually present is the one replaced in place; a release revert can leave both,
|
|
8393
|
+
// and the second pass then removes whichever shipped copy is left beside the new section.
|
|
8394
|
+
const v2First = content.includes(NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2);
|
|
8395
|
+
const passes = [
|
|
8396
|
+
[NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V2()],
|
|
8397
|
+
[NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V1, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V1()],
|
|
8398
|
+
];
|
|
8399
|
+
for (const [oldHeading, oldSection] of v2First ? passes : passes.reverse()) {
|
|
8400
|
+
const r = replaceOrAppendMarkdownSection(content, oldHeading, NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION(), oldSection);
|
|
8401
|
+
if (r.action === 'present')
|
|
8402
|
+
continue;
|
|
8343
8403
|
content = r.content;
|
|
8344
8404
|
patched = true;
|
|
8345
|
-
result.upgraded.push(r.action === 'replaced' ? 'CLAUDE.md: replaced Normal-Chrome browser section (macOS
|
|
8346
|
-
: r.action === 'appended-old-kept' ? 'CLAUDE.md: added Normal-Chrome browser section (macOS
|
|
8347
|
-
: r.action === 'removed-stale' ? 'CLAUDE.md: removed
|
|
8405
|
+
result.upgraded.push(r.action === 'replaced' ? 'CLAUDE.md: replaced Normal-Chrome browser section (macOS, Windows and Linux)'
|
|
8406
|
+
: r.action === 'appended-old-kept' ? 'CLAUDE.md: added Normal-Chrome browser section (macOS, Windows and Linux); the edited older section was kept'
|
|
8407
|
+
: r.action === 'removed-stale' ? 'CLAUDE.md: removed a stale older Normal-Chrome browser section'
|
|
8348
8408
|
: 'CLAUDE.md: added Normal-Chrome browser section');
|
|
8349
8409
|
}
|
|
8350
8410
|
}
|
|
@@ -9485,6 +9545,23 @@ setTimeout(() => process.exit(0), 2000);
|
|
|
9485
9545
|
patched = true;
|
|
9486
9546
|
result.upgraded.push('CLAUDE.md: added the native Proposals and How I\'m doing inside line');
|
|
9487
9547
|
}
|
|
9548
|
+
// Native console pages (docs/specs/mobile-native-console-pages.md): one bullet after the Passwords & keys
|
|
9549
|
+
// bullet of an existing Mobile app routes block (a block added below already has it).
|
|
9550
|
+
if (content.includes('Mobile app routes') && !content.includes(MOBILE_CONSOLE_PAGES_MARKER)) {
|
|
9551
|
+
const lines = content.split('\n');
|
|
9552
|
+
const writes = lines.findIndex((l) => l.includes(MOBILE_SECRETS_WRITES_MARKER));
|
|
9553
|
+
const at = writes >= 0 ? writes : lines.findIndex((l) => l.includes(MOBILE_SECRETS_MARKER));
|
|
9554
|
+
if (at >= 0) {
|
|
9555
|
+
lines.splice(at + 1, 0, MOBILE_CONSOLE_PAGES_LINE(port));
|
|
9556
|
+
content = lines.join('\n');
|
|
9557
|
+
}
|
|
9558
|
+
else {
|
|
9559
|
+
// A block without that bullet: append the line rather than skip it.
|
|
9560
|
+
content = `${content.replace(/\n*$/, '\n')}${MOBILE_CONSOLE_PAGES_LINE(port)}\n`;
|
|
9561
|
+
}
|
|
9562
|
+
patched = true;
|
|
9563
|
+
result.upgraded.push('CLAUDE.md: added the native console pages line');
|
|
9564
|
+
}
|
|
9488
9565
|
// Mobile app routes (docs/specs/mobile-multi-route.md) — Agent Awareness + Migration Parity.
|
|
9489
9566
|
if (!content.includes('Mobile app routes')) {
|
|
9490
9567
|
content += MOBILE_ROUTES_CLAUDEMD_SECTION(port);
|
|
@@ -13797,6 +13874,15 @@ The user has been talking to you (possibly for days). A generic greeting like "H
|
|
|
13797
13874
|
result.upgraded.push('CLAUDE.md: added Secret Drop --run atomic use-and-consume guidance');
|
|
13798
13875
|
}
|
|
13799
13876
|
}
|
|
13877
|
+
// A browser password has one exit and is not stored (normal-chrome-linux). Same anchor as --run.
|
|
13878
|
+
if (content.includes('secret-drop-retrieve.mjs') && !content.includes('Website passwords for the Linux browser')) {
|
|
13879
|
+
const anchor = 'The hardened script exists specifically to close that leak class (origin: 2026-05-20 incident).';
|
|
13880
|
+
if (content.includes(anchor)) {
|
|
13881
|
+
content = content.replace(anchor, anchor + "\n- **Website passwords for the Linux browser**: request with `browserHost` set to the host the operator named (the person sees it on the form), then `XD_PROFILE=<id> node .instar/scripts/secret-drop-retrieve.mjs TOKEN password --browser` with the password box focused. It types straight into that site's box and you never see it; stdout, --run and --consume are refused, and the submission is not stored, so a server restart loses it.");
|
|
13882
|
+
patched = true;
|
|
13883
|
+
result.upgraded.push('CLAUDE.md: added Secret Drop browser password guidance');
|
|
13884
|
+
}
|
|
13885
|
+
}
|
|
13800
13886
|
// Secret Drop store-first durability (2026-06-04). Existing agents'
|
|
13801
13887
|
// Security bullet still claims submissions are "in-memory only (never
|
|
13802
13888
|
// written to disk)" — no longer true: submissions are persisted store-first
|
|
@@ -14458,7 +14544,7 @@ An agent created in a temporary folder (\`/tmp\`, \`/private/tmp\`, \`/var/folde
|
|
|
14458
14544
|
'### Hand-started Codex: `instar codex connect <agent>`',
|
|
14459
14545
|
// normal-chrome-builtin-skill: the helper scripts are framework-neutral
|
|
14460
14546
|
// (.instar/scripts/browser/), so a Codex/Gemini agent on macOS uses them too.
|
|
14461
|
-
'### Normal-Chrome browser (account-bound web tasks, macOS + Windows)', // == NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING (a literal so the parity guard can see it)
|
|
14547
|
+
'### Normal-Chrome browser (account-bound web tasks, macOS + Windows + Linux)', // == NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING (a literal so the parity guard can see it)
|
|
14462
14548
|
// a2a-single-agent-identity: the agent identity + coherence check are server-side and
|
|
14463
14549
|
// framework-agnostic (a Codex/Gemini agent runs on the same mesh and must explain the
|
|
14464
14550
|
// not-provisioned posture and the adopt-from-a-sibling path honestly too).
|
|
@@ -14828,13 +14914,16 @@ An agent created in a temporary folder (\`/tmp\`, \`/private/tmp\`, \`/var/folde
|
|
|
14828
14914
|
}
|
|
14829
14915
|
let appended = refreshOriginCanaryCleanupAwareness(refreshOriginCanaryStartupAwareness(shadowContent));
|
|
14830
14916
|
let mirrored = appended === shadowContent ? 0 : 1;
|
|
14831
|
-
// A shadow that still carries
|
|
14832
|
-
//
|
|
14833
|
-
//
|
|
14834
|
-
|
|
14917
|
+
// A shadow that still carries a SHIPPED older Normal-Chrome section loses it here (whether or not
|
|
14918
|
+
// the current section is already present, so a release revert cannot leave both), and the marker
|
|
14919
|
+
// loop below mirrors the current section once. An edited older section is kept.
|
|
14920
|
+
for (const [oldHeading, oldSection] of [
|
|
14921
|
+
[NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V1, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V1()],
|
|
14922
|
+
[NORMAL_CHROME_BROWSER_CLAUDEMD_HEADING_V2, NORMAL_CHROME_BROWSER_CLAUDEMD_SECTION_V2()],
|
|
14923
|
+
]) {
|
|
14835
14924
|
const crlf = appended.includes('\r\n');
|
|
14836
14925
|
const lf = crlf ? appended.replace(/\r\n/g, '\n') : appended;
|
|
14837
|
-
const stale = findExactMarkdownSection(lf,
|
|
14926
|
+
const stale = findExactMarkdownSection(lf, oldHeading, oldSection);
|
|
14838
14927
|
if (stale) {
|
|
14839
14928
|
const stripped = lf.slice(0, stale.start).replace(/\n*$/, '') + '\n' + lf.slice(stale.end).replace(/^\n*/, '\n');
|
|
14840
14929
|
appended = crlf ? stripped.replace(/\n/g, '\r\n') : stripped;
|
|
@@ -17507,6 +17596,20 @@ if [ -n "\$NOW" ]; then
|
|
|
17507
17596
|
echo "--- END CURRENT TIME ---"
|
|
17508
17597
|
fi
|
|
17509
17598
|
|
|
17599
|
+
# Browser awareness on a Linux server: every session starts knowing it has one. Read from the file
|
|
17600
|
+
# the install writes, so it works with the server down. Never says "no browser" (normal-chrome-linux).
|
|
17601
|
+
if [ "\$(uname -s)" = "Linux" ] && ! command -v powershell.exe >/dev/null 2>&1; then
|
|
17602
|
+
BROWSER_RESULT=\$(sed -n 's/.*"status":"\\([^"]*\\)".*/\\1/p' "$INSTAR_DIR/state/xdrive/provision.json" 2>/dev/null)
|
|
17603
|
+
case "\$BROWSER_RESULT" in
|
|
17604
|
+
installing) BROWSER_STATE="installing" ;;
|
|
17605
|
+
failed*) BROWSER_STATE="broken" ;;
|
|
17606
|
+
*) if [ -x /opt/google/chrome/chrome ]; then BROWSER_STATE="ready"; else BROWSER_STATE="not-built"; fi ;;
|
|
17607
|
+
esac
|
|
17608
|
+
echo ""
|
|
17609
|
+
echo "BROWSER: I have a browser on this server: ordinary Chrome on my own private display (/normal-chrome-browser, xdrive.sh). State: \$BROWSER_STATE."
|
|
17610
|
+
echo "Before saying a browser task can't be done, check GET /browser/state. not-built and broken have a nextStep there; neither means no browser."
|
|
17611
|
+
fi
|
|
17612
|
+
|
|
17510
17613
|
# TOPIC CONTEXT (loaded FIRST — highest priority context)
|
|
17511
17614
|
if [ -n "\$INSTAR_TELEGRAM_TOPIC" ]; then
|
|
17512
17615
|
TOPIC_ID="\$INSTAR_TELEGRAM_TOPIC"
|