@timurproko/a1 0.1.8-dev.290 → 0.1.8-dev.322
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/README.md +21 -0
- package/bin/guardian.js +4 -3
- package/bin/ui.js +4 -2
- package/bin/update-recovery.js +3 -1
- package/dist/composition/owned-ui.js +13 -1
- package/dist/contracts/owned-ui/index.d.ts +1 -0
- package/dist/contracts/owned-ui/index.js +1 -0
- package/dist/contracts/owned-ui/prompt-history.d.ts +37 -0
- package/dist/contracts/owned-ui/prompt-history.js +23 -0
- package/dist/features/launch/profile-paths.d.ts +2 -0
- package/dist/features/launch/profile-paths.js +11 -0
- package/dist/features/prompt-history/index.d.ts +2 -0
- package/dist/features/prompt-history/index.js +2 -0
- package/dist/features/prompt-history/paths.d.ts +4 -0
- package/dist/features/prompt-history/paths.js +16 -0
- package/dist/features/prompt-history/service.d.ts +24 -0
- package/dist/features/prompt-history/service.js +260 -0
- package/dist/features/prompt-history/store.d.ts +15 -0
- package/dist/features/prompt-history/store.js +166 -0
- package/dist/features/prompt-history/worker.d.ts +9 -0
- package/dist/features/prompt-history/worker.js +42 -0
- package/dist/foundation/launch-context/index.d.ts +29 -0
- package/dist/foundation/launch-context/index.js +83 -0
- package/dist/foundation/launch-guardian/main.js +4 -3
- package/dist/foundation/release/bootstrap.d.ts +1 -1
- package/dist/foundation/release/bootstrap.js +18 -12
- package/dist/foundation/release/cohort-state.d.ts +1 -0
- package/dist/foundation/release/cohort-state.js +4 -0
- package/dist/foundation/release/release-gc.js +2 -2
- package/dist/foundation/release/release-store.js +10 -3
- package/dist/foundation/release/release.d.ts +3 -1
- package/dist/foundation/release/release.js +7 -3
- package/dist/foundation/release/restart-certification.d.ts +1 -0
- package/dist/foundation/release/restart-certification.js +5 -0
- package/dist/foundation/release/update-recovery.d.ts +2 -0
- package/dist/foundation/release/update-recovery.js +4 -0
- package/dist/foundation/release/update.js +5 -0
- package/dist/foundation/release/warmup.d.ts +1 -1
- package/dist/foundation/release/warmup.js +5 -4
- package/dist/foundation/startup/startup-runtime.js +13 -11
- package/dist/foundation/supervision/main.js +8 -7
- package/dist/integrations/pi/components/editor-interaction.d.ts +38 -0
- package/dist/integrations/pi/components/editor-interaction.js +1 -0
- package/dist/integrations/pi/components/history-editor-loader.d.ts +5 -0
- package/dist/integrations/pi/components/history-editor-loader.js +5 -0
- package/dist/integrations/pi/components/index.d.ts +1 -0
- package/dist/integrations/pi/components/index.js +1 -0
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -1
- package/dist/integrations/pi/components/owned-editor-ux.js +95 -22
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +12 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +9 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +35 -4
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +3 -2
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +8 -5
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +15 -2
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +12 -0
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +25 -2
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +13 -9
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +137 -133
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +280 -0
- package/dist/integrations/pi/components/upstream/history/editor-core.js +2062 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +32 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +48 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.d.ts +1 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.js +40 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.d.ts +14 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +28 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +22 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +36 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.d.ts +24 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +100 -0
- package/dist/integrations/pi/engine/adapter.d.ts +13 -1
- package/dist/integrations/pi/engine/adapter.js +86 -25
- package/dist/integrations/pi/engine/changelog.d.ts +2 -0
- package/dist/integrations/pi/engine/changelog.js +63 -0
- package/dist/integrations/pi/engine/resources/changelog.json +12 -0
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +1 -1
- package/dist/integrations/pi/engine/workflows.d.ts +1 -1
- package/dist/integrations/pi/session-ui/prompt-chips.d.ts +4 -1
- package/dist/integrations/pi/session-ui/prompt-chips.js +40 -13
- package/dist/integrations/pi/session-ui/prompt-history-controller.d.ts +30 -0
- package/dist/integrations/pi/session-ui/prompt-history-controller.js +147 -0
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +33 -0
- package/dist/integrations/pi/session-ui/session-shell-root.js +68 -74
- package/dist/integrations/pi/session-ui/session-shell.d.ts +1 -1
- package/dist/integrations/pi/session-ui/session-shell.js +98 -12
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +21 -15
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +7 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +7 -6
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/product-identity.d.ts +2 -2
- package/dist/product-identity.js +3 -36
- package/dist/product-identity.json +1 -22
- package/dist/ui/components/transcript-viewport.d.ts +8 -0
- package/dist/ui/components/transcript-viewport.js +23 -2
- package/dist/ui/components/visible-hyperlinks.d.ts +7 -0
- package/dist/ui/components/visible-hyperlinks.js +1 -0
- package/dist/ui/settings/declarations.js +19 -0
- package/dist/ui/settings/sections.js +11 -1
- package/dist/ui/settings/session.js +13 -4
- package/docs/architecture/boundaries.md +2 -0
- package/docs/architecture/history-editor-provenance.md +96 -0
- package/docs/architecture/internal-naming.md +89 -0
- package/docs/architecture/project-structure.md +1 -0
- package/docs/architecture/resource-and-data-policy.md +27 -1
- package/docs/architecture/toolchain.md +15 -1
- package/docs/features/prompt-history.md +149 -0
- package/package.json +8 -3
|
@@ -12,6 +12,12 @@ export interface PiTuiDamageFrameDescriptor {
|
|
|
12
12
|
readonly rowStart: number;
|
|
13
13
|
readonly rowEnd: number;
|
|
14
14
|
} | null;
|
|
15
|
+
/**
|
|
16
|
+
* Visible rows owned by the block that is currently streaming. A live block repaints
|
|
17
|
+
* every row it owns when it reflows, so the allowed damage follows the declared tail
|
|
18
|
+
* instead of assuming a one-row tail.
|
|
19
|
+
*/
|
|
20
|
+
readonly liveTailRows?: number;
|
|
15
21
|
readonly verticalShiftRows: number;
|
|
16
22
|
readonly safeVerticalShift: boolean;
|
|
17
23
|
readonly cause: string;
|
|
@@ -34,6 +40,7 @@ export interface DamageAwareTerminalOptions {
|
|
|
34
40
|
/** The shell supplies visible-row analysis; the terminal layer owns no UI parser. */
|
|
35
41
|
readonly inspectHyperlinks: (content: string) => {
|
|
36
42
|
readonly ranges: readonly unknown[];
|
|
43
|
+
readonly hasExplicitLink: boolean;
|
|
37
44
|
readonly signature: string;
|
|
38
45
|
readonly replaySafe: boolean;
|
|
39
46
|
readonly width: number;
|
|
@@ -204,10 +204,11 @@ export class DamageAwareTerminalAdapter {
|
|
|
204
204
|
if (descriptor.dock !== null && row.row >= descriptor.dock.rowStart && row.row <= descriptor.dock.rowEnd)
|
|
205
205
|
painted.add(row.row);
|
|
206
206
|
}
|
|
207
|
-
// Rationale:
|
|
208
|
-
//
|
|
209
|
-
//
|
|
210
|
-
|
|
207
|
+
// Rationale: a followed frame may repaint the live tail it declares, expose the shifted
|
|
208
|
+
// suffix, and restyle one sticky boundary row. A frame that declares no tail keeps the
|
|
209
|
+
// historical one-row allowance. Anything beyond that reaches settled rows and fails closed.
|
|
210
|
+
const liveTailRows = Math.max(1, descriptor.liveTailRows ?? 1);
|
|
211
|
+
if (painted.size > descriptor.verticalShiftRows + liveTailRows + 1 + countDockRows(parsed.rows, descriptor.dock)) {
|
|
211
212
|
return { ...base, reason: "excessive-real-damage" };
|
|
212
213
|
}
|
|
213
214
|
return {
|
|
@@ -252,7 +253,7 @@ export class DamageAwareTerminalAdapter {
|
|
|
252
253
|
for (const [row, state] of this.#links) {
|
|
253
254
|
if (region !== undefined && (row < region.rowStart || row > region.rowEnd))
|
|
254
255
|
continue;
|
|
255
|
-
if (state.ranges.length > 0)
|
|
256
|
+
if (state.hasExplicitLink || state.ranges.length > 0)
|
|
256
257
|
return true;
|
|
257
258
|
}
|
|
258
259
|
return false;
|
|
@@ -345,7 +346,7 @@ function hasUnsafeTerminalContent(parsed, inspect, linkRegion) {
|
|
|
345
346
|
if (linkRegion !== undefined && (row.row < linkRegion.rowStart || row.row > linkRegion.rowEnd))
|
|
346
347
|
return false;
|
|
347
348
|
const state = inspect(row.content);
|
|
348
|
-
return !state.replaySafe || state.ranges.length > 0;
|
|
349
|
+
return !state.replaySafe || state.hasExplicitLink || state.ranges.length > 0;
|
|
349
350
|
});
|
|
350
351
|
}
|
|
351
352
|
function buildDamageWrite(parsed, descriptor, paintedRows, previousRows) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "darwin",
|
|
6
6
|
"architecture": "arm64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-09-
|
|
8
|
+
"builtAt": "2026-09-12T11:45:08.507Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "9db1726bbe3fc2e8292f2ead1e7e9d0fd4d7d0dc9217b372582bf354b0f565dc",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "linux",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-09-
|
|
8
|
+
"builtAt": "2026-09-12T11:45:14.951Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "d8cda6b0c7cb36c0cc41e90802aceebf6c02eaebbc08a83d7d963d2e918dbd7a",
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
"platform": "win32",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-09-
|
|
8
|
+
"builtAt": "2026-09-12T11:45:38.237Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian.exe",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "ae2bf5d92411273a936b89376077bc13db6f73d16707a2bace8a8f048523891e",
|
|
12
12
|
"size": 177664
|
|
13
13
|
},
|
|
14
14
|
"provenance": {
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
declare const ENVIRONMENT_KEYS: readonly ["
|
|
1
|
+
declare const ENVIRONMENT_KEYS: readonly ["configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "paneId", "probeTrace", "processGuardianPath", "profileHome", "runtimeDir", "startupTrace", "terminalSessionId"];
|
|
2
2
|
declare const FILESYSTEM_KEYS: readonly ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
3
3
|
declare const STATE_KEYS: readonly ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile"];
|
|
4
4
|
declare const ENDPOINT_KEYS: readonly ["windowsPipeStem", "unixSocketFilename", "metadataFilename", "supervisorLogFilename", "databaseFilename"];
|
|
5
5
|
declare const MANIFEST_KEYS: readonly ["releaseFilename", "packageFilename"];
|
|
6
|
-
declare const PROTOCOL_KEYS: readonly ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
6
|
+
declare const PROTOCOL_KEYS: readonly ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "promptHistorySchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
7
7
|
declare const EVIDENCE_KEYS: readonly ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
8
8
|
declare const ARTIFACT_KEYS: readonly ["cliEntry", "supervisorEntry", "guardianEntry", "uiEntry", "nativeExecutable", "nativeCrate", "processGuardianExecutable", "releaseTarballStem", "diagnosticStem"];
|
|
9
9
|
type StringRecord<Keys extends readonly string[]> = {
|
package/dist/product-identity.js
CHANGED
|
@@ -1,46 +1,13 @@
|
|
|
1
1
|
import rawIdentity from "./product-identity.json" with { type: "json" };
|
|
2
2
|
const ENVIRONMENT_KEYS = [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"dataDir",
|
|
6
|
-
"databasePath",
|
|
7
|
-
"developmentInstanceId",
|
|
8
|
-
"developmentRoot",
|
|
9
|
-
"endpoint",
|
|
10
|
-
"fixture",
|
|
11
|
-
"fixtureInput",
|
|
12
|
-
"fixtureToken",
|
|
13
|
-
"inputAcknowledgement",
|
|
14
|
-
"immutableWarmup",
|
|
15
|
-
"internalPackaging",
|
|
16
|
-
"launchProfile",
|
|
17
|
-
"nativePi",
|
|
18
|
-
"paneId",
|
|
19
|
-
"piParityIntentionalMutation",
|
|
20
|
-
"piPortRoot",
|
|
21
|
-
"piSourceLedgerPath",
|
|
22
|
-
"piSourceScanRoot",
|
|
23
|
-
"probeTrace",
|
|
24
|
-
"processGuardianPath",
|
|
25
|
-
"profileHome",
|
|
26
|
-
"protocolVersion",
|
|
27
|
-
"releaseDigest",
|
|
28
|
-
"releaseId",
|
|
29
|
-
"releaseLayers",
|
|
30
|
-
"releaseRoot",
|
|
31
|
-
"releaseRunnerLabel",
|
|
32
|
-
"runtimeDir",
|
|
33
|
-
"structuredFlowLimits",
|
|
34
|
-
"startupTrace",
|
|
35
|
-
"terminalArgumentsJson",
|
|
36
|
-
"terminalExecutable",
|
|
37
|
-
"terminalSessionId",
|
|
3
|
+
"configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint",
|
|
4
|
+
"paneId", "probeTrace", "processGuardianPath", "profileHome", "runtimeDir", "startupTrace", "terminalSessionId",
|
|
38
5
|
];
|
|
39
6
|
const FILESYSTEM_KEYS = ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
40
7
|
const STATE_KEYS = ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile"];
|
|
41
8
|
const ENDPOINT_KEYS = ["windowsPipeStem", "unixSocketFilename", "metadataFilename", "supervisorLogFilename", "databaseFilename"];
|
|
42
9
|
const MANIFEST_KEYS = ["releaseFilename", "packageFilename"];
|
|
43
|
-
const PROTOCOL_KEYS = ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
10
|
+
const PROTOCOL_KEYS = ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "promptHistorySchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
44
11
|
const EVIDENCE_KEYS = ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
45
12
|
const ARTIFACT_KEYS = ["cliEntry", "supervisorEntry", "guardianEntry", "uiEntry", "nativeExecutable", "nativeCrate", "processGuardianExecutable", "releaseTarballStem", "diagnosticStem"];
|
|
46
13
|
const ROOT_KEYS = ["schema", "displayName", "commandName", "packageName", "filesystem", "environment", "state", "endpoint", "manifest", "protocol", "evidence", "artifacts"];
|
|
@@ -10,40 +10,18 @@
|
|
|
10
10
|
"temporaryPrefix": "a1-"
|
|
11
11
|
},
|
|
12
12
|
"environment": {
|
|
13
|
-
"certificationTarball": "A1_CERTIFICATION_TARBALL",
|
|
14
13
|
"configDir": "A1_CONFIG_DIR",
|
|
15
14
|
"dataDir": "A1_DATA_DIR",
|
|
16
15
|
"databasePath": "A1_DATABASE_PATH",
|
|
17
16
|
"developmentInstanceId": "A1_DEV_INSTANCE_ID",
|
|
18
17
|
"developmentRoot": "A1_DEV_ROOT",
|
|
19
18
|
"endpoint": "A1_ENDPOINT",
|
|
20
|
-
"fixture": "A1_FIXTURE",
|
|
21
|
-
"fixtureInput": "A1_FIXTURE_INPUT",
|
|
22
|
-
"fixtureToken": "A1_FIXTURE_TOKEN",
|
|
23
|
-
"inputAcknowledgement": "A1_INPUT_ACK",
|
|
24
|
-
"immutableWarmup": "A1_IMMUTABLE_WARMUP",
|
|
25
|
-
"internalPackaging": "A1_INTERNAL_PACKAGING",
|
|
26
|
-
"launchProfile": "A1_LAUNCH_PROFILE",
|
|
27
|
-
"nativePi": "A1_NATIVE_PI",
|
|
28
19
|
"paneId": "A1_PANE_ID",
|
|
29
|
-
"piParityIntentionalMutation": "A1_PI_PARITY_INTENTIONAL_MUTATION",
|
|
30
|
-
"piPortRoot": "A1_PI_PORT_ROOT",
|
|
31
|
-
"piSourceLedgerPath": "A1_PI_SOURCE_LEDGER_PATH",
|
|
32
|
-
"piSourceScanRoot": "A1_PI_SOURCE_SCAN_ROOT",
|
|
33
20
|
"probeTrace": "A1_PROBE_TRACE",
|
|
34
21
|
"processGuardianPath": "A1_PROCESS_GUARDIAN_PATH",
|
|
35
22
|
"profileHome": "A1_PROFILE_HOME",
|
|
36
|
-
"protocolVersion": "A1_PROTOCOL_VERSION",
|
|
37
|
-
"releaseDigest": "A1_RELEASE_DIGEST",
|
|
38
|
-
"releaseId": "A1_RELEASE_ID",
|
|
39
|
-
"releaseLayers": "A1_RELEASE_LAYERS",
|
|
40
|
-
"releaseRoot": "A1_RELEASE_ROOT",
|
|
41
|
-
"releaseRunnerLabel": "A1_RELEASE_RUNNER_LABEL",
|
|
42
23
|
"runtimeDir": "A1_RUNTIME_DIR",
|
|
43
|
-
"structuredFlowLimits": "A1_STRUCTURED_FLOW_LIMITS",
|
|
44
24
|
"startupTrace": "A1_STARTUP_TRACE",
|
|
45
|
-
"terminalArgumentsJson": "A1_TERMINAL_ARGUMENTS_JSON",
|
|
46
|
-
"terminalExecutable": "A1_TERMINAL_EXECUTABLE",
|
|
47
25
|
"terminalSessionId": "A1_TERMINAL_SESSION_ID"
|
|
48
26
|
},
|
|
49
27
|
"state": {
|
|
@@ -71,6 +49,7 @@
|
|
|
71
49
|
"nativeHostSchema": "a1-native-host-v1",
|
|
72
50
|
"structuredAgentSchema": "a1-structured-agent-v1",
|
|
73
51
|
"controlStoreSchema": "a1-control-store-v1",
|
|
52
|
+
"promptHistorySchema": "a1-prompt-history-v1",
|
|
74
53
|
"releaseCohortSchema": "a1-release-cohort-v1",
|
|
75
54
|
"updateJournalSchema": "a1-update-journal-v1"
|
|
76
55
|
},
|
|
@@ -24,6 +24,12 @@ export interface TranscriptViewportFrameInput {
|
|
|
24
24
|
readonly paintDocumentRow?: (row: string) => string;
|
|
25
25
|
/** Leading document rows that participate in pointer selection and copying. */
|
|
26
26
|
readonly selectableDocumentRowCount?: number;
|
|
27
|
+
/**
|
|
28
|
+
* First document row owned by the block that is currently streaming, if any. Rows from
|
|
29
|
+
* here to the end of the selectable document reflow together whenever that block
|
|
30
|
+
* re-renders, so the frame can declare how much damage is legitimately its own.
|
|
31
|
+
*/
|
|
32
|
+
readonly liveTailStartRow?: number;
|
|
27
33
|
/** Final transient rows to bottom-align with unused viewport space while content fits. */
|
|
28
34
|
readonly bottomAlignedTailRowCount?: number;
|
|
29
35
|
readonly dockRows: readonly string[];
|
|
@@ -94,6 +100,8 @@ export interface TranscriptViewportFrameDescriptor {
|
|
|
94
100
|
readonly transientAlignmentGapRows: number;
|
|
95
101
|
/** Live status rows at the end of the transient suffix. */
|
|
96
102
|
readonly bottomAlignedTailRowCount: number;
|
|
103
|
+
/** Visible rows owned by the currently streaming transcript block. */
|
|
104
|
+
readonly liveTailRows: number;
|
|
97
105
|
readonly verticalShiftRows: number;
|
|
98
106
|
readonly safeVerticalShift: boolean;
|
|
99
107
|
/** Monotonic interaction revision used to reject stale selection evidence. */
|
|
@@ -358,9 +358,9 @@ export class TranscriptViewport {
|
|
|
358
358
|
const frameRows = [...visible, ...dock].slice(0, height);
|
|
359
359
|
let bottomHit = null;
|
|
360
360
|
if (this.#maxScroll > 0 && !this.#followingEnd && frameRows.length > 0) {
|
|
361
|
-
const genericLabel = " Jump to bottom (End) ";
|
|
361
|
+
const genericLabel = " Jump to bottom (Ctrl+End) ↓ ";
|
|
362
362
|
const countedLabel = this.#newMessages > 0
|
|
363
|
-
? ` ${this.#newMessages} new message${this.#newMessages === 1 ? "" : "s"} (End) `
|
|
363
|
+
? ` ${this.#newMessages} new message${this.#newMessages === 1 ? "" : "s"} (Ctrl+End) ↓ `
|
|
364
364
|
: genericLabel;
|
|
365
365
|
const label = displayWidth(countedLabel) <= contentWidth ? countedLabel : genericLabel;
|
|
366
366
|
const labelWidth = displayWidth(label);
|
|
@@ -406,6 +406,7 @@ export class TranscriptViewport {
|
|
|
406
406
|
transientRowCount: Math.max(0, documentRows.length - this.#selectableDocumentRowCount),
|
|
407
407
|
transientAlignmentGapRows,
|
|
408
408
|
bottomAlignedTailRowCount,
|
|
409
|
+
liveTailRows: visibleLiveTailRows(input.liveTailStartRow, this.#selectableDocumentRowCount, this.#scrollTop, viewportHeight),
|
|
409
410
|
verticalShiftRows,
|
|
410
411
|
safeVerticalShift,
|
|
411
412
|
selectionRevision: composingSelectionRevision,
|
|
@@ -480,6 +481,7 @@ export class TranscriptViewport {
|
|
|
480
481
|
transientRowCount: previous.descriptor.transientRowCount,
|
|
481
482
|
transientAlignmentGapRows: previous.descriptor.transientAlignmentGapRows,
|
|
482
483
|
bottomAlignedTailRowCount: previous.descriptor.bottomAlignedTailRowCount,
|
|
484
|
+
liveTailRows: previous.descriptor.liveTailRows,
|
|
483
485
|
verticalShiftRows: 0,
|
|
484
486
|
safeVerticalShift: false,
|
|
485
487
|
selectionRevision: this.#selectionRevision,
|
|
@@ -568,6 +570,18 @@ function trimCache(cache, limit) {
|
|
|
568
570
|
while (cache.size > limit)
|
|
569
571
|
cache.delete(cache.keys().next().value);
|
|
570
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Rows of the streaming block that the visible window actually shows. Gap insertion happens
|
|
575
|
+
* after the selectable document, so live-block indices need no adjustment here.
|
|
576
|
+
*/
|
|
577
|
+
function visibleLiveTailRows(liveTailStartRow, selectableDocumentRowCount, scrollTop, viewportHeight) {
|
|
578
|
+
if (liveTailStartRow === undefined || !Number.isSafeInteger(liveTailStartRow))
|
|
579
|
+
return 0;
|
|
580
|
+
const start = clamp(liveTailStartRow, 0, selectableDocumentRowCount);
|
|
581
|
+
const visibleStart = Math.max(start, scrollTop);
|
|
582
|
+
const visibleEnd = Math.min(selectableDocumentRowCount, scrollTop + viewportHeight);
|
|
583
|
+
return Math.max(0, visibleEnd - visibleStart);
|
|
584
|
+
}
|
|
571
585
|
function governingPrompt(anchors, scrollTop) {
|
|
572
586
|
let result = null;
|
|
573
587
|
for (const anchor of anchors) {
|
|
@@ -611,6 +625,13 @@ export function assertTranscriptViewportFrameDescriptor(descriptor) {
|
|
|
611
625
|
|| descriptor.transientAlignmentGapRows + descriptor.bottomAlignedTailRowCount > descriptor.transientRowCount) {
|
|
612
626
|
throw new TypeError("viewport frame descriptor transient geometry is invalid");
|
|
613
627
|
}
|
|
628
|
+
const transcriptHeight = descriptor.transcript === null
|
|
629
|
+
? 0
|
|
630
|
+
: descriptor.transcript.rowEnd - descriptor.transcript.rowStart + 1;
|
|
631
|
+
if (!Number.isSafeInteger(descriptor.liveTailRows) || descriptor.liveTailRows < 0
|
|
632
|
+
|| descriptor.liveTailRows > transcriptHeight) {
|
|
633
|
+
throw new TypeError("viewport frame descriptor live tail is invalid");
|
|
634
|
+
}
|
|
614
635
|
if (!Number.isSafeInteger(descriptor.verticalShiftRows))
|
|
615
636
|
throw new TypeError("viewport frame descriptor shift is invalid");
|
|
616
637
|
if (descriptor.previousDocumentRange === null && descriptor.verticalShiftRows !== 0) {
|
|
@@ -6,6 +6,13 @@ export interface VisibleHyperlinkRange {
|
|
|
6
6
|
}
|
|
7
7
|
export interface VisibleHyperlinkRow {
|
|
8
8
|
readonly ranges: readonly VisibleHyperlinkRange[];
|
|
9
|
+
/**
|
|
10
|
+
* Whether the row declares a terminal hyperlink of its own. Only a declared link gives the
|
|
11
|
+
* terminal per-cell link identity that moving the row can misattribute, so movement safety
|
|
12
|
+
* asks this rather than counting ranges: a candidate range is host-hover text such as
|
|
13
|
+
* `obj.method` or `./src/index.ts`, which ordinary code produces on nearly every row.
|
|
14
|
+
*/
|
|
15
|
+
readonly hasExplicitLink: boolean;
|
|
9
16
|
/** False for unclosed links, malformed escapes, images, or row-moving controls. */
|
|
10
17
|
readonly replaySafe: boolean;
|
|
11
18
|
readonly width: number;
|
|
@@ -55,6 +55,7 @@ export function readVisibleHyperlinks(line, widthOf = displayWidth) {
|
|
|
55
55
|
ranges.sort((left, right) => left.from - right.from);
|
|
56
56
|
return {
|
|
57
57
|
ranges,
|
|
58
|
+
hasExplicitLink: ranges.some(range => range.kind === "explicit"),
|
|
58
59
|
replaySafe,
|
|
59
60
|
width: column,
|
|
60
61
|
// Rationale: a path with spaces or a wrapped host match may extend beyond
|
|
@@ -30,9 +30,28 @@ export const OWNED_UI_SETTING_DECLARATIONS = Object.freeze([
|
|
|
30
30
|
defaultValue: "normal",
|
|
31
31
|
allowedValues: Object.freeze(["normal", "fast", "high"]),
|
|
32
32
|
}),
|
|
33
|
+
Object.freeze({
|
|
34
|
+
id: "promptHistoryEnabled",
|
|
35
|
+
label: "Persistent history",
|
|
36
|
+
section: Object.freeze({ id: "history", title: "History" }),
|
|
37
|
+
description: "Retain reusable prompts across sessions. Applies on next start; disabling does not erase saved history or stop existing instances.",
|
|
38
|
+
application: "restart",
|
|
39
|
+
defaultValue: true,
|
|
40
|
+
allowedValues: Object.freeze([true, false]),
|
|
41
|
+
}),
|
|
42
|
+
Object.freeze({
|
|
43
|
+
id: "promptHistoryMaxItems",
|
|
44
|
+
label: "History limit",
|
|
45
|
+
section: Object.freeze({ id: "history", title: "History" }),
|
|
46
|
+
description: "Maximum recent unique prompts after next start. Byte limits also apply; increasing the limit cannot restore pruned entries.",
|
|
47
|
+
application: "restart",
|
|
48
|
+
defaultValue: 100,
|
|
49
|
+
allowedValues: Object.freeze([10, 20, 30, 40, 50, 60, 70, 80, 90, 100]),
|
|
50
|
+
}),
|
|
33
51
|
Object.freeze({
|
|
34
52
|
id: "promptSuggestions",
|
|
35
53
|
label: "Prompt suggestions",
|
|
54
|
+
section: Object.freeze({ id: "agent", title: "Agent" }),
|
|
36
55
|
description: "Predict likely next prompts with one additional background request using the selected model.",
|
|
37
56
|
application: "live",
|
|
38
57
|
defaultValue: true,
|
|
@@ -25,6 +25,8 @@ export function buildOwnedUiSettingsSections(input) {
|
|
|
25
25
|
});
|
|
26
26
|
grouped.set(section.id, group);
|
|
27
27
|
}
|
|
28
|
+
const ownedAgentEntries = grouped.get(AGENT_SECTION_ID)?.entries ?? [];
|
|
29
|
+
grouped.delete(AGENT_SECTION_ID);
|
|
28
30
|
const ownedSections = [...grouped].map(([id, group]) => ({
|
|
29
31
|
id,
|
|
30
32
|
title: group.title,
|
|
@@ -32,7 +34,15 @@ export function buildOwnedUiSettingsSections(input) {
|
|
|
32
34
|
unavailableReason: null,
|
|
33
35
|
readOnlyReason: null,
|
|
34
36
|
}));
|
|
35
|
-
|
|
37
|
+
const agent = agentSection(input.agent);
|
|
38
|
+
// Invariant: presentation grouping does not transfer ownership or engine availability to owned entries.
|
|
39
|
+
const combinedAgent = ownedAgentEntries.length === 0 ? agent : {
|
|
40
|
+
...agent,
|
|
41
|
+
entries: Object.freeze([...agent.entries, ...ownedAgentEntries]),
|
|
42
|
+
unavailableReason: null,
|
|
43
|
+
readOnlyReason: null,
|
|
44
|
+
};
|
|
45
|
+
return Object.freeze([...ownedSections, combinedAgent]);
|
|
36
46
|
}
|
|
37
47
|
export function findOwnedUiSettingsEntry(sections, id, backend) {
|
|
38
48
|
for (const section of sections) {
|
|
@@ -10,12 +10,17 @@ export class OwnedUiSettingsSession {
|
|
|
10
10
|
#resolution;
|
|
11
11
|
#agentSnapshot = null;
|
|
12
12
|
#pending = new Map();
|
|
13
|
+
#restartEffective = new Map();
|
|
13
14
|
constructor(options) {
|
|
14
15
|
this.#store = options.store;
|
|
15
16
|
this.#agent = options.agent ?? null;
|
|
16
17
|
this.#agentProvider = options.agentProvider ?? null;
|
|
17
18
|
this.#hiddenAgentSettingIds = new Set(options.hiddenAgentSettingIds ?? []);
|
|
18
19
|
this.#resolution = options.store.read();
|
|
20
|
+
for (const setting of this.#resolution.settings) {
|
|
21
|
+
if (setting.declaration.application === "restart")
|
|
22
|
+
this.#restartEffective.set(setting.declaration.id, setting.value);
|
|
23
|
+
}
|
|
19
24
|
}
|
|
20
25
|
get resolution() {
|
|
21
26
|
return this.#resolution;
|
|
@@ -27,10 +32,15 @@ export class OwnedUiSettingsSession {
|
|
|
27
32
|
this.#notify();
|
|
28
33
|
}
|
|
29
34
|
sections() {
|
|
30
|
-
return buildOwnedUiSettingsSections({ resolution: this.#resolution, agent: this.#agentSnapshot })
|
|
35
|
+
return buildOwnedUiSettingsSections({ resolution: this.#resolution, agent: this.#agentSnapshot }).map(section => ({
|
|
36
|
+
...section,
|
|
37
|
+
entries: section.entries.map(entry => entry.backend === "a1" && this.#restartEffective.has(entry.id)
|
|
38
|
+
? { ...entry, effectiveValue: this.#restartEffective.get(entry.id) }
|
|
39
|
+
: entry),
|
|
40
|
+
}));
|
|
31
41
|
}
|
|
32
42
|
value(id) {
|
|
33
|
-
return this.#resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
43
|
+
return this.#restartEffective.get(id) ?? this.#resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
34
44
|
}
|
|
35
45
|
pendingValue(id) {
|
|
36
46
|
return this.#pending.get(id) ?? null;
|
|
@@ -61,9 +71,8 @@ export class OwnedUiSettingsSession {
|
|
|
61
71
|
const previousSetting = previous.settings.find(setting => setting.declaration.id === id);
|
|
62
72
|
if (previousSetting?.declaration.application === "restart") {
|
|
63
73
|
this.#pending.set(id, value);
|
|
64
|
-
this.#resolution = previous;
|
|
65
74
|
this.#notify();
|
|
66
|
-
return changed("deferred", "next-start", value,
|
|
75
|
+
return changed("deferred", "next-start", value, this.#restartEffective.get(id));
|
|
67
76
|
}
|
|
68
77
|
this.#pending.delete(id);
|
|
69
78
|
this.#notify();
|
|
@@ -28,6 +28,8 @@ The owned Pi-backed surface is not an arbitrary-CLI terminal multiplexer. A feat
|
|
|
28
28
|
- `structured-agent-runtime`: planned typed event/command/snapshot runtime. It must not infer semantics from terminal text, own pseudoterminals, or reconstruct screens.
|
|
29
29
|
- `native-host-protocol`: bounded typed local boundary for terminal-host identity, topology revisions, lifecycle, and recovery. Terminal bytes, per-event child input, and rendered cells are forbidden across it.
|
|
30
30
|
- `protocol`: additive control handshake, bounded line framing, authenticated launch-instance commands, typed stop intent, snapshots, and command results.
|
|
31
|
+
- `launch`: resolves the effective profile home and the history-specific data root. Composition uses its public path resolver to select `~/.a1/data` for history unless `A1_DATA_DIR` is explicit; global control/release/runtime/cache paths stay unchanged.
|
|
32
|
+
- `prompt-history`: narrowly typed user-input retention in separate profile-owned databases under `~/.a1/data/history` (or `<A1_DATA_DIR>/history`), with bounded worker queues and no supervisor/control-store payloads. It receives a resolved root rather than importing launch-feature internals; it never probes, imports, or deletes the former platform-default history. The editor's owned history state machine remains inside the Pi component boundary; the session UI only coordinates snapshots and classified submissions.
|
|
31
33
|
- `storage`: SQLite migrations, prior-boot reconciliation, and plural launch-instance persistence. Legacy foreground rows are historical migration input and never authorize current ownership.
|
|
32
34
|
- `supervisor`: endpoint identity, plural cohort ownership, per-instance reconciliation, and aggregate release shutdown coordination. It owns no terminal surface.
|
|
33
35
|
- `pi-engine-adapter`, `pi-component-adapter`, `pi-tui-runtime-adapter`, and `pi-session-ui-integration`: isolate pinned Pi engine and presentation knowledge behind neutral contracts; product features do not import them directly. The session UI render root assembles semantic document and dock rows, while its focused viewport controller owns follow state, pointer routing, selection, and interaction timers. Owned-app route lifecycle belongs to the neutral `ui-apps` owner and is only hosted by the Pi session UI.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# History editor source boundary
|
|
2
|
+
|
|
3
|
+
The history-enabled default editor is derived from Pi 0.84.2 at commit
|
|
4
|
+
`914cf1472e715297caa30db4b9535d534a9eb718`, repository
|
|
5
|
+
<https://github.com/earendil-works/pi>. The approved scope is
|
|
6
|
+
`openspec/changes/add-persistent-prompt-history/design.md`, decision 2a.
|
|
7
|
+
|
|
8
|
+
## Source and import inventory
|
|
9
|
+
|
|
10
|
+
The owning directory is `src/integrations/pi/components/upstream/history/`.
|
|
11
|
+
|
|
12
|
+
| Owned unit | Upstream source under `packages/tui/src/` | Retained behavior |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `editor-core.ts` | `components/editor.ts` | Editor state machine, layout, history boundaries, paste backing, autocomplete, undo integration |
|
|
15
|
+
| `kill-ring.ts` | `kill-ring.ts` | Kill/yank accumulation and rotation |
|
|
16
|
+
| `undo-stack.ts` | `undo-stack.ts` | Clone-on-push undo storage |
|
|
17
|
+
| `word-navigation.ts` | `word-navigation.ts` | Word/atomic-segment navigation |
|
|
18
|
+
| `text-helpers.ts` | selected declarations in `utils.ts` | Shared local segmenters, CJK break classification, punctuation/whitespace predicates only |
|
|
19
|
+
| `printable-key.ts` | selected declarations in `keys.ts` | Pure modifyOtherKeys printable helper and modifier constants; delegates Kitty decoding to the public export |
|
|
20
|
+
|
|
21
|
+
All reusable terminal APIs come from `#pi-tui`: keybinding state, `matchesKey`,
|
|
22
|
+
`decodeKittyPrintable`, `CURSOR_MARKER`, width/slicing, `SelectList`, and public
|
|
23
|
+
component/autocomplete types. No terminal runtime, parser stack, terminal
|
|
24
|
+
renderer, package loader, or dependency copy is introduced. The terminal-package
|
|
25
|
+
alias and exported constructors remain unchanged.
|
|
26
|
+
|
|
27
|
+
`node scripts/pi/extract-history-editor-source.mjs` resolves the terminal package
|
|
28
|
+
from pinned Pi's entry and extracts references and hashes into the ignored
|
|
29
|
+
`.artifacts/history-editor-upstream/` directory. It never overwrites owned code.
|
|
30
|
+
The source ledger records upstream and owned destination hashes. Source maps are
|
|
31
|
+
used only by provenance tooling, not by the shipped runtime. Changed source must
|
|
32
|
+
be explicitly reconciled, not automatically adopted in an engine upgrade.
|
|
33
|
+
|
|
34
|
+
## Owned changes and collaborator boundaries
|
|
35
|
+
|
|
36
|
+
The core uses public imports, a distinct `HistoryEditorCore` class, and strict
|
|
37
|
+
TypeScript declaration adjustments. Persistent history is opt-in: its typed
|
|
38
|
+
snapshot installation and observation methods preserve input and undo state,
|
|
39
|
+
freeze an active browse cycle, and change caret placement only in that mode.
|
|
40
|
+
The editor renders position/overflow in its existing border. The position label
|
|
41
|
+
uses an injected neutral status-text style (`dim`), while the surrounding rules
|
|
42
|
+
retain the active input-border color, as clarified during manual review. Recall temporarily
|
|
43
|
+
separates the draft's live paste backing from recalled literal text, restoring it
|
|
44
|
+
on return; ordinary pinned mode remains source-equivalent.
|
|
45
|
+
|
|
46
|
+
The integration inventory is:
|
|
47
|
+
|
|
48
|
+
- `shell-editor-autocomplete.ts`: choose the default editor through a typed
|
|
49
|
+
component interface, never cast the owned core to the concrete Pi editor.
|
|
50
|
+
- `upstream/components/owned-editor.ts`: retain its pinned-based comparison and
|
|
51
|
+
disabled-history route; share app actions and owned prefix/suggestion behavior
|
|
52
|
+
through typed composition for the history-enabled route.
|
|
53
|
+
- `owned-editor-ux.ts`: selection, atomic segmentation, visual-line geometry,
|
|
54
|
+
provisional paste completion, and undo repair need a typed owned collaborator
|
|
55
|
+
boundary. Existing compatibility access on the pinned route is not permission
|
|
56
|
+
for new private access on the owned core.
|
|
57
|
+
- `shell-extension-ui.ts`: public text, shortcut, autocomplete, and factory
|
|
58
|
+
behavior remain extension-owned. A custom editor is not patched for recall.
|
|
59
|
+
- `session-shell-root.ts` and `session-shell.ts`: deliver semantic snapshot and
|
|
60
|
+
submission events; they must not own a second history index, mutable draft,
|
|
61
|
+
undo stack, or rendered-border parser.
|
|
62
|
+
|
|
63
|
+
`test/integrations/pi/components/history-editor-core.test.ts` independently runs
|
|
64
|
+
real pinned and owned editors against the same input tapes, comparing rows,
|
|
65
|
+
text/expanded text, cursor, autocomplete, and submissions. Separate fixtures
|
|
66
|
+
cover v2 directional placement and numbering, deferred snapshots, draft/undo
|
|
67
|
+
restoration, and literal paste-marker collisions. This is editor-core evidence,
|
|
68
|
+
not acceptance of the complete persistent-history feature.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
Upstream license at the recorded commit:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
MIT License
|
|
76
|
+
|
|
77
|
+
Copyright (c) 2025 Mario Zechner
|
|
78
|
+
|
|
79
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
80
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
81
|
+
in the Software without restriction, including without limitation the rights
|
|
82
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
83
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
84
|
+
furnished to do so, subject to the following conditions:
|
|
85
|
+
|
|
86
|
+
The above copyright notice and this permission notice shall be included in all
|
|
87
|
+
copies or substantial portions of the Software.
|
|
88
|
+
|
|
89
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
90
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
91
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
92
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
93
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
94
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
95
|
+
SOFTWARE.
|
|
96
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Internal naming and private launch context
|
|
2
|
+
|
|
3
|
+
Internal code names contain no case-insensitive `a1` substring. This includes constants, variables, parameters, functions, methods, classes, types, private fields, aliases, and quoted/constant-computed member names. Branding remains at supported external boundaries: the `a1` command, public package identity, user-visible text, user directories, public settings, and declared serialized fields.
|
|
4
|
+
|
|
5
|
+
## Required PR validation
|
|
6
|
+
|
|
7
|
+
The required **Internal naming validation** job scans complete added, modified, copied, and renamed-to files at the exact PR head against the complete merge-base diff. It does not inspect only changed lines. Policy, exception, ownership, parser-dependency, and selection changes require a full audit and inspector regression tests. A stale, missing, failed, or unexpectedly skipped required result blocks the aggregate development check.
|
|
8
|
+
|
|
9
|
+
The nightly release workflow runs `full-release`, including `naming-full`, against the entire tracked codebase at its selected source commit. It does not use PR changed-file selection, including when it verifies an already-published immutable package. Naming failure fails platform validation and blocks publication. `naming-selection.test.ts` locks down this nightly wiring and checks that unchanged source is audited.
|
|
10
|
+
|
|
11
|
+
- Full local audit: `npm run check:names` (tracked files, including staged new files).
|
|
12
|
+
- Exact selected PR audit: `npm run check:names:changed` after producing `.artifacts/validation/impact.json`.
|
|
13
|
+
- Evidence: `.artifacts/validation/naming.json`, uploaded as `development-naming-validation`.
|
|
14
|
+
- Parser fixtures: `test/repository-governance/naming-inspection.test.ts`.
|
|
15
|
+
- Git selection fixtures: `test/repository-governance/naming-selection.test.ts`.
|
|
16
|
+
|
|
17
|
+
TypeScript/JavaScript and Python use syntax trees. Rust uses a token-aware scanner. Workflow environment maps, embedded Node scripts, JSON environment definitions, and supported shell assignments are inspected. Dependencies, immutable vendor files, generated output, and other worktrees are excluded; owned test helpers and locally adapted source ports are not. Unsupported owned inputs fail explicitly. Python inspection uses a bundled development-only grammar, not an installed Python interpreter.
|
|
18
|
+
|
|
19
|
+
The exact externally branded key/member authority is `config/internal-naming-policy.json`. It records each setting's owner, evidence, exposure, and value semantics. Arbitrary uppercase properties are not public environment settings. No compatibility-alias exposure category is allowed. Test snippets and negative-test input data are not declarations or supported aliases.
|
|
20
|
+
|
|
21
|
+
## Environment ownership inventory
|
|
22
|
+
|
|
23
|
+
### Supported branded external settings
|
|
24
|
+
|
|
25
|
+
| Keys | Producer / consumer and exposure |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `A1_CONFIG_DIR`, `A1_DATA_DIR`, `A1_RUNTIME_DIR`, `A1_DATABASE_PATH`, `A1_ENDPOINT` | User/shell configuration consumed by `src/foundation/lifecycle/paths.ts`; documented public overrides, unchanged. |
|
|
28
|
+
| `A1_PROFILE_HOME` | Caller-supplied profile-home override consumed by `src/features/launch/profile-paths.ts`; exact existing exposure-review entry. |
|
|
29
|
+
| `A1_STARTUP_TRACE` | Caller-supplied diagnostic path and trace context in `src/foundation/startup/startup-runtime.ts`; exact existing exposure-review entry. |
|
|
30
|
+
| `A1_DEV_INSTANCE_ID`, `A1_DEV_ROOT` | Caller-supplied development overrides consumed by `src/features/launch/development-launch.ts`; exact existing exposure-review entries. |
|
|
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
|
+
| `A1_PROBE_TRACE` | Opt-in diagnostics read by native terminal-host code; exact existing exposure-review entry. |
|
|
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. |
|
|
35
|
+
|
|
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
|
+
|
|
38
|
+
### Current private settings
|
|
39
|
+
|
|
40
|
+
| Keys | Producer / consumer and value semantics |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `LAUNCH_CONTEXT_RELEASE_ROOT`, `LAUNCH_CONTEXT_RELEASE_ID`, `LAUNCH_CONTEXT_RELEASE_DIGEST`, `LAUNCH_CONTEXT_RELEASE_LAYERS` | Release bootstrap writes the selected verified immutable identity; supervision, guardian, and startup/cache readers consume it. Layers are comma-separated and can be empty. |
|
|
43
|
+
| `LAUNCH_CONTEXT_PROFILE` | Bootstrap or the development launcher writes the selected `a1`/`pi` profile; guardian and UI entries consume it. |
|
|
44
|
+
| `LAUNCH_CONTEXT_WARMUP` | Release warmup writes exactly `1`; the private warmup entry requires it together with release context. |
|
|
45
|
+
| `RELEASE_CLEANUP_HOLDS`, `RELEASE_CLEANUP_RUN_ID` | Cleanup scheduler/worker handoff in `src/foundation/release/release-gc.ts`; serialized holds and a worker run identity. |
|
|
46
|
+
| `SOURCE_LEDGER_PATH`, `SOURCE_LEDGER_SCAN_ROOT`, `SOURCE_LEDGER_PORT_ROOT` | Source-ledger governance fixture overrides; produced by its tests and consumed by `check-pinned-pi-source-ledger.mjs`. |
|
|
47
|
+
| `RELEASE_RUNNER_LABEL` | Release/full-regression workflows supply certification-runner provenance to `run-release-gates.mjs`. |
|
|
48
|
+
| `TERMINAL_FIXTURE_INPUT`, `TERMINAL_FIXTURE_TOKEN` | Native terminal probe producer/consumer in `native/terminal-host/src/main.rs`; expected input and fixture token. |
|
|
49
|
+
| `DOCS_AUTO_MERGE_POLL_ATTEMPTS`, `DOCS_AUTO_MERGE_POLL_MS` | Documentation automation polling controls, produced by governance tests and consumed by `manage-documentation-auto-merge.mjs`. |
|
|
50
|
+
| `VALIDATION_JOB_STARTED_MS`, `RENDERING_JOB_STARTED_MS` | CI timing handoffs within `.github/workflows/ci.yml`; epoch milliseconds. |
|
|
51
|
+
| `RUN_PROCESS_CONTAINMENT_INTEGRATION` | CI enables the real containment fixture with exactly `1`; platform containment tests consume it. |
|
|
52
|
+
| `PACKAGE_MESSAGE_SCENARIO` | Package-message worker parent/child JSON scenario handoff. |
|
|
53
|
+
| `RECOVERY_TEST_CANCEL_AFTER`, `RECOVERY_TEST_REMOVAL_MARKER` | Recovery test parent/fake-npm handoff; mutation index and disposable sentinel path. |
|
|
54
|
+
|
|
55
|
+
The private launch contract is `neutral-launch-v1`, declared by the package's `privateLaunchContract` metadata and bound into immutable release identity. It is validated before activation or execution. There is one reader/writer and no mapping from obsolete private names.
|
|
56
|
+
|
|
57
|
+
### Existing neutral automation and third-party boundaries
|
|
58
|
+
|
|
59
|
+
These names are already neutral; their definitions and consumers remain the authority for their existing behavior:
|
|
60
|
+
|
|
61
|
+
- Development aggregate: `CHANGES_RESULT`, `DOCS_RESULT`, `DOCUMENTATION_RESULT`, `DOCUMENTATION_REQUIRED`, `VALIDATE_RESULT`, `CONTAINMENT_RESULT`, `STARTUP_RESULT`, `RENDERING_RESULT`, `RENDERING_TIER`, `DOCS_ONLY`, `VERSION_ONLY`, `OPENSPEC_TOUCHED`, `SELECTED_HEAD`, `EXPECTED_HEAD`, `EVENT_BASE_SHA`, `EVENT_HEAD_SHA`. The workflow produces these and `require-development-validation.mjs` or the selector consumes them.
|
|
62
|
+
- Naming aggregate: `NAMING_RESULT`, `NAMING_REQUIRED`, `NAMING_HEAD`, produced by CI and consumed by the same required aggregate.
|
|
63
|
+
- Validation: `VALIDATION_BUILD_READY`, `VALIDATION_CANDIDATE_TARBALL`, `VALIDATION_DOCUMENTATION_FULL_READY`, `VALIDATION_SELECTION_JSON`, `STARTUP_PERFORMANCE_RESULT`, owned by validation orchestration and exact-package fixtures.
|
|
64
|
+
- Publication workflow-local handoffs: `BUILD`, `EVENT_NAME`, `EXISTS`, `EXPECTED_INTEGRITY`, `EXPECTED_REGISTRY_INTEGRITY`, `EXPECTED_REGISTRY_SHASUM`, `EXPECTED_SHASUM`, `MODE`, `PACKAGE`, `PLAN`, `PUBLISH`, `PULLS_PATH`, `PULL_REQUEST`, `REGISTRY_TARBALL`, `RELEASE_CHANNEL`, `RELEASE_VERSION`, `REQUESTED_CHANNEL`, `REQUESTED_SHA`, `SOURCE_SHA`, `VALIDATE`, `VERSION`, `WORK`, defined and consumed in `.github/workflows/release.yml`.
|
|
65
|
+
- Isolated fixture controls: `PROMPT_SUGGESTION_AGENT_DIR`, `RUN_PROMPT_SUGGESTION_PROVIDER_TEST`, `TEST_SUPERVISOR_SECRET`, owned by their specific provider/supervisor tests.
|
|
66
|
+
- Host/tool integration: `CARGO`, `ZIG`, `PATH`, `HOME`, `USERPROFILE`, `APPDATA`, `LOCALAPPDATA`, XDG directory variables, `TERM`, `COLORTERM`, `TERM_PROGRAM`, `WT_SESSION`, `EXEPATH`, `MINGW_PREFIX`, `MSYSTEM`, and third-party `PI_*`, `GITHUB_*`, `GH_TOKEN`, and npm variables. Their external spellings and caller values are not private product naming targets. The forwarding of an arbitrary user's environment is distinct from defining an owned setting.
|
|
67
|
+
|
|
68
|
+
### Removed or reclassified registry entries
|
|
69
|
+
|
|
70
|
+
The old environment registry included `fixture` and `inputAcknowledgement`, but their values describe native probe stdout markers, not environment settings. Their existing external wire spellings stay in that protocol, not in the public environment registry.
|
|
71
|
+
|
|
72
|
+
`certificationTarball`, `internalPackaging`, `nativePi`, `piParityIntentionalMutation`, `protocolVersion`, `structuredFlowLimits`, `terminalArgumentsJson`, and `terminalExecutable` had no active runtime consumer in the reviewed tree. They are removed from the current environment authority, not renamed into new settings. Rejection patterns and immutable historical evidence remain factual.
|
|
73
|
+
|
|
74
|
+
## Clean cutover and protected state
|
|
75
|
+
|
|
76
|
+
The first new-contract installation is intentionally not an old-to-new `a1 update` path. Stop existing A1 sessions, supervisors, and workers first. Install the **accepted published version** explicitly with `npm install --global @timurproko/a1@<accepted-version>`; the implementation/release handoff must replace the placeholder with the actual accepted version. Do not execute an old recovery launcher to bridge the cutover.
|
|
77
|
+
|
|
78
|
+
Old-contract targets are rejected with a cutover diagnostic. No reset or migration runs automatically. If disposable state blocks installation, inspect its resolved paths and obtain separate approval before removal. A supported rollback must also use `neutral-launch-v1`; no eligible target means an explicit unavailable rollback, not a fallback to older code.
|
|
79
|
+
|
|
80
|
+
| State | Treatment |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `<configDir>` and its settings | Preserve. |
|
|
83
|
+
| `~/.a1/agent`, credentials, extensions, and session files | Preserve. |
|
|
84
|
+
| Prompt-history databases under the selected data/history owner | Preserve; this change does not relocate history. |
|
|
85
|
+
| `<dataDir>/releases`, release references/certification records, `<dataDir>/update-recovery`, update journal | Disposable runtime/release candidates only; inspect exact paths and live ownership before any separately approved manual reset. |
|
|
86
|
+
| `<runtimeDir>` endpoints, locks, and worker records | Reset candidates only after all affected processes stop and their precise scope is confirmed. |
|
|
87
|
+
| The whole `<dataDir>` or `<configDir>` | Never delete as a shortcut: disposable and user data can share these roots. |
|
|
88
|
+
|
|
89
|
+
`test/foundation/launch-context/cutover.test.ts` places protected settings/session/history sentinels next to incompatible runtime fixtures and verifies failed admission does not change them. No test or implementation command uses actual user data as its cleanup fixture.
|