@timurproko/a1 0.1.8-dev.157 → 0.1.8-dev.214
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 +32 -0
- package/bin/cli.js +2 -2
- package/bin/sync-pi-tui-proxy.js +1 -1
- package/bin/ui.js +18 -3
- package/dist/cli/dispatch.js +3 -3
- package/dist/cli/packages.js +1 -1
- package/dist/cli/version-stats.js +3 -3
- package/dist/composition/owned-ui.d.ts +4 -1
- package/dist/composition/owned-ui.js +9 -6
- package/dist/composition/settings-route-host.js +6 -4
- package/dist/contracts/agent-engine/capability-ports.d.ts +2 -2
- package/dist/contracts/agent-engine/domain-validation.js +22 -4
- package/dist/contracts/agent-engine/domain.d.ts +17 -0
- package/dist/contracts/owned-ui/model.d.ts +8 -0
- package/dist/contracts/owned-ui/validation.js +11 -0
- package/dist/features/launch/development-launch.js +1 -1
- package/dist/features/owned-ui/customization.d.ts +2 -0
- package/dist/features/owned-ui/customization.js +2 -0
- package/dist/features/owned-ui/diagnostics.d.ts +1 -0
- package/dist/features/owned-ui/diagnostics.js +1 -0
- package/dist/features/owned-ui/index.d.ts +1 -0
- package/dist/features/owned-ui/index.js +1 -0
- package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
- package/dist/features/owned-ui/project-trust-prompt.js +149 -0
- package/dist/features/owned-ui/settings-app.js +69 -44
- package/dist/features/workspace/reducer.d.ts +1 -0
- package/dist/features/workspace/reducer.js +1 -0
- package/dist/features/workspace/router.d.ts +1 -0
- package/dist/features/workspace/router.js +1 -0
- package/dist/features/workspace/store.d.ts +1 -0
- package/dist/features/workspace/store.js +1 -0
- package/dist/foundation/launch-guardian/main.js +1 -1
- package/dist/foundation/native-host-protocol/codec.d.ts +2 -0
- package/dist/foundation/native-host-protocol/codec.js +2 -0
- package/dist/foundation/process-containment/linux-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/linux-process-inspector.js +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.d.ts +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.js +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.js +1 -0
- package/dist/foundation/protocol/client.d.ts +1 -0
- package/dist/foundation/protocol/client.js +1 -0
- package/dist/foundation/protocol/messages.d.ts +1 -0
- package/dist/foundation/protocol/messages.js +1 -0
- package/dist/foundation/release/bootstrap.js +6 -6
- package/dist/foundation/release/cohort-state.d.ts +1 -0
- package/dist/foundation/release/cohort-state.js +1 -0
- package/dist/foundation/release/release-gc.js +1 -1
- package/dist/foundation/release/release.js +1 -1
- package/dist/foundation/release/update-transaction.d.ts +1 -0
- package/dist/foundation/release/update-transaction.js +1 -0
- package/dist/foundation/release/update.js +12 -12
- package/dist/foundation/storage/control-store.d.ts +1 -0
- package/dist/foundation/storage/control-store.js +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.js +1 -0
- package/dist/foundation/structured-agent-runtime/commands.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/commands.js +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.js +1 -0
- package/dist/foundation/structured-agent-runtime/state.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/state.js +1 -0
- package/dist/foundation/supervision/main.js +1 -1
- package/dist/foundation/supervision/server.d.ts +1 -0
- package/dist/foundation/supervision/server.js +4 -6
- package/dist/integrations/pi/components/conformance.d.ts +1 -0
- package/dist/integrations/pi/components/conformance.js +1 -0
- package/dist/integrations/pi/components/shell-components.d.ts +1 -0
- package/dist/integrations/pi/components/shell-components.js +1 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +10 -0
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +19 -13
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +36 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +78 -0
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +3 -36
- package/dist/integrations/pi/components/shell-presenters-transcript.js +88 -128
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +11 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +22 -4
- package/dist/integrations/pi/engine/adapter.js +220 -70
- package/dist/integrations/pi/engine/conformance.d.ts +2 -0
- package/dist/integrations/pi/engine/conformance.js +2 -0
- package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
- package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
- package/dist/integrations/pi/engine/index.d.ts +3 -0
- package/dist/integrations/pi/engine/index.js +3 -0
- package/dist/integrations/pi/engine/model-auth-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/model-auth-integration.js +1 -0
- package/dist/integrations/pi/engine/package-integration.js +1 -1
- package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
- package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
- package/dist/integrations/pi/engine/resource-extension-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/resource-extension-integration.js +1 -0
- package/dist/integrations/pi/engine/runtime-integration.d.ts +16 -1
- package/dist/integrations/pi/engine/runtime-integration.js +34 -4
- package/dist/integrations/pi/engine/session-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/session-integration.js +2 -1
- package/dist/integrations/pi/engine/settings-effects.d.ts +66 -0
- package/dist/integrations/pi/engine/settings-effects.js +249 -0
- package/dist/integrations/pi/engine/settings-integration.d.ts +14 -26
- package/dist/integrations/pi/engine/settings-integration.js +102 -108
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +2 -1
- package/dist/integrations/pi/engine/workflow-controllers.js +1 -0
- package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
- package/dist/integrations/pi/session-ui/clipboard-image.js +29 -0
- package/dist/integrations/pi/session-ui/index.d.ts +1 -0
- package/dist/integrations/pi/session-ui/index.js +1 -0
- package/dist/integrations/pi/session-ui/prompt-chips.js +6 -2
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +39 -4
- package/dist/integrations/pi/session-ui/session-shell-root.js +215 -80
- package/dist/integrations/pi/session-ui/session-shell.d.ts +10 -1
- package/dist/integrations/pi/session-ui/session-shell.js +256 -45
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +76 -11
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.d.ts +29 -0
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.js +79 -0
- package/dist/integrations/pi/session-ui/system-clipboard.d.ts +9 -0
- package/dist/integrations/pi/session-ui/system-clipboard.js +38 -9
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +166 -8
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +25 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +63 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +240 -0
- package/dist/integrations/pi/tui-runtime/index.d.ts +2 -0
- package/dist/integrations/pi/tui-runtime/index.js +2 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
- 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/ui/apps/host.js +5 -9
- package/dist/ui/apps/registry.d.ts +1 -0
- package/dist/ui/apps/registry.js +1 -0
- package/dist/ui/components/dialog-panel.js +5 -3
- package/dist/ui/components/frame.d.ts +1 -0
- package/dist/ui/components/frame.js +1 -0
- package/dist/ui/components/index.d.ts +1 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/line-input.d.ts +1 -6
- package/dist/ui/components/line-input.js +4 -9
- package/dist/ui/components/list-view.d.ts +0 -6
- package/dist/ui/components/list-view.js +14 -7
- package/dist/ui/components/progress-status.d.ts +2 -0
- package/dist/ui/components/progress-status.js +4 -0
- package/dist/ui/components/scrollbar.js +1 -1
- package/dist/ui/components/shortcuts.d.ts +1 -0
- package/dist/ui/components/shortcuts.js +1 -0
- package/dist/ui/components/spans.d.ts +2 -5
- package/dist/ui/components/spans.js +28 -8
- package/dist/ui/components/surface.d.ts +0 -5
- package/dist/ui/components/surface.js +1 -5
- package/dist/ui/components/text-selection.d.ts +10 -1
- package/dist/ui/components/text-selection.js +96 -29
- package/dist/ui/components/text.js +3 -3
- package/dist/ui/components/transcript-viewport.d.ts +42 -0
- package/dist/ui/components/transcript-viewport.js +287 -39
- package/dist/ui/settings/sections.d.ts +6 -19
- package/dist/ui/settings/sections.js +17 -15
- package/dist/ui/settings/session.d.ts +8 -18
- package/dist/ui/settings/session.js +60 -52
- package/dist/ui/settings/store.d.ts +1 -0
- package/dist/ui/settings/store.js +2 -1
- package/docs/architecture/code-documentation.md +77 -0
- package/docs/architecture/project-structure.md +15 -1
- package/docs/architecture/ui-reference-provenance.md +23 -3
- package/docs/ci-release-runbook.md +98 -7
- package/docs/manual-owned-ui-checkpoint.md +28 -1
- package/docs/manual-terminal-colour-check.md +4 -3
- package/docs/repository-governance-live-acceptance.md +77 -0
- package/package.json +11 -3
|
@@ -1,46 +1,36 @@
|
|
|
1
|
-
import type { AgentSettingsPort } from "../../contracts/agent-engine/index.js";
|
|
1
|
+
import type { AgentJsonValue, AgentSettingApplicationBoundary, AgentSettingsPort } from "../../contracts/agent-engine/index.js";
|
|
2
2
|
import type { OwnedUiSettingValue } from "./declarations.js";
|
|
3
3
|
import type { OwnedUiSettingsResolution } from "./resolution.js";
|
|
4
4
|
import { type OwnedUiSettingsBackend, type OwnedUiSettingsSection } from "./sections.js";
|
|
5
5
|
import type { OwnedUiSettingsStore } from "./store.js";
|
|
6
6
|
export interface OwnedUiSettingsChangeOutcome {
|
|
7
|
+
readonly status: "applied" | "deferred" | "unavailable" | "failed";
|
|
7
8
|
readonly applied: boolean;
|
|
8
|
-
/**
|
|
9
|
+
/** Compatibility projection for existing A1 restart-bound declarations. */
|
|
9
10
|
readonly pendingRestart: boolean;
|
|
10
|
-
|
|
11
|
+
readonly application: AgentSettingApplicationBoundary | null;
|
|
12
|
+
readonly storedValue: AgentJsonValue | null;
|
|
13
|
+
readonly effectiveValue: AgentJsonValue | null;
|
|
14
|
+
readonly limitationReason: string | null;
|
|
11
15
|
readonly failure: string | null;
|
|
12
16
|
}
|
|
13
17
|
export interface OwnedUiSettingsSessionOptions {
|
|
14
18
|
readonly store: OwnedUiSettingsStore;
|
|
15
|
-
/** Null when no engine is attached; the Agent section then reports itself unavailable. */
|
|
16
19
|
readonly agent?: AgentSettingsPort | null;
|
|
17
|
-
/**
|
|
18
|
-
* Resolves the port at load time instead of construction time, for an engine
|
|
19
|
-
* whose runtime is not up yet. Takes precedence over `agent`.
|
|
20
|
-
*/
|
|
21
20
|
readonly agentProvider?: () => AgentSettingsPort | null;
|
|
22
|
-
/** Agent-owned controls fixed by this product surface and therefore omitted. */
|
|
23
21
|
readonly hiddenAgentSettingIds?: readonly string[];
|
|
24
22
|
}
|
|
25
23
|
export type OwnedUiSettingsListener = (session: OwnedUiSettingsSession) => void;
|
|
26
|
-
/**
|
|
27
|
-
* Holds the resolved settings for one owned UI session and routes every accepted
|
|
28
|
-
* change to the backend that owns it: A1 settings to the A1 document, agent
|
|
29
|
-
* settings to the engine settings port. Neither backend ever sees the other's value.
|
|
30
|
-
*/
|
|
24
|
+
/** Routes every accepted setting change only to its owning backend. */
|
|
31
25
|
export declare class OwnedUiSettingsSession {
|
|
32
26
|
#private;
|
|
33
27
|
constructor(options: OwnedUiSettingsSessionOptions);
|
|
34
28
|
get resolution(): OwnedUiSettingsResolution;
|
|
35
|
-
/** Reads the engine's settings so the Agent section can be built. Never throws. */
|
|
36
29
|
load(): Promise<void>;
|
|
37
30
|
sections(): readonly OwnedUiSettingsSection[];
|
|
38
|
-
/** Resolved value of an A1 setting, or null when it is not declared. */
|
|
39
31
|
value(id: string): OwnedUiSettingValue | null;
|
|
40
|
-
/** Value stored this session but not yet in effect, for a restart-required setting. */
|
|
41
32
|
pendingValue(id: string): OwnedUiSettingValue | null;
|
|
42
33
|
onChange(listener: OwnedUiSettingsListener): () => void;
|
|
43
|
-
/** Writes a structured value, which only an engine-backed setting can hold. */
|
|
44
34
|
changeStructured(backend: OwnedUiSettingsBackend, id: string, value: Readonly<Record<string, unknown>>): Promise<OwnedUiSettingsChangeOutcome>;
|
|
45
35
|
change(backend: OwnedUiSettingsBackend, id: string, value: OwnedUiSettingValue): Promise<OwnedUiSettingsChangeOutcome>;
|
|
46
36
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
+
import { assertAgentSettingDescriptor } from "../../contracts/agent-engine/index.js";
|
|
1
2
|
import { buildOwnedUiSettingsSections, findOwnedUiSettingsEntry, } from "./sections.js";
|
|
2
|
-
/**
|
|
3
|
-
* Holds the resolved settings for one owned UI session and routes every accepted
|
|
4
|
-
* change to the backend that owns it: A1 settings to the A1 document, agent
|
|
5
|
-
* settings to the engine settings port. Neither backend ever sees the other's value.
|
|
6
|
-
*/
|
|
3
|
+
/** Routes every accepted setting change only to its owning backend. */
|
|
7
4
|
export class OwnedUiSettingsSession {
|
|
8
5
|
#store;
|
|
9
6
|
#agent;
|
|
@@ -23,21 +20,18 @@ export class OwnedUiSettingsSession {
|
|
|
23
20
|
get resolution() {
|
|
24
21
|
return this.#resolution;
|
|
25
22
|
}
|
|
26
|
-
/** Reads the engine's settings so the Agent section can be built. Never throws. */
|
|
27
23
|
async load() {
|
|
28
24
|
this.#resolution = this.#store.read();
|
|
29
|
-
const agent = this.#
|
|
25
|
+
const agent = this.#currentAgent();
|
|
30
26
|
this.#agentSnapshot = agent === null ? null : await snapshotOf(agent, this.#hiddenAgentSettingIds);
|
|
31
27
|
this.#notify();
|
|
32
28
|
}
|
|
33
29
|
sections() {
|
|
34
30
|
return buildOwnedUiSettingsSections({ resolution: this.#resolution, agent: this.#agentSnapshot });
|
|
35
31
|
}
|
|
36
|
-
/** Resolved value of an A1 setting, or null when it is not declared. */
|
|
37
32
|
value(id) {
|
|
38
33
|
return this.#resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
39
34
|
}
|
|
40
|
-
/** Value stored this session but not yet in effect, for a restart-required setting. */
|
|
41
35
|
pendingValue(id) {
|
|
42
36
|
return this.#pending.get(id) ?? null;
|
|
43
37
|
}
|
|
@@ -45,27 +39,10 @@ export class OwnedUiSettingsSession {
|
|
|
45
39
|
this.#listeners.add(listener);
|
|
46
40
|
return () => this.#listeners.delete(listener);
|
|
47
41
|
}
|
|
48
|
-
/** Writes a structured value, which only an engine-backed setting can hold. */
|
|
49
42
|
async changeStructured(backend, id, value) {
|
|
50
43
|
if (backend !== "agent")
|
|
51
44
|
return failed("only an agent setting holds a structured value");
|
|
52
|
-
|
|
53
|
-
if (agent === null)
|
|
54
|
-
return failed("no agent engine is attached");
|
|
55
|
-
if (!agent.capabilities.write || !agent.writeSetting) {
|
|
56
|
-
return failed("the agent engine does not support changing settings from this surface");
|
|
57
|
-
}
|
|
58
|
-
try {
|
|
59
|
-
await agent.writeSetting(id, value);
|
|
60
|
-
if (agent.capabilities.flush && agent.flush)
|
|
61
|
-
await agent.flush();
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
return failed(`${id} could not be written to the agent engine: ${describe(error)}`);
|
|
65
|
-
}
|
|
66
|
-
this.#agentSnapshot = await snapshotOf(agent, this.#hiddenAgentSettingIds);
|
|
67
|
-
this.#notify();
|
|
68
|
-
return { applied: true, pendingRestart: false, failure: null };
|
|
45
|
+
return await this.#changeAgentValue(id, value);
|
|
69
46
|
}
|
|
70
47
|
async change(backend, id, value) {
|
|
71
48
|
const entry = findOwnedUiSettingsEntry(this.sections(), id, backend);
|
|
@@ -73,7 +50,7 @@ export class OwnedUiSettingsSession {
|
|
|
73
50
|
return failed(`unknown ${backend} setting: ${id}`);
|
|
74
51
|
if (!entry.editable)
|
|
75
52
|
return failed(`${id} is not editable from this surface`);
|
|
76
|
-
return backend === "a1" ? this.#changeOwned(id, value) : await this.#
|
|
53
|
+
return backend === "a1" ? this.#changeOwned(id, value) : await this.#changeAgentValue(id, value);
|
|
77
54
|
}
|
|
78
55
|
#changeOwned(id, value) {
|
|
79
56
|
const outcome = this.#store.write(this.#resolution, id, value);
|
|
@@ -81,35 +58,39 @@ export class OwnedUiSettingsSession {
|
|
|
81
58
|
return failed(outcome.failure ?? `${id} could not be stored`);
|
|
82
59
|
const previous = this.#resolution;
|
|
83
60
|
this.#resolution = this.#store.read();
|
|
84
|
-
const
|
|
85
|
-
if (declaration
|
|
61
|
+
const previousSetting = previous.settings.find(setting => setting.declaration.id === id);
|
|
62
|
+
if (previousSetting?.declaration.application === "restart") {
|
|
86
63
|
this.#pending.set(id, value);
|
|
87
64
|
this.#resolution = previous;
|
|
88
65
|
this.#notify();
|
|
89
|
-
return
|
|
66
|
+
return changed("deferred", "next-start", value, previousSetting.value);
|
|
90
67
|
}
|
|
91
68
|
this.#pending.delete(id);
|
|
92
69
|
this.#notify();
|
|
93
|
-
return
|
|
70
|
+
return changed("applied", "live", value, value);
|
|
94
71
|
}
|
|
95
|
-
async #
|
|
96
|
-
const agent = this.#
|
|
72
|
+
async #changeAgentValue(id, value) {
|
|
73
|
+
const agent = this.#currentAgent();
|
|
97
74
|
if (agent === null)
|
|
98
75
|
return failed("no agent engine is attached");
|
|
99
76
|
if (!agent.capabilities.write || !agent.writeSetting) {
|
|
100
77
|
return failed("the agent engine does not support changing settings from this surface");
|
|
101
78
|
}
|
|
79
|
+
let result;
|
|
102
80
|
try {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
81
|
+
// Invariant: the coordinator behind the port owns effect installation, persistence,
|
|
82
|
+
// flush, and rollback. A second surface-level flush would split authority.
|
|
83
|
+
result = await agent.writeSetting(id, value);
|
|
106
84
|
}
|
|
107
85
|
catch (error) {
|
|
108
86
|
return failed(`${id} could not be written to the agent engine: ${describe(error)}`);
|
|
109
87
|
}
|
|
110
88
|
this.#agentSnapshot = await snapshotOf(agent, this.#hiddenAgentSettingIds);
|
|
111
89
|
this.#notify();
|
|
112
|
-
return
|
|
90
|
+
return fromAgentOutcome(result);
|
|
91
|
+
}
|
|
92
|
+
#currentAgent() {
|
|
93
|
+
return this.#agentProvider === null ? this.#agent : this.#agentProvider();
|
|
113
94
|
}
|
|
114
95
|
#notify() {
|
|
115
96
|
for (const listener of this.#listeners)
|
|
@@ -118,29 +99,56 @@ export class OwnedUiSettingsSession {
|
|
|
118
99
|
}
|
|
119
100
|
async function snapshotOf(agent, hidden) {
|
|
120
101
|
try {
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
values[descriptor.key] = null;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
102
|
+
const listed = await agent.listSettings();
|
|
103
|
+
for (const descriptor of listed)
|
|
104
|
+
assertAgentSettingDescriptor(descriptor);
|
|
105
|
+
const writeAdvertised = agent.capabilities.write && typeof agent.writeSetting === "function";
|
|
106
|
+
const descriptors = listed.filter(descriptor => !hidden.has(descriptor.key) && writeAdvertised && descriptor.writable && descriptor.available);
|
|
131
107
|
return {
|
|
132
108
|
descriptors,
|
|
133
|
-
|
|
134
|
-
writeAdvertised: agent.capabilities.write && typeof agent.writeSetting === "function",
|
|
109
|
+
writeAdvertised,
|
|
135
110
|
failure: null,
|
|
136
111
|
};
|
|
137
112
|
}
|
|
138
113
|
catch (error) {
|
|
139
|
-
return { descriptors: [],
|
|
114
|
+
return { descriptors: [], writeAdvertised: false, failure: describe(error) };
|
|
140
115
|
}
|
|
141
116
|
}
|
|
142
117
|
function failed(failure) {
|
|
143
|
-
return {
|
|
118
|
+
return {
|
|
119
|
+
status: "failed",
|
|
120
|
+
applied: false,
|
|
121
|
+
pendingRestart: false,
|
|
122
|
+
application: null,
|
|
123
|
+
storedValue: null,
|
|
124
|
+
effectiveValue: null,
|
|
125
|
+
limitationReason: null,
|
|
126
|
+
failure,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function changed(status, application, storedValue, effectiveValue) {
|
|
130
|
+
return {
|
|
131
|
+
status,
|
|
132
|
+
applied: status === "applied",
|
|
133
|
+
pendingRestart: status === "deferred" && application === "next-start",
|
|
134
|
+
application,
|
|
135
|
+
storedValue,
|
|
136
|
+
effectiveValue,
|
|
137
|
+
limitationReason: null,
|
|
138
|
+
failure: null,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function fromAgentOutcome(result) {
|
|
142
|
+
return {
|
|
143
|
+
status: result.status,
|
|
144
|
+
applied: result.status === "applied",
|
|
145
|
+
pendingRestart: result.status === "deferred" && result.application === "next-start",
|
|
146
|
+
application: result.application,
|
|
147
|
+
storedValue: result.storedValue,
|
|
148
|
+
effectiveValue: result.effectiveValue,
|
|
149
|
+
limitationReason: result.limitationReason,
|
|
150
|
+
failure: result.failure,
|
|
151
|
+
};
|
|
144
152
|
}
|
|
145
153
|
function describe(error) {
|
|
146
154
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -13,6 +13,7 @@ export interface OwnedUiSettingsWriteOutcome {
|
|
|
13
13
|
/** Present when the write failed; the caller must not report the change as saved. */
|
|
14
14
|
readonly failure: string | null;
|
|
15
15
|
}
|
|
16
|
+
/** Resolves and atomically persists one profile's owned settings without discarding unknown keys. */
|
|
16
17
|
export declare class OwnedUiSettingsStore {
|
|
17
18
|
#private;
|
|
18
19
|
constructor(options: OwnedUiSettingsStoreOptions);
|
|
@@ -5,6 +5,7 @@ import { OWNED_UI_SETTINGS_MIGRATIONS } from "./migrations.js";
|
|
|
5
5
|
import { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, } from "./resolution.js";
|
|
6
6
|
const PROFILE_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
7
7
|
const MAX_DOCUMENT_BYTES = 256 * 1024;
|
|
8
|
+
/** Resolves and atomically persists one profile's owned settings without discarding unknown keys. */
|
|
8
9
|
export class OwnedUiSettingsStore {
|
|
9
10
|
#file;
|
|
10
11
|
#declarations;
|
|
@@ -76,7 +77,7 @@ export class OwnedUiSettingsStore {
|
|
|
76
77
|
rmSync(temporary, { force: true });
|
|
77
78
|
}
|
|
78
79
|
catch {
|
|
79
|
-
//
|
|
80
|
+
// Security: a leftover temporary file is inert: read() only ever opens the target path.
|
|
80
81
|
}
|
|
81
82
|
return { stored: false, failure: `${this.#file} could not be written: ${describe(error)}` };
|
|
82
83
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Code documentation
|
|
2
|
+
|
|
3
|
+
A1 treats source documentation as a contract, not as a coverage target. Names, types, and decomposition explain ordinary behavior. Comments remain only where removing them would hide a public responsibility, invariant, rationale, security property, platform constraint, compatibility boundary, protocol rule, concurrency rule, performance decision, or provenance fact.
|
|
4
|
+
|
|
5
|
+
## Public class contracts
|
|
6
|
+
|
|
7
|
+
Every first-party TypeScript class exposed through a production owner's public entry has exactly one JSDoc description at its declaration. The description states what the class owns and includes its material lifecycle or safety boundary when one exists.
|
|
8
|
+
|
|
9
|
+
Do not add JSDoc solely because a function, type, constructor, property, or method is exported. Do not document a class by repeating its name or listing its methods. Private and protected members never use JSDoc.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
/** Persists complete workspace views and recovery references through the control-store boundary. */
|
|
13
|
+
export class WorkspaceStore {
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Implementation comments
|
|
17
|
+
|
|
18
|
+
A retained implementation comment starts with the reason it exists:
|
|
19
|
+
|
|
20
|
+
| Intent | Use |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| `Invariant:` | State or ordering that every implementation path must preserve |
|
|
23
|
+
| `Rationale:` | A non-obvious choice among plausible alternatives |
|
|
24
|
+
| `Security:` | Trust, ownership, cleanup, disclosure, or failure-safety boundary |
|
|
25
|
+
| `Platform:` | Operating-system, terminal, filesystem, or toolchain behavior |
|
|
26
|
+
| `Compatibility:` | Behavior intentionally matching or accepting another version or surface |
|
|
27
|
+
| `Protocol:` | Wire, framing, input, encoding, or externally defined semantic rule |
|
|
28
|
+
| `Concurrency:` | Race, serialization, cancellation, or event-loop ordering |
|
|
29
|
+
| `Performance:` | Bounded work, caching, coalescing, or resource decision |
|
|
30
|
+
| `Provenance:` | Source, generated authority, or adaptation origin |
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// Security: an uncertain process identity never authorizes termination.
|
|
34
|
+
// Platform: Windows Terminal encodes Ctrl+Backspace as a raw backspace byte.
|
|
35
|
+
// Performance: finalized blocks cache by revision and width; live blocks always render.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A continuation line does not repeat the label. If no intent applies, remove the comment and make the code explain itself.
|
|
39
|
+
|
|
40
|
+
## Forbidden forms
|
|
41
|
+
|
|
42
|
+
The repository gate rejects:
|
|
43
|
+
|
|
44
|
+
- missing or multiple contracts on owner-public first-party classes;
|
|
45
|
+
- `<summary>` and `@summary` tags;
|
|
46
|
+
- boilerplate class descriptions and method inventories;
|
|
47
|
+
- JSDoc on private or protected members;
|
|
48
|
+
- uncategorized implementation comments;
|
|
49
|
+
- obvious commented-out code or control-flow narration;
|
|
50
|
+
- `TODO` or `FIXME` without an issue number, issue URL, or tracker identifier;
|
|
51
|
+
- `@ts-ignore` and suppression directives without a reason;
|
|
52
|
+
- an unclassified tracked code path or synchronized source without provenance.
|
|
53
|
+
|
|
54
|
+
Follow-up and suppression forms include their authority inline:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// TODO(#321): remove the compatibility path after the pinned upgrade.
|
|
58
|
+
// @ts-expect-error -- the shipped JavaScript module has no declaration file
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Source roles
|
|
62
|
+
|
|
63
|
+
The full style policy applies to first-party production TypeScript and to applicable comments in first-party tests, tooling, and native source. Native source does not receive TypeScript declaration requirements.
|
|
64
|
+
|
|
65
|
+
Synchronized Pi source, native vendor trees, generated source, build output, and runtime artifacts are not rewritten to match first-party style. Their exclusion comes from the repository source-role classifier, not from a list of accepted violations. Synchronized source must remain covered by its source ledger or explicit provenance header.
|
|
66
|
+
|
|
67
|
+
## Validation
|
|
68
|
+
|
|
69
|
+
Run the focused check with:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
npm run check:code-documentation
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The check scans the complete tracked baseline and reports stable rule identifiers with path, line, column, and declaration symbol when available. It has no accepted-violation count or grandfather file. Fast pull-request validation runs the check, and full release validation inherits it through the fast tier.
|
|
76
|
+
|
|
77
|
+
Focused governance tests use valid and invalid virtual sources to preserve each rule independently from the clean repository-baseline assertion. The gate validates deterministic structure and high-confidence anti-patterns; review remains responsible for the factual accuracy of retained prose.
|
|
@@ -86,6 +86,20 @@ The repository has one root `package.json`, `package-lock.json`, TypeScript conf
|
|
|
86
86
|
|
|
87
87
|
Build output mirrors the production namespaces directly under ignored `dist/`, without an intermediate `src/` directory; release and test evidence belongs in ignored `.artifacts/`; temporary agent work belongs in ignored `.worktrees/` and `.builds/`. Repository tooling is grouped under `scripts/governance`, `scripts/release`, `scripts/pi`, and `scripts/development`; the few root scripts are standalone maintenance or build commands. Package contents are selected by the root manifest. The Rust process guardian and console terminal-host proof live under `native/`; Cargo output is ignored. Third-party terminal parser sources are isolated under `native/terminal-host/vendor/` and are not owned application modules.
|
|
88
88
|
|
|
89
|
+
## Development worktrees
|
|
90
|
+
|
|
91
|
+
Every task worktree must be created at `{working-dir}/.worktrees/<task-id>`, where `{working-dir}` is the agent session's initial working directory. The `.worktrees` directory is inside that working directory, not beside it. For working directory `D:/Git/a1`, `D:/Git/a1/.worktrees/<task-id>` is correct and `D:/Git/a1-<task-id>` is forbidden.
|
|
92
|
+
|
|
93
|
+
From the initial working directory, create and address a task worktree explicitly:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
git fetch origin develop
|
|
97
|
+
git worktree add --detach .worktrees/<task-id> origin/develop
|
|
98
|
+
git -C .worktrees/<task-id> status
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The primary worktree stays on `develop` for integration and must not be used for task edits. Do not edit, move, or remove another session's worktree.
|
|
102
|
+
|
|
89
103
|
## Documentation and comments
|
|
90
104
|
|
|
91
105
|
- README explains installation, commands, and current limitations.
|
|
@@ -93,7 +107,7 @@ Build output mirrors the production namespaces directly under ignored `dist/`, w
|
|
|
93
107
|
- `docs/features` explains maintained user-facing behavior.
|
|
94
108
|
- Operational and manual procedures live in focused runbooks under `docs`.
|
|
95
109
|
- OpenSpec and Git carry planning and implementation history.
|
|
96
|
-
- Source
|
|
110
|
+
- Source documentation follows the focused [code-documentation policy](code-documentation.md): owner-public class contracts are consistent, retained implementation comments state their intent, and names, types, and decomposition explain ordinary control flow.
|
|
97
111
|
|
|
98
112
|
## Terminal capability boundary
|
|
99
113
|
|
|
@@ -29,7 +29,7 @@ its own `core` facade layer; A1 is a product, so the port adapts imports and kee
|
|
|
29
29
|
| `ui-components/list-block.ts` — sticky scroll | `settings/impl.ts` — `stickyHeaderGroup`, `topPaddingRows`, `visibleRowCountAt`, `clampScrollForView` | Same reservation arithmetic and two-pass reveal. |
|
|
30
30
|
| `ui-components/mouse.ts` | `core/panes/sgr-mouse.ts` | Same SGR decoding and per-call regex reset; A1 emits its own event shape. |
|
|
31
31
|
| `ui-components/mouse.ts` — tracking sequences | `core/host/pi/providers/host-bridge-surface.ts` | Mouse modes only. A1 does not take the alternate screen, because the Pi TUI owns the screen A1 renders through. |
|
|
32
|
-
| `features/owned-ui/settings-app.ts` — layout | `settings/impl.ts` — `settingsValueColumn`,
|
|
32
|
+
| `features/owned-ui/settings-app.ts` — section layout, pointer controls, and scrolling | `settings/impl.ts` — `settingsValueColumn`, block navigation, sticky sections, and pointer hit regions | Setting discovery is A1's own A1/Agent section model. Section navigation and pointer-only numeric controls follow the A1 reference; explicit `/` search, ruled shared input, shortcut-derived hints, hidden description rows, configured wheel cadence, and distinct floating scalar menus are reviewed owned interactions. |
|
|
33
33
|
|
|
34
34
|
## Ported from the pinned engine
|
|
35
35
|
|
|
@@ -37,16 +37,36 @@ its own `core` facade layer; A1 is a product, so the port adapts imports and kee
|
|
|
37
37
|
| --- | --- | --- |
|
|
38
38
|
| `pi-engine-adapter/settings-integration.ts` — `SETTING_LABELS` | pinned Pi settings selector | Labels and descriptions transcribed so an owned screen reads as the vanilla route words it. Ids are mapped from the selector kebab-case to the exposed camelCase keys. |
|
|
39
39
|
| `pi-engine/session-integration.ts` and `pi-components/shell-footer-status.ts` — steering queue | pinned Pi interactive mode `onSubmit` and `updatePendingMessagesDisplay` | Steering/follow-up uses `prompt(..., { streamingBehavior })`, allowing Pi to emit the accepted user row, while remaining steering rows preserve Pi's opening spacer, dim `Steering:` labels, dequeue hint, and order before `Working`. |
|
|
40
|
+
| `ui-components/list-view.ts`, `dialog-panel.ts`, `value-menu.ts`, and `features/owned-ui/settings-app.ts` — setting presentation | pinned Pi `SettingsSelectorComponent`, Pi TUI `SettingsList`, `SelectList`, and `Input` at `0.84.2` | Cursor, selected label/value accents, unselected muted values, the 30-column label cap, dialog styling, notices, and narrow-width geometry retain pinned semantics. Scalar-menu placement and input remain shared, while A1/Agent grouping, pointer steppers, explicit `/` search, ruled shared input, shortcut-derived status hints, suppressed selected descriptions, `scrollbarSpeed`-driven wheel movement, and the dark floating menu with lighter active row and effective-value check mark are declared product-owned differences. Independent row evidence: `test/features/owned-ui/pinned-settings-presentation-parity.test.ts`; owned interaction evidence: `test/features/owned-ui/settings-app.test.ts`, `test/ui/components/value-menu.test.ts`, and `test/composition/settings-route-host.test.ts`. |
|
|
41
|
+
| `features/owned-ui/project-trust-prompt.ts` — pre-resource selector | pinned Pi `cli/startup-ui.ts`, `cli/project-trust.ts`, and `core/project-trust.ts` at commit `914cf1472e715297caa30db4b9535d534a9eb718` | Uses a fixed, dependency-bounded A1 startup selector rather than importing private CLI modules. It preserves selected-option accent, navigation/accept/reject/cancel semantics, fail-closed behavior, raw-mode restoration, clearing, cursor restoration, and parent-screen restoration before diagnostics. |
|
|
42
|
+
| `pi-session-ui/session-shell-root.ts` and `session-shell.ts` — fullscreen exit | pinned Pi `InteractiveMode.formatResumeCommand()` and shutdown output at commit `914cf1472e715297caa30db4b9535d534a9eb718` | Re-renders authoritative transcript components with semantic SGR intact, excludes inline-image control payloads and fullscreen-only chrome, restores the terminal first, then emits pinned dim `To resume this session:` wording with `a1`, compact session id, and conditional quoted `--session-dir`. |
|
|
43
|
+
| `pi-tui-runtime/input-presentation-coordinator.ts` and custom-viewport dock reuse | pinned Pi TUI `TuiBase` input dispatch and immediate-render pending guard at `0.84.2` | Preserves each original terminal delivery and invokes the existing Pi handlers exactly once in order. Bare A1 alone drains finite-grammar text/edit/navigation bursts in one immediate event-loop opportunity so Pi's existing pending guard paints the newest state once; effectful, unknown, protocol, paste, and extension-owned input remains an immediate barrier. Geometry-stable dock frames reuse A1's established transcript viewport, while uncertain geometry and replacement-surface damage still fail closed. Independent evidence is under `test/support/input-responsiveness/`. |
|
|
44
|
+
| `test/features/owned-ui/pi-raw-terminal-parity.ts` — parity normalization | pinned Pi public components/runtime at `0.84.2` | Only synchronized-output envelopes, absolute hyperlink targets, declared product/path substitutions, and nondeterministic timing may normalize. SGR roles/reset boundaries, rows, cursor operations, clearing, restoration, and write order remain authoritative; A1-generated JSON captures are diagnostics and cannot serve as pinned evidence. |
|
|
40
45
|
|
|
41
46
|
## Deliberate differences
|
|
42
47
|
|
|
43
|
-
- **
|
|
44
|
-
through the pinned Pi TUI, so an owned screen is a full-viewport overlay instead.
|
|
48
|
+
- **Owned in-session routes are overlays.** The A1 UI reference owns its surface and can switch screens; A1 renders in-session owned routes through the pinned Pi TUI as full-viewport overlays. The pre-resource trust selector is separate and uses a bounded alternate startup surface solely so every completion path can restore the untouched parent terminal before engine activation or a fail-closed diagnostic.
|
|
45
49
|
- **Colour is a port, not an import.** The reference takes a Pi `Theme` directly. A1 defines
|
|
46
50
|
`UiTheme` so the component layer never imports a Pi adapter and can be rendered plainly in
|
|
47
51
|
tests.
|
|
48
52
|
- **Settings content.** The reference aggregates per-extension settings files; A1 has one
|
|
49
53
|
section for its own settings and one for the agent's, read through the engine settings port.
|
|
54
|
+
- **Settings scalar-menu contrast.** The shared menu keeps reviewed placement, clipping, and
|
|
55
|
+
input behavior, but A1 uses its prior dark floating panel, lighter white-text active row,
|
|
56
|
+
and independent effective-value check mark because physical review rejected a menu that
|
|
57
|
+
blended into the settings rows.
|
|
58
|
+
- **Spinner-backed progress punctuation.** Bare A1 resolves built-in and extension working
|
|
59
|
+
labels through `ui-components/progress-status.ts`, injected by
|
|
60
|
+
`pi-session-ui/session-shell-root.ts` into the shared `pi-components/shell-footer-status.ts`
|
|
61
|
+
spinner factory. The factory canonicalizes the visible progress marker once, to three ASCII
|
|
62
|
+
periods, without importing across the component-adapter boundary. Engine producers remain
|
|
63
|
+
semantic and the source-synchronized Pi status indicators, installed packages, `a1 pi`, and
|
|
64
|
+
vanilla Pi remain untouched.
|
|
65
|
+
- **Keyboard presentation scheduling.** Pinned components, semantic key handling, and the
|
|
66
|
+
comparison profiles stay unchanged. Bare A1 adds one A1-owned event-loop-turn coordinator
|
|
67
|
+
before its fullscreen root and may omit only superseded visual states after every delivery
|
|
68
|
+
has already been applied in order. It does not debounce by wall clock, combine strings,
|
|
69
|
+
patch Pi TUI, or classify unknown extension/terminal data as safe.
|
|
50
70
|
- **No viewport prototype or child-tree patches.** `ui/agent-view/user-prompt.ts` and the
|
|
51
71
|
private-child traversal in `ui/agent-view/render.ts` were analyzed only for behavior. The
|
|
52
72
|
destination renders source timestamps through an owned transcript adapter and derives sticky
|
|
@@ -12,6 +12,33 @@ GitHub Actions is the only automation platform. Three refs are protected:
|
|
|
12
12
|
channel. The workflow starts at `03:17 UTC` for nightly development verification,
|
|
13
13
|
or by explicit dispatch from `npm run develop` or `npm run release`.
|
|
14
14
|
|
|
15
|
+
`.github/workflows/documentation-auto-merge.yml` is the only pull-request
|
|
16
|
+
auto-merge authority. It runs trusted policy from `develop`; it never checks out or
|
|
17
|
+
executes a pull request's code with its write token.
|
|
18
|
+
|
|
19
|
+
`.github/workflows/merged-branch-cleanup.yml` owns branch deletion after a human or
|
|
20
|
+
external actor closes a pull request. On the close event it checks out trusted
|
|
21
|
+
default-branch policy and installs no pull-request dependencies. GitHub does not
|
|
22
|
+
emit a new workflow event for a merge authored with the workflow `GITHUB_TOKEN`, so
|
|
23
|
+
Documentation auto-merge also performs the same shared reconciliation synchronously
|
|
24
|
+
after its own validated integration. Both paths delete only an unprotected same-
|
|
25
|
+
repository topic ref whose live object still equals the merged pull request head SHA.
|
|
26
|
+
An absent ref is success; fork, unmerged, advanced, protected, default, release-owned,
|
|
27
|
+
or malformed refs are preserved and reported.
|
|
28
|
+
|
|
29
|
+
`config/github-repository-governance.json` is the reviewed policy for repository
|
|
30
|
+
settings, Actions defaults, security capabilities, environments, complete rulesets,
|
|
31
|
+
protected refs, and workflow authority. Inspection is read-only by default:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
node scripts/governance/check-github-repository-governance.mjs --check
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Applying reviewed mutable drift is a separate maintainer operation requiring
|
|
38
|
+
`--apply --confirm apply-a1-github-governance` and a matching post-apply read.
|
|
39
|
+
Secrets and external npm trusted-publisher configuration are capability checks, not
|
|
40
|
+
serialized credentials.
|
|
41
|
+
|
|
15
42
|
`develop` is where work lands. `master` records what npm `latest` serves and is an
|
|
16
43
|
effect of stable publication, not a trigger.
|
|
17
44
|
|
|
@@ -19,12 +46,67 @@ effect of stable publication, not a trigger.
|
|
|
19
46
|
|
|
20
47
|
| Trigger | Validation and outcome |
|
|
21
48
|
| --- | --- |
|
|
22
|
-
| Pull request into `develop` |
|
|
49
|
+
| Pull request into `develop` | Modular fast validation; changed/new source documentation is checked once, and rendering runs as `none`, `smoke`, or `full` from the exact impact |
|
|
23
50
|
| `npm run develop` | Preview package gates on Windows, Linux, and macOS; an existing numbered preview is an early successful no-op |
|
|
24
|
-
| Nightly at `03:17 UTC` |
|
|
51
|
+
| Nightly at `03:17 UTC` | One full documentation review plus the complete non-physical suite on Windows, Linux, and macOS, every night |
|
|
25
52
|
| `npm run release -- ...` | Complete exact-byte stable gates, then npm `latest`, tag, GitHub Release, and `master` |
|
|
26
53
|
| `.github/workflows/full-regression.yml` | Additional on-demand complete regression without publication authority |
|
|
27
54
|
|
|
55
|
+
## Impact-aware development validation
|
|
56
|
+
|
|
57
|
+
`scripts/release/select-validation-impact.mjs` is the single pull-request selector. It records the complete merge-base-to-head name-status diff, changed/new documentation inputs, rendering dependency reasons, conservative fallbacks, and the exact head SHA in a machine-readable artifact. Missing history, unresolved rendering dependencies, unknown relevant inputs, or classifier failure select full rendering rather than silently skipping it.
|
|
58
|
+
|
|
59
|
+
Ordinary type, architecture, unit/contract, and dist checks always run for code changes. Changed-file documentation and rendering run as independent parallel jobs. Rendered shell/component changes select `smoke`; viewport, scheduler, terminal adapter, evidence harness, package identity, and selector changes select `full`; unrelated changes select `none`. The aggregate accepts a skipped modular job only when the current selector requested the skip.
|
|
60
|
+
|
|
61
|
+
Inspect local committed and worktree impact without running tests:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npm run select:validation-impact -- --include-worktree
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Check documentation only for modified, added, copied, and renamed-to policy files:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npm run check:code-documentation:changed
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Run the explicit complete documentation review used by nightly and complete regression:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
npm run check:code-documentation
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Rendering evidence captures each selected producer/mode/workload matrix once and reuses it for semantic, paint, parity, and damage assertions. A deliberate second `streamed-prose` capture remains only for determinism. Workflow summaries separate repository-gate timing from runner setup; wall-clock values diagnose runner/cache variance, while selected scopes, matrix captures, producer launches, documentation file counts, and full-scan counts are structural gates.
|
|
80
|
+
|
|
81
|
+
## Pull request integration
|
|
82
|
+
|
|
83
|
+
`Development validation required` remains the merge gate for every pull request.
|
|
84
|
+
Documentation auto-merge reads the complete GitHub changed-file response and arms
|
|
85
|
+
squash auto-merge for an eligible pull request while required validation is pending;
|
|
86
|
+
branch protection prevents integration until `Development validation required`
|
|
87
|
+
succeeds. If validation finishes before auto-merge can be armed and GitHub already
|
|
88
|
+
reports the pull request clean, the reconciler squash-merges only the validated head
|
|
89
|
+
SHA. Every current and renamed-from path must be under `openspec/**`, under
|
|
90
|
+
`docs/**`, or exactly the root `README.md`. Eligible pull requests must use a
|
|
91
|
+
non-draft branch in this repository and target `develop`.
|
|
92
|
+
|
|
93
|
+
The exact allowlist covers maintained OpenSpec, architecture, feature, manual,
|
|
94
|
+
runbook, and root README documentation. Other root Markdown files, `LICENSE`,
|
|
95
|
+
`.gitignore`, source, tests, scripts, workflows, configuration, generated baselines,
|
|
96
|
+
and mixed changes do not auto-merge. The guard also runs when a pull request changes
|
|
97
|
+
or auto-merge is manually enabled; if any path is outside the allowlist, it disables
|
|
98
|
+
auto-merge while leaving the pull request available for a later manual merge. Every
|
|
99
|
+
docs-only change runs lightweight generated-governance consistency, so archiving an
|
|
100
|
+
inventoried OpenSpec occurrence fails that pull request rather than a later code pull
|
|
101
|
+
request. A legitimate generated baseline update remains outside the allowlist and
|
|
102
|
+
follows the manually accepted mixed/code path.
|
|
103
|
+
|
|
104
|
+
A specification request lands as an OpenSpec-only pull request. Implementation
|
|
105
|
+
starts only after that specification merges and the maintainer explicitly requests
|
|
106
|
+
it, in a fresh worktree and pull request based on updated `origin/develop`. Every
|
|
107
|
+
code/operational pull request remains open after CI until the maintainer validates it
|
|
108
|
+
locally and explicitly authorizes manual integration.
|
|
109
|
+
|
|
28
110
|
## Numbered development previews
|
|
29
111
|
|
|
30
112
|
A merge or push to `develop` does not publish by itself. To request a deliberate
|
|
@@ -42,8 +124,7 @@ already exists it reports that version without dispatching package work. Otherwi
|
|
|
42
124
|
it dispatches GitHub Actions, waits, and reports the published version. It never
|
|
43
125
|
builds or uploads npm bytes from the workstation.
|
|
44
126
|
|
|
45
|
-
Nightly resolves the same current `origin/develop` source. It always runs complete
|
|
46
|
-
verification even if source has not changed. For a new number it packs once and
|
|
127
|
+
Nightly resolves the same current `origin/develop` source. It runs one platform-independent full documentation review before the platform matrix, and the matrix records that prerequisite instead of repeating the scan four times. It always runs complete verification even if source has not changed. For a new number it packs once and
|
|
47
128
|
runs the suite against that final-version tarball before publication. For an
|
|
48
129
|
existing number it downloads the exact npm tarball and runs package/update gates
|
|
49
130
|
against those registry bytes; publication is then a successful no-op.
|
|
@@ -92,6 +173,14 @@ Rules that do not bend:
|
|
|
92
173
|
## When something fails
|
|
93
174
|
|
|
94
175
|
- **PR validation fails:** fix the code and push; do not mark a failed tier optional.
|
|
176
|
+
- **Documentation auto-merge fails:** leave the pull request open, inspect its exact
|
|
177
|
+
changed-file classification, docs-sensitive inventory, and workflow permissions,
|
|
178
|
+
and never broaden the allowlist to make one pull request pass.
|
|
179
|
+
- **Merged-branch cleanup fails:** inspect the bounded PR/ref/SHA disposition. Never
|
|
180
|
+
delete an advanced or protected ref merely because its name matches an old PR.
|
|
181
|
+
- **Repository governance drifts:** run the read-only checker, review every reported
|
|
182
|
+
path, and use the confirmed apply mode only for an accepted mutable policy change.
|
|
183
|
+
- **Nightly documentation review fails:** inspect the reported paths and rules, identify the introducing merge from the nightly interval, and repair the invariant before unrelated work proceeds.
|
|
95
184
|
- **Development publication fails:** fix the cause and rerun `npm run develop`; an npm version that already exists is never overwritten.
|
|
96
185
|
- **Stable publication fails before npm accepts bytes:** no tag, release, or moved branch exists. Fix the cause and release the next version.
|
|
97
186
|
- **Stable publication is uncertain after npm accepted bytes:** stop and inspect registry version, digest, tag, and release. Never republish immutable bytes.
|
|
@@ -104,6 +193,8 @@ and resolved review threads, but zero approving reviews. `master` and release ta
|
|
|
104
193
|
are written only after publication and are protected from force-push, movement, and
|
|
105
194
|
deletion.
|
|
106
195
|
|
|
107
|
-
Do not add direct-push bypasses.
|
|
108
|
-
|
|
109
|
-
|
|
196
|
+
Do not add direct-push bypasses. Approval count, strict-base validation, repository
|
|
197
|
+
merge methods, Actions allowance/SHA enforcement, Dependabot, and npm environment
|
|
198
|
+
protection remain explicit maintainer decisions; governance automation does not
|
|
199
|
+
silently change them. Repository mutation remains a separate confirmed administrative
|
|
200
|
+
operation through `check-github-repository-governance.mjs`.
|
|
@@ -4,6 +4,8 @@ This checkpoint is user-controlled. Tests and coding agents must not launch or f
|
|
|
4
4
|
|
|
5
5
|
## Prepare an exact candidate
|
|
6
6
|
|
|
7
|
+
For a checkout smoke test in Git Bash, build once and launch with `./scripts/dev` or `./scripts/dev pi`. Do not invoke `node scripts/development/dev-launch.mjs` or `node scripts/development/start-local.mjs` directly: that bypasses the color-preserving shell `exec` shape and can collapse the pinned 24-bit palette to Git Bash's 16 terminal colors. Run `node scripts/check-terminal-colour.mjs` first when color fidelity is in doubt; the first color block must differ from the terminal-palette cyan block.
|
|
8
|
+
|
|
7
9
|
From the candidate checkout, pack once and install that tarball into a disposable prefix:
|
|
8
10
|
|
|
9
11
|
```powershell
|
|
@@ -46,6 +48,31 @@ Use the same terminal, working directory, dimensions, environment, and equivalen
|
|
|
46
48
|
- [ ] Normal and error exits return a usable parent prompt.
|
|
47
49
|
- [ ] Parent typing, cursor movement, Backspace, Delete, and submission work after exit.
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
### Setting-controlled visual matrix
|
|
52
|
+
|
|
53
|
+
Use equivalent values in bare A1 and the Pi comparison profile. Exercise both a wide frame and a narrow frame that forces wrapping/clipping.
|
|
54
|
+
|
|
55
|
+
- [ ] `/settings`: selected cursor, label and value accent; unselected values muted; descriptions and hints dim; search uses `> ` with inverse cursor; scalar menus, numeric controls, warning-parts dialog, deferred notice, failed write, section spacing, clipping, and hidden-entry absence match their pinned semantic roles.
|
|
56
|
+
- [ ] Transcript: toggle images and image width, thinking level/visibility, Mermaid mode, output padding, cache notices, warnings, auto-compaction, queue modes, command autocomplete, provider timeout/retry/error, and changelog collapse. Existing and streaming blocks must re-render without focus, selection, scroll, or queued-work loss.
|
|
57
|
+
- [ ] Trust startup: from an undecided project, compare selected Trust/Do not trust rows, arrow navigation, Enter, Escape/Ctrl+C, clearing, cursor state, and restoration. No project extension/theme/prompt/skill may run before selection, and a fail-closed diagnostic must appear once on the restored parent rather than above a blank fullscreen frame.
|
|
58
|
+
- [ ] Terminal lifecycle: toggle hardware cursor, clear-on-shrink, and terminal progress; resize smaller/larger; open/close selectors; select and copy transcript text; verify no duplicate rows, stale OSC progress, leaked mouse mode, misplaced cursor, or broken parent input.
|
|
59
|
+
- [ ] Images: in Kitty or iTerm2 verify inline width and clipping; in Windows Terminal verify the textual fallback and absence of image protocol bytes without hiding `showImages`.
|
|
60
|
+
- [ ] Fullscreen exit `transcript`: verify the parent is restored before styled user, assistant Markdown, thinking, tool, notice, warning, error, and spacing rows are printed. No overlay, draft, animation, scrollbar, or inline-image payload may appear.
|
|
61
|
+
- [ ] Fullscreen exit `resume-hint`: verify only dim `To resume this session:` plus `a1 --session <compact-id>` is printed for the default directory. A custom directory must place quoted `--session-dir <dir>` before `--session`; the raw default `.jsonl` path must never print.
|
|
62
|
+
|
|
63
|
+
Record acceptance with:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
A1 commit/tarball:
|
|
67
|
+
Pi package: @earendil-works/pi-coding-agent 0.84.2
|
|
68
|
+
OS/version:
|
|
69
|
+
Terminal/version:
|
|
70
|
+
Terminal dimensions (wide/narrow):
|
|
71
|
+
Image protocol result:
|
|
72
|
+
Settings values exercised:
|
|
73
|
+
Outcome and any declared substitutions:
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Report failures with bare-versus-comparison behavior, platform and terminal versions, exact command, dimensions, settings values, reproducibility, and optional manually captured evidence.
|
|
50
77
|
|
|
51
78
|
For recovery, use `a1 pi`; do not use the removed `a1 ui` command. Manual acceptance can authorize an exact uncertified development preview after non-desktop gates pass. It does not certify stable presentation parity or platform support.
|
|
@@ -29,9 +29,10 @@ leave the launch without a terminal on its input; the launcher says so and stops
|
|
|
29
29
|
rather than opening a session that closes as it starts. Running `scripts/dev`
|
|
30
30
|
from the shell is the direct path.
|
|
31
31
|
|
|
32
|
-
A directly launched `node scripts/development/
|
|
33
|
-
|
|
34
|
-
the
|
|
32
|
+
A directly launched `node scripts/development/dev-launch.mjs` or
|
|
33
|
+
`node scripts/development/start-local.mjs` under Git Bash does not, and neither
|
|
34
|
+
does a directly launched `node …/pi/dist/cli.js`: the collapse belongs to the
|
|
35
|
+
launch, not to either application.
|
|
35
36
|
|
|
36
37
|
## Checking a terminal
|
|
37
38
|
|