Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
ce5f52b
πŸ“ Define interactive terminal grid architecture (#717)
taras Sep 2, 2026
3a87e87
✨ Describe terminal grids as executable document structure (#729)
taras Sep 2, 2026
cf6c7e6
πŸ“ Shorten the terminal-grid component descriptions (#729)
taras Sep 2, 2026
feb47d3
✨ Add the terminal provider boundary and pane authority (#730)
taras Sep 2, 2026
4ba3f06
✨ Run a terminal grid's panes concurrently through the provider (#730)
taras Sep 2, 2026
df61e96
✨ Run a document's terminal grid panes through the provider (#730)
taras Sep 2, 2026
8ab4952
♻️ Drop an unused parameter from the grid's pane work (#730)
taras Sep 2, 2026
c0f7e52
✨ Give terminal grids an authority boundary and durable pane children…
taras Sep 2, 2026
5ea1249
πŸ› Repair durableSpawn, and put the grid on it (#730)
taras Sep 2, 2026
64ee684
πŸ“ Decide the cancelled-child contract and TG17's replay boundary (#730)
taras Sep 2, 2026
b15d1e4
✨ Implement DEC-040, and complete TG15 and TG17 (#730)
taras Sep 2, 2026
6dde639
πŸ› Make the replay evidence deterministic, and pin DEC-040's boundarie…
taras Sep 2, 2026
0418d9c
♻️ Coordinate the DEC-040 rows by signal, not by duration (#730)
taras Sep 2, 2026
bb5f14b
πŸ› Observe every disposal surface, and make reader close cooperative (…
taras Sep 2, 2026
36206d5
πŸ“ Define reader-close cancellation commit boundary (#730)
taras Sep 2, 2026
6508ec2
✨ Implement the reader-close cancellation commit boundary (#730)
taras Sep 2, 2026
9ccfd29
♻️ Defer the grid owner's cancellation at the live close boundary (#730)
taras Sep 2, 2026
682402b
βœ… Count what TG19 proves: resources, records and the lease (#730)
taras Sep 2, 2026
4aade57
✨ Launch native Agent sessions in independent terminal panes (#731)
taras Sep 3, 2026
152135b
βœ… Complete #731's controlled integration evidence (#731)
taras Sep 3, 2026
ed64b57
♻️ Build the interrupted run's outcome with Err (#731)
taras Sep 3, 2026
d5dee3f
πŸ› Acknowledge session quiescence from the launch's own cleanup (#731)
taras Sep 3, 2026
27974eb
✨ Give the host a way to prove a terminal pane is free (#732)
taras Sep 3, 2026
d1a53d7
✨ Lay a tmux window out in the authored order (#732)
taras Sep 3, 2026
871a0e8
✨ Give a terminal pane a worker and a private channel (#732)
taras Sep 3, 2026
1420dd8
✨ Build the hidden tmux composite for a terminal grid (#732)
taras Sep 3, 2026
13a5458
πŸ› Narrow the visible client, and make teardown prove itself (#732)
taras Sep 3, 2026
091dceb
πŸ› Refuse when the visible client will not stop (#732)
taras Sep 3, 2026
8acedf1
✨ Install the tmux grid provider on the foreground hosts (#732)
taras Sep 3, 2026
d737899
πŸ“ Route pane-native launches through terminal composites (#732)
taras Sep 3, 2026
46567a7
✨ Route a pane's native launch through its own composite (#732)
taras Sep 3, 2026
935474b
✨ Complete the tmux terminal-grid provider (#732)
taras Sep 3, 2026
81b51c3
πŸ› Finish fail-closed observation, teardown, listeners and host eviden…
taras Sep 3, 2026
f5d45e2
πŸ› Finish listener ownership and freeze the combined teardown (#732)
taras Sep 3, 2026
ad4b95f
πŸ› Freeze the foreground-host boundary, and repair what it exposed (#732)
taras Sep 3, 2026
374fc4c
πŸ› Freeze the combined grid teardown, and finish close-request failure…
taras Sep 3, 2026
d725f54
πŸ› Keep the tmux grid suite off the runtimes that register no worker (…
taras Sep 3, 2026
38cdf40
πŸ“ Define terminal package boundary (#717)
taras Sep 4, 2026
5aad719
πŸ“ Remove unshipped terminal compatibility paths (#717)
taras Sep 4, 2026
5d308a5
♻️ Extract the terminal domain and its tmux adapter into packages (#717)
taras Sep 4, 2026
8d6de02
♻️ Split the terminal facets, narrow the tmux root, complete the lock…
taras Sep 5, 2026
8a30171
πŸ› Declare the pane wire format so the adapter can be published (#717)
taras Sep 5, 2026
25aa4fd
πŸ› Keep the hidden control protocol off the reader's terminal (#717)
taras Sep 5, 2026
83be4b2
πŸ› Suppress internal tmux stdio in the scope that owns each child (#717)
taras Sep 5, 2026
cfe2609
πŸ› Name the fixture entrypoints so the test runner does not load them …
taras Sep 5, 2026
1a5400d
πŸ› Keep an installer's linked copies out of the boundary walk (#717)
taras Sep 5, 2026
a73b2d6
πŸ› Give a pane's launched child the terminal it is drawing on (#717)
taras Sep 5, 2026
81c8a4d
πŸ›οΈ Scope native capability advertisement to proved builds
taras Sep 6, 2026
2672935
πŸ”’ Admit a native capability per proved build, not per adapter name
taras Sep 6, 2026
0e171c5
πŸ”’ Prove a launch's own teardown before releasing its session
taras Sep 6, 2026
0876896
πŸ›οΈ Admit native capabilities by observed protocol shape
taras Sep 6, 2026
cef72fd
πŸ›οΈ Admit a native capability by protocol and profile, not by release
taras Sep 6, 2026
bb275f8
πŸ”’ Admit a Claude operation by the value its option takes
taras Sep 6, 2026
3f614b4
πŸ”’ Recognize what a Claude help entry states, not what it mentions
taras Sep 6, 2026
2e27feb
πŸ—οΈ Continue client-native sessions across compatible releases
taras Sep 6, 2026
d74e090
πŸ”“ Continue a client-native session across compatible releases
taras Sep 6, 2026
d1be015
πŸ”’ Pin a V2 route's native protocol to its route contract (#717)
taras Sep 6, 2026
8a736ab
πŸ”’ Settle a client-native route's protocol before the race (#717)
taras Sep 6, 2026
6049184
πŸ—οΈ Compose Codex native launch with terminal grids
taras Sep 6, 2026
2ba2da8
πŸ› Align the extracted terminal package's @effectionx/node pin (#717)
taras Sep 7, 2026
1cc1dad
πŸ› Reconcile the terminal stack with main's renamed surfaces (#717)
taras Sep 7, 2026
44826a9
πŸ› Bind the terminal stack's event listeners to their owners (#717)
taras Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions .github/workflows/publish-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Validate the manifests declare this version
run: |
VERSION="${{ steps.resolve.outputs.value }}"
for f in packages/durable-streams/deno.json packages/runtime/deno.json packages/core/deno.json packages/acp/deno.json packages/testing/deno.json packages/test-agent/deno.json packages/web/deno.json packages/workflow/deno.json packages/cli/deno.json packages/code-review-agent/deno.json; do
for f in packages/durable-streams/deno.json packages/runtime/deno.json packages/terminal/deno.json packages/core/deno.json packages/acp/deno.json packages/terminal-tmux/deno.json packages/testing/deno.json packages/test-agent/deno.json packages/web/deno.json packages/workflow/deno.json packages/cli/deno.json packages/code-review-agent/deno.json; do
declared="$(jq -r .version "$f")"
if [ "$declared" != "$VERSION" ]; then
echo "::error::$f declares $declared, not $VERSION β€” the tag does not match the manifests"
Expand Down Expand Up @@ -75,20 +75,34 @@ jobs:
package: packages/runtime
version: ${{ needs.version.outputs.value }}

terminal:
needs: [version, durable-streams]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/terminal
version: ${{ needs.version.outputs.value }}

core:
needs: [version, durable-streams, runtime]
needs: [version, durable-streams, runtime, terminal]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/core
version: ${{ needs.version.outputs.value }}

acp:
needs: [version, core, runtime]
needs: [version, core, runtime, terminal]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/acp
version: ${{ needs.version.outputs.value }}

terminal-tmux:
needs: [version, terminal]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/terminal-tmux
version: ${{ needs.version.outputs.value }}

testing:
needs: [version, core, durable-streams, runtime]
uses: ./.github/workflows/publish-one.yml
Expand All @@ -97,7 +111,7 @@ jobs:
version: ${{ needs.version.outputs.value }}

test-agent:
needs: [version, acp, core, durable-streams, runtime, testing]
needs: [version, acp, core, durable-streams, runtime, terminal, testing]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/test-agent
Expand All @@ -118,7 +132,7 @@ jobs:
version: ${{ needs.version.outputs.value }}

cli:
needs: [version, acp, core, durable-streams, runtime, test-agent, testing, web, workflow]
needs: [version, acp, core, durable-streams, runtime, terminal, terminal-tmux, test-agent, testing, web, workflow]
uses: ./.github/workflows/publish-one.yml
with:
package: packages/cli
Expand Down
530 changes: 522 additions & 8 deletions architecture.md

Large diffs are not rendered by default.

46 changes: 45 additions & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions packages/acp/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,35 @@ export {
ADVERTISED_NATIVE_LAUNCH,
knownNativeAdapters,
nativeAdapterFor,
nativeCapabilityPolicy,
} from "./src/native-launch.ts";
export { allocatesIdentity } from "./src/native-launch.ts";
export type {
ClientAllocatedAdapter,
NativeAdapter,
NativeBinding,
NativeCapabilityProbe,
ProbedNativeCapabilities,
ProviderReturnedAdapter,
} from "./src/native-launch.ts";

/**
* Which protocol shapes and machines a native capability is admitted on.
*
* Public because the host is what states them: it supplies its own OS and
* architecture beside the coordinator and the observer, and shared provider
* code must not detect either for itself.
*/
export { admitsNativeCapability } from "./src/native-capability.ts";
export type {
NativeCapability,
NativeCapabilityAdmission,
NativeCapabilityHost,
NativeCapabilityPolicy,
ObservedNativeCapability,
ProvedNativeCapability,
} from "./src/native-capability.ts";

/**
* ACPX's own runtime types.
*
Expand Down
1 change: 1 addition & 0 deletions packages/acp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@agentclientprotocol/sdk": "1.3.0",
"@executablemd/core": "workspace:*",
"@executablemd/runtime": "workspace:*",
"@executablemd/terminal": "workspace:*",
"acpx": "0.12.0",
"effection": "4.1.0"
}
Expand Down
98 changes: 98 additions & 0 deletions packages/acp/src/native-capability.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* What one real-CLI proof admits, and nothing wider (specs/decisions.md
* DEC-017).
*
* An Agent name says which command shape to consider. It does not say that the
* thing found under that name works: a proof ran against one implementation's
* protocol, on one operating system, on one architecture, and every other
* protocol and machine is a claim nobody made. So admission is stated as
* profiles, and a profile is the whole tuple β€”
*
* adapter protocol + capability + observed probe profile + host OS + host
* architecture
*
* β€” matched exactly. Nothing here is a version. A version says which release
* was installed, not what it can do, and admitting one would make a routine
* upgrade disable every new session while telling nobody why. What is matched
* instead is the adapter's stable protocol identifier and what its own
* side-effect-free probe recognized in the exact executable that was hashed.
*
* The host pair is supplied rather than read. Which machine this is is a fact
* the trusted host has and shared provider code must not go looking for: a
* provider that detected its own runtime would answer the admission question
* with the thing being asked about.
*/

/**
* Which behavior a proof established.
*
* Two, not one, because they are proved separately: handing a session to a
* native UI and later joining that same conversation through ACP are different
* things that can be true independently.
*/
export type NativeCapability = "native-launch" | "client-native-attachment";

/** The machine a host is actually running on, as that host states it. */
export interface NativeCapabilityHost {
readonly platform: string;
readonly architecture: string;
}

/** One capability, proved for one protocol shape on one exact machine. */
export interface NativeCapabilityAdmission {
/**
* The adapter implementation whose protocol was proved.
*
* Deliberately not the Agent registry name and not the launcher command:
* either can be pointed at something else, and neither says which protocol
* the thing behind it speaks.
*/
readonly adapterProtocol: string;
readonly capability: NativeCapability;
/** The probe whose recognized shape this admission was proved against. */
readonly probeProfile: string;
readonly platform: string;
readonly architecture: string;
}

/** Everything a host admits, beside the machine it admits it on. */
export interface NativeCapabilityPolicy {
readonly host: NativeCapabilityHost;
readonly admissions: readonly NativeCapabilityAdmission[];
}

/** What an adapter carries about its own proofs, before a host names a machine. */
export type ProvedNativeCapability = Omit<NativeCapabilityAdmission, "adapterProtocol">;

/** The live capability an observation offers for admission. */
export interface ObservedNativeCapability {
readonly adapterProtocol: string;
readonly capability: NativeCapability;
readonly probeProfile: string;
}

/**
* Whether this host admits what was actually observed.
*
* The host's own OS and architecture are what an admitted profile is compared
* against, so a profile proved elsewhere cannot admit anything here. An absent
* policy admits nothing: a host that states no proof has none, and treating
* silence as permission is the failure this whole tuple exists to prevent.
*/
export function admitsNativeCapability(
policy: NativeCapabilityPolicy | undefined,
observed: ObservedNativeCapability,
): boolean {
if (policy === undefined) {
return false;
}
const { platform, architecture } = policy.host;
return policy.admissions.some(
(admission) =>
admission.adapterProtocol === observed.adapterProtocol &&
admission.capability === observed.capability &&
admission.probeProfile === observed.probeProfile &&
admission.platform === platform &&
admission.architecture === architecture,
);
}
Loading
Loading