@timurproko/a1 0.2.7-dev.754 → 0.2.7-dev.767

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 (149) hide show
  1. package/bin/guardian.js +5 -0
  2. package/bin/tab-launch-context.d.ts +23 -0
  3. package/bin/tab-launch-context.js +45 -0
  4. package/bin/ui.js +20 -5
  5. package/dist/app/session-shell/helper-pool.d.ts +3 -5
  6. package/dist/app/session-shell/helper-pool.js +3 -5
  7. package/dist/app/session-shell/session-shell-root.d.ts +29 -1
  8. package/dist/app/session-shell/session-shell-root.js +3 -2
  9. package/dist/app/session-shell/session-shell.js +153 -30
  10. package/dist/app/session-shell/session-viewport-controller.d.ts +1 -1
  11. package/dist/app/session-shell/session-viewport-controller.js +3 -3
  12. package/dist/composition/owned-ui.d.ts +20 -0
  13. package/dist/composition/owned-ui.js +76 -3
  14. package/dist/contracts/owned-ui/session-backend.d.ts +1 -0
  15. package/dist/features/owned-ui/settings-app.js +8 -35
  16. package/dist/foundation/launch-context/index.d.ts +6 -0
  17. package/dist/foundation/launch-context/index.js +15 -0
  18. package/dist/foundation/launch-guardian/main.d.ts +5 -0
  19. package/dist/foundation/launch-guardian/main.js +2 -1
  20. package/dist/foundation/release/bootstrap.d.ts +4 -0
  21. package/dist/foundation/release/bootstrap.js +44 -6
  22. package/dist/foundation/release/dependency-certification.js +54 -19
  23. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  24. package/dist/foundation/release/progress-palette.generated.js +2 -2
  25. package/dist/foundation/resident-tabs/bridge-client.d.ts +41 -0
  26. package/dist/foundation/resident-tabs/bridge-client.js +199 -0
  27. package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
  28. package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
  29. package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +30 -0
  30. package/dist/foundation/resident-tabs/ensure-terminal-host.js +121 -0
  31. package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
  32. package/dist/foundation/resident-tabs/fault-injection.js +26 -0
  33. package/dist/foundation/resident-tabs/index.d.ts +6 -0
  34. package/dist/foundation/resident-tabs/index.js +3 -0
  35. package/dist/foundation/resident-tabs/prompt-journal.d.ts +65 -0
  36. package/dist/foundation/resident-tabs/prompt-journal.js +214 -0
  37. package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
  38. package/dist/foundation/resident-tabs/protocol.js +195 -0
  39. package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
  40. package/dist/foundation/resident-tabs/recovery.js +205 -0
  41. package/dist/foundation/resident-tabs/routing.d.ts +10 -0
  42. package/dist/foundation/resident-tabs/routing.js +8 -0
  43. package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
  44. package/dist/foundation/resident-tabs/session-sync.js +37 -0
  45. package/dist/foundation/resident-tabs/settings.d.ts +9 -0
  46. package/dist/foundation/resident-tabs/settings.js +65 -0
  47. package/dist/foundation/session-writer-lock/index.d.ts +27 -0
  48. package/dist/foundation/session-writer-lock/index.js +197 -0
  49. package/dist/foundation/startup/startup-descriptor.js +2 -2
  50. package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
  51. package/dist/foundation/terminal-cleanup/index.js +1 -1
  52. package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +1 -0
  53. package/dist/foundation/terminal-cleanup/terminal-reset.js +1 -0
  54. package/dist/integrations/pi/components/owned-editor-ux.d.ts +1 -1
  55. package/dist/integrations/pi/components/owned-editor-ux.js +2 -2
  56. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
  57. package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
  58. package/dist/integrations/pi/components/shell-shared-facade.d.ts +1 -1
  59. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  60. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
  61. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  62. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  64. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  65. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  66. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  68. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  70. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  71. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  72. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  74. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  75. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  76. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  77. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  78. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
  79. package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
  80. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  81. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  82. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  83. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  84. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +0 -2
  85. package/dist/integrations/pi/components/upstream/components/tool-execution.js +41 -20
  86. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  87. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  88. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  89. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  90. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
  91. package/dist/integrations/pi/components/upstream/history/editor-core.js +5 -5
  92. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  93. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  94. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  95. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  96. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  97. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  98. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  99. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  100. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  101. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  102. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +3 -0
  103. package/dist/integrations/pi/components/upstream/theme/theme.js +24 -1
  104. package/dist/integrations/pi/engine/adapter.js +1 -0
  105. package/dist/integrations/pi/engine/pi-settings-metadata.json +2 -2
  106. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  107. package/dist/integrations/pi/engine/runtime-integration.js +102 -29
  108. package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
  109. package/dist/integrations/pi/engine/session-runtime.js +8 -3
  110. package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
  111. package/dist/integrations/pi/engine/session-selection.js +45 -9
  112. package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
  113. package/dist/integrations/pi/startup-public.js +152 -222
  114. package/dist/integrations/pi/startup-public.manifest.json +266 -177
  115. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  116. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  117. package/dist/native/darwin-arm64/manifest.json +1 -1
  118. package/dist/native/linux-x64/manifest.json +1 -1
  119. package/dist/native/win32-x64/manifest.json +2 -2
  120. package/dist/native/win32-x64/process-guardian.exe +0 -0
  121. package/dist/product-identity.d.ts +1 -1
  122. package/dist/product-identity.js +1 -1
  123. package/dist/product-identity.json +5 -0
  124. package/dist/runtime-payload-inventory.json +5349 -6035
  125. package/dist/ui/components/line-input.d.ts +1 -1
  126. package/dist/ui/components/prompt-input.d.ts +7 -5
  127. package/dist/ui/components/prompt-input.js +7 -7
  128. package/dist/ui/components/transcript-viewport.d.ts +6 -3
  129. package/dist/ui/components/transcript-viewport.js +13 -15
  130. package/dist/ui/settings/declarations.d.ts +49 -1
  131. package/dist/ui/settings/declarations.js +37 -1
  132. package/dist/ui/settings/index.d.ts +5 -3
  133. package/dist/ui/settings/index.js +3 -2
  134. package/dist/ui/settings/manager.d.ts +9 -3
  135. package/dist/ui/settings/manager.js +81 -29
  136. package/dist/ui/settings/migrations.d.ts +6 -0
  137. package/dist/ui/settings/migrations.js +32 -0
  138. package/dist/ui/settings/profile-document.d.ts +26 -0
  139. package/dist/ui/settings/profile-document.js +164 -0
  140. package/dist/ui/settings/resolution.d.ts +2 -0
  141. package/dist/ui/settings/resolution.js +13 -1
  142. package/dist/ui/settings/sections.js +4 -0
  143. package/docs/architecture/internal-naming.md +1 -1
  144. package/docs/architecture/resident-tabs-requirements.md +580 -0
  145. package/docs/architecture/resident-tabs.md +522 -0
  146. package/docs/architecture/terminal-host-proof-gate.md +2 -0
  147. package/docs/openspec-archive-automation.md +17 -16
  148. package/docs/validation.md +1 -1
  149. package/package.json +6 -4
@@ -0,0 +1,164 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import lockfile from "proper-lockfile";
5
+ const NAMESPACE_PATTERN = /^[a-z][a-z0-9-]*$/;
6
+ const MAX_RECOVERABLE_PREFIX_BYTES = 256;
7
+ /** Refuse an injected namespace already claimed by the surrounding root schema. */
8
+ export function assertProfileSettingsNamespaceAvailable(namespace, rootSettingKeys) {
9
+ assertNamespace(namespace);
10
+ if (rootSettingKeys.includes(namespace))
11
+ throw new Error(`profile settings namespace collides with a root setting: ${namespace}`);
12
+ }
13
+ /** Read one product-owned root object without exposing unrelated profile settings. */
14
+ export function readProfileSettingsNamespace(file, namespace) {
15
+ assertNamespace(namespace);
16
+ let raw;
17
+ try {
18
+ raw = readFileSync(file, "utf8");
19
+ }
20
+ catch (error) {
21
+ if (isMissing(error))
22
+ return { status: "missing", value: null };
23
+ return { status: "invalid", value: null, detail: `${file} could not be read: ${describe(error)}` };
24
+ }
25
+ const root = parseRoot(raw);
26
+ if (root === null)
27
+ return { status: "invalid", value: null, detail: `${file} is not a valid settings object` };
28
+ if (!Object.hasOwn(root, namespace))
29
+ return { status: "missing", value: null };
30
+ const value = root[namespace];
31
+ if (!isRecord(value)) {
32
+ return { status: "invalid", value: null, detail: `${file} contains a non-object ${namespace} settings namespace` };
33
+ }
34
+ return { status: "available", value: Object.freeze({ ...value }) };
35
+ }
36
+ /**
37
+ * Remove bounded leading noise only when the remaining bytes are one complete root object.
38
+ * The repair is silent and uses the same lock and atomic replacement path as namespace writes.
39
+ */
40
+ export function repairProfileSettingsDocument(file) {
41
+ if (!existsSync(file))
42
+ return false;
43
+ const release = acquireLock(file);
44
+ try {
45
+ if (!existsSync(file))
46
+ return false;
47
+ const raw = readFileSync(file, "utf8");
48
+ if (parseRoot(raw) !== null)
49
+ return false;
50
+ const root = parseRootAfterLeadingNoise(raw);
51
+ if (root === null)
52
+ return false;
53
+ replaceRoot(file, root);
54
+ return true;
55
+ }
56
+ finally {
57
+ release();
58
+ }
59
+ }
60
+ /**
61
+ * Replace one root namespace through the lock protocol used by pinned Pi.
62
+ * The updater receives bytes reread while locked, so unrelated concurrent writes survive.
63
+ */
64
+ export function updateProfileSettingsNamespace(file, namespace, update) {
65
+ assertNamespace(namespace);
66
+ mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
67
+ const release = acquireLock(file);
68
+ try {
69
+ const root = existsSync(file) ? parseRoot(readFileSync(file, "utf8")) : {};
70
+ if (root === null)
71
+ throw new Error(`${file} is not a valid settings object`);
72
+ const existing = root[namespace];
73
+ if (existing !== undefined && !isRecord(existing)) {
74
+ throw new Error(`${file} contains a non-object ${namespace} settings namespace`);
75
+ }
76
+ const nextNamespace = update(existing === undefined ? null : Object.freeze({ ...existing }));
77
+ const nextRoot = { ...root };
78
+ if (nextNamespace === null || Object.keys(nextNamespace).length === 0)
79
+ delete nextRoot[namespace];
80
+ else
81
+ nextRoot[namespace] = { ...nextNamespace };
82
+ replaceRoot(file, nextRoot);
83
+ }
84
+ finally {
85
+ release();
86
+ }
87
+ }
88
+ function acquireLock(file) {
89
+ for (let attempt = 0;; attempt += 1) {
90
+ try {
91
+ return lockfile.lockSync(file, { realpath: false });
92
+ }
93
+ catch (error) {
94
+ if (attempt >= 9 || !isLocked(error))
95
+ throw error;
96
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20);
97
+ }
98
+ }
99
+ }
100
+ function replaceRoot(file, root) {
101
+ let temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
102
+ try {
103
+ writeFileSync(temporary, `${JSON.stringify(root, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
104
+ renameSync(temporary, file);
105
+ temporary = null;
106
+ }
107
+ finally {
108
+ if (temporary !== null) {
109
+ try {
110
+ rmSync(temporary, { force: true });
111
+ }
112
+ catch {
113
+ // Invariant: failed temporary cleanup cannot make the target document authoritative.
114
+ }
115
+ }
116
+ }
117
+ }
118
+ function parseRoot(raw) {
119
+ return parseRootValue(stripBom(raw));
120
+ }
121
+ function parseRootAfterLeadingNoise(raw) {
122
+ const withoutBom = stripBom(raw);
123
+ const start = withoutBom.indexOf("{");
124
+ if (start <= 0)
125
+ return null;
126
+ const prefix = withoutBom.slice(0, start);
127
+ if (Buffer.byteLength(prefix, "utf8") > MAX_RECOVERABLE_PREFIX_BYTES || prefix.trim().length === 0)
128
+ return null;
129
+ try {
130
+ JSON.parse(prefix);
131
+ return null;
132
+ }
133
+ catch {
134
+ return parseRootValue(withoutBom.slice(start));
135
+ }
136
+ }
137
+ function parseRootValue(raw) {
138
+ try {
139
+ const value = JSON.parse(raw);
140
+ return isRecord(value) ? value : null;
141
+ }
142
+ catch {
143
+ return null;
144
+ }
145
+ }
146
+ function stripBom(raw) {
147
+ return raw.charCodeAt(0) === 0xfeff ? raw.slice(1) : raw;
148
+ }
149
+ function isRecord(value) {
150
+ return typeof value === "object" && value !== null && !Array.isArray(value);
151
+ }
152
+ function assertNamespace(namespace) {
153
+ if (!NAMESPACE_PATTERN.test(namespace))
154
+ throw new Error(`profile settings namespace is invalid: ${namespace}`);
155
+ }
156
+ function isMissing(error) {
157
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
158
+ }
159
+ function isLocked(error) {
160
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ELOCKED";
161
+ }
162
+ function describe(error) {
163
+ return error instanceof Error ? error.message : String(error);
164
+ }
@@ -42,4 +42,6 @@ export interface ResolveOwnedUiSettingsInput {
42
42
  */
43
43
  export declare function resolveOwnedUiSettings(input: ResolveOwnedUiSettingsInput): OwnedUiSettingsResolution;
44
44
  export declare function settingValue(resolution: OwnedUiSettingsResolution, id: string): OwnedUiSettingValue | null;
45
+ /** Resolve the launch-routing flag without constructing the UI settings manager. */
46
+ export declare function resolveResidentTabsSetting(document: OwnedUiSettingsDocument | null): boolean;
45
47
  export declare function documentFrom(resolution: OwnedUiSettingsResolution): OwnedUiSettingsDocument;
@@ -1,4 +1,4 @@
1
- import { OWNED_UI_SETTINGS_VERSION, findOwnedUiSettingDeclaration, } from "./declarations.js";
1
+ import { OWNED_SETTING_DECLARATIONS, OWNED_UI_SETTINGS_VERSION, findOwnedUiSettingDeclaration, } from "./declarations.js";
2
2
  import { migrationsFrom } from "./migrations.js";
3
3
  export function parseOwnedUiSettingsDocument(raw) {
4
4
  let parsed;
@@ -122,6 +122,18 @@ export function resolveOwnedUiSettings(input) {
122
122
  export function settingValue(resolution, id) {
123
123
  return resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
124
124
  }
125
+ /** Resolve the launch-routing flag without constructing the UI settings manager. */
126
+ export function resolveResidentTabsSetting(document) {
127
+ if (document === null || document.version !== OWNED_UI_SETTINGS_VERSION)
128
+ return false;
129
+ const resolution = resolveOwnedUiSettings({
130
+ declarations: [OWNED_SETTING_DECLARATIONS.residentTabs],
131
+ migrations: [],
132
+ document,
133
+ currentVersion: OWNED_UI_SETTINGS_VERSION,
134
+ });
135
+ return settingValue(resolution, "residentTabs") === true;
136
+ }
125
137
  export function documentFrom(resolution) {
126
138
  const values = { ...resolution.preserved };
127
139
  for (const setting of resolution.settings) {
@@ -2,7 +2,11 @@ export const AGENT_SECTION_ID = "agent";
2
2
  const BOOLEAN_CHOICES = Object.freeze([true, false]);
3
3
  export function buildOwnedUiSettingsSections(input) {
4
4
  const grouped = new Map();
5
+ const residentTabsEnabled = input.resolution.settings
6
+ .find(setting => setting.declaration.id === "residentTabs")?.value === true;
5
7
  for (const setting of input.resolution.settings) {
8
+ if (!residentTabsEnabled && ["tabsUnresponsiveRestartSeconds", "tabsStallNoticeSeconds"].includes(setting.declaration.id))
9
+ continue;
6
10
  const section = setting.declaration.section ?? { id: "a1", title: "A1" };
7
11
  const group = grouped.get(section.id) ?? { title: section.title, entries: [] };
8
12
  group.entries.push({
@@ -31,7 +31,7 @@ The exact externally branded key/member authority is `config/internal-naming-pol
31
31
  | `A1_PROCESS_GUARDIAN_PATH` | Explicit executable override in `src/foundation/process-containment/native-guardian-containment.ts`, also configured by CI; exact existing exposure-review entry. |
32
32
  | `A1_PROBE_TRACE` | Opt-in diagnostics read by native terminal-host code; exact existing exposure-review entry. |
33
33
  | `A1_BUILD_VERBOSE`, `A1_DEV_SHELL` | Developer invocation controls in the build helper and development launcher; exact existing exposure-review entries. |
34
- | `A1_PANE_ID`, `A1_TERMINAL_SESSION_ID` | Produced by `native/terminal-host/src/workspace.rs` and exported to launched programs; external integration names, unchanged. |
34
+ | `A1_PANE_ID`, `A1_TERMINAL_SESSION_ID` | Reserved compatibility identities retained in the product identity manifest; the resident host does not currently emit them. |
35
35
 
36
36
  Pending review preserves a possible external interface, not an obsolete private alias. Once a setting is established as private, it cannot keep its branded spelling through that category.
37
37