@astrosheep/keiyaku 4.6.7 → 4.6.8
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 +6 -2
- package/build/plugins/pi/keiyaku.ts +0 -5
- package/build/src/akuma/akuma-call.d.ts +2 -0
- package/build/src/akuma/akuma-call.js +8 -2
- package/build/src/akuma/akuma-instance.d.ts +12 -1
- package/build/src/akuma/akuma-instance.js +27 -7
- package/build/src/akuma/akuma-observe.js +2 -0
- package/build/src/akuma/akuma-owner.d.ts +3 -0
- package/build/src/akuma/akuma-owner.js +4 -0
- package/build/src/akuma/akuma.d.ts +35 -5
- package/build/src/akuma/akuma.js +8 -10
- package/build/src/akuma/archetype.d.ts +7 -15
- package/build/src/akuma/archetype.js +36 -35
- package/build/src/akuma/body.d.ts +5 -3
- package/build/src/akuma/body.js +29 -7
- package/build/src/akuma/call-request.d.ts +18 -10
- package/build/src/akuma/call-request.js +10 -3
- package/build/src/akuma/caller.d.ts +39 -0
- package/build/src/akuma/caller.js +36 -0
- package/build/src/akuma/dispatch-association.d.ts +0 -1
- package/build/src/akuma/dispatch-association.js +0 -3
- package/build/src/akuma/heart/facts.d.ts +16 -12
- package/build/src/akuma/heart/facts.js +8 -0
- package/build/src/akuma/heart/index.d.ts +2 -7
- package/build/src/akuma/heart/index.js +3 -17
- package/build/src/akuma/heart/rows.d.ts +3 -3
- package/build/src/akuma/heart/soul.d.ts +1 -1
- package/build/src/akuma/heart/soul.js +5 -24
- package/build/src/akuma/heart/storage.d.ts +5 -0
- package/build/src/akuma/heart/storage.js +7 -3
- package/build/src/akuma/identity.d.ts +0 -1
- package/build/src/akuma/identity.js +2 -5
- package/build/src/akuma/index.d.ts +5 -2
- package/build/src/akuma/index.js +1 -0
- package/build/src/akuma/nuke.js +6 -28
- package/build/src/akuma/projection.d.ts +0 -11
- package/build/src/akuma/provider-recipe.d.ts +7 -6
- package/build/src/akuma/provider-recipe.js +1 -1
- package/build/src/akuma/provider.d.ts +6 -10
- package/build/src/akuma/provider.js +6 -7
- package/build/src/akuma/providers/acp/events.js +5 -18
- package/build/src/akuma/providers/acp/index.js +2 -3
- package/build/src/akuma/providers/claude/events.js +35 -60
- package/build/src/akuma/providers/claude/index.d.ts +2 -2
- package/build/src/akuma/providers/claude/index.js +2 -3
- package/build/src/akuma/providers/codex-app-server/index.js +2 -2
- package/build/src/akuma/providers/decode.d.ts +25 -0
- package/build/src/akuma/providers/decode.js +44 -0
- package/build/src/akuma/providers/execution-environment.d.ts +2 -1
- package/build/src/akuma/providers/execution-environment.js +3 -0
- package/build/src/akuma/providers/grok-build/index.js +6 -22
- package/build/src/akuma/providers/index.js +2 -0
- package/build/src/akuma/providers/lifecycle.d.ts +9 -0
- package/build/src/akuma/providers/lifecycle.js +10 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
- package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
- package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
- package/build/src/akuma/providers/paseo/events.d.ts +25 -0
- package/build/src/akuma/providers/paseo/events.js +157 -0
- package/build/src/akuma/providers/paseo/index.d.ts +9 -0
- package/build/src/akuma/providers/paseo/index.js +353 -0
- package/build/src/akuma/providers/pi/events.js +5 -15
- package/build/src/akuma/publication.d.ts +2 -0
- package/build/src/akuma/publication.js +5 -0
- package/build/src/akuma/request-lifecycle.d.ts +3 -0
- package/build/src/akuma/request-lifecycle.js +25 -4
- package/build/src/akuma/requests.d.ts +3 -1
- package/build/src/akuma/requests.js +32 -0
- package/build/src/akuma/selection-observation.d.ts +72 -2
- package/build/src/akuma/selection-observation.js +0 -6
- package/build/src/akuma/turn-drive.js +2 -5
- package/build/src/cli/akuma-caller.d.ts +3 -0
- package/build/src/cli/akuma-caller.js +21 -0
- package/build/src/cli/commands/akuma-grammar.js +7 -12
- package/build/src/cli/commands/akuma.js +12 -4
- package/build/src/cli/commands/contract-grammar.d.ts +2 -1
- package/build/src/cli/commands/contract-grammar.js +13 -15
- package/build/src/cli/commands/contract-help.d.ts +2 -1
- package/build/src/cli/commands/contract-help.js +31 -1
- package/build/src/cli/commands/contract.js +24 -53
- package/build/src/cli/commands/task.js +18 -35
- package/build/src/cli/parse.d.ts +2 -2
- package/build/src/cli/render/catalog.d.ts +2 -5
- package/build/src/cli/render/contract-history.js +3 -6
- package/build/src/cli/render/contract.js +15 -50
- package/build/src/cli/render/receipt.js +3 -10
- package/build/src/cli/render/task.d.ts +4 -6
- package/build/src/cli/render/task.js +9 -26
- package/build/src/cli/runtime.d.ts +1 -1
- package/build/src/cli/runtime.js +11 -17
- package/build/src/cli/selectors.d.ts +3 -6
- package/build/src/cli/selectors.js +22 -53
- package/build/src/dispatch/index.d.ts +3 -3
- package/build/src/dispatch/index.js +1 -2
- package/build/src/git/observe.d.ts +6 -2
- package/build/src/git/observe.js +6 -2
- package/build/src/index.d.ts +6 -6
- package/build/src/index.js +2 -2
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +21 -6
- package/build/src/library/address.js +2 -4
- package/build/src/library/akuma-creation.d.ts +5 -1
- package/build/src/library/akuma-creation.js +27 -47
- package/build/src/library/akumas.d.ts +5 -4
- package/build/src/library/akumas.js +13 -9
- package/build/src/library/bind.d.ts +14 -14
- package/build/src/library/bind.js +11 -7
- package/build/src/library/contract-address.d.ts +9 -0
- package/build/src/library/contract-address.js +71 -0
- package/build/src/library/contract-composition.d.ts +4 -7
- package/build/src/library/contract-composition.js +6 -18
- package/build/src/library/contract-creation.d.ts +3 -5
- package/build/src/library/contract-creation.js +19 -17
- package/build/src/library/contract-execution.js +18 -23
- package/build/src/library/contract-outcomes.d.ts +2 -14
- package/build/src/library/contract-outcomes.js +2 -13
- package/build/src/library/contract-types.d.ts +36 -2
- package/build/src/library/delivery.d.ts +0 -2
- package/build/src/library/delivery.js +2 -5
- package/build/src/library/keiyaku.d.ts +0 -5
- package/build/src/library/keiyaku.js +6 -12
- package/build/src/library/outcome.d.ts +500 -499
- package/build/src/library/outcome.js +10 -0
- package/build/src/library/reconcile.js +8 -16
- package/build/src/library/refusal.d.ts +2 -2
- package/build/src/library/repo.d.ts +3 -2
- package/build/src/library/repo.js +10 -5
- package/build/src/library/selection.d.ts +4 -4
- package/build/src/library/selection.js +12 -12
- package/build/src/plugin/akuma-signals.d.ts +2 -0
- package/build/src/plugin/akuma-signals.js +4 -0
- package/build/src/plugin/public.d.ts +27 -2
- package/build/src/plugin/runtime.js +2 -2
- package/build/src/protocol/amend.js +3 -2
- package/build/src/protocol/attempt.js +3 -8
- package/build/src/protocol/bind.d.ts +2 -2
- package/build/src/protocol/bind.js +1 -1
- package/build/src/protocol/deliver.js +3 -3
- package/build/src/protocol/operations.d.ts +1 -3
- package/build/src/protocol/operations.js +0 -8
- package/build/src/protocol/outcome.d.ts +1 -2
- package/build/src/protocol/outcome.js +1 -13
- package/build/src/protocol/placement.js +3 -10
- package/build/src/protocol/read/status.js +31 -70
- package/build/src/protocol/reintegrate.js +3 -10
- package/build/src/protocol/review.js +3 -3
- package/build/src/protocol/run.d.ts +5 -1
- package/build/src/protocol/run.js +3 -3
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +8 -4
- package/plugins/pi/keiyaku.ts +57 -0
- package/skills/keiyaku/SKILL.md +44 -0
- package/skills/keiyaku-akuma/SKILL.md +130 -0
- package/skills/keiyaku-akuma/references/automation.md +269 -0
- package/skills/keiyaku-babysit/SKILL.md +65 -0
- package/skills/keiyaku-bind/SKILL.md +216 -0
- package/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/skills/keiyaku-task/SKILL.md +104 -0
- package/skills/keiyaku-workflow/SKILL.md +129 -0
- package/build/src/cli/commands/amend.d.ts +0 -12
- package/build/src/cli/commands/amend.js +0 -10
- package/build/src/cli/commands/bind.d.ts +0 -11
- package/build/src/cli/commands/bind.js +0 -23
- package/build/src/dispatch/association.d.ts +0 -1
- package/build/src/dispatch/association.js +0 -1
|
@@ -57,9 +57,6 @@ function appointedWorkspace(repository, register, state) {
|
|
|
57
57
|
? undefined
|
|
58
58
|
: { contractId: state.id, place: appointed.place, workspace: worktreePath(repository, appointed.place) };
|
|
59
59
|
}
|
|
60
|
-
async function readSelectedHandoffs(observation, workspaces) {
|
|
61
|
-
return await readConflictHandoffs(observation.repository, observation.readBlobs, workspaces.flatMap((workspace) => (workspace === undefined ? [] : [workspace])));
|
|
62
|
-
}
|
|
63
60
|
async function managedWorkspaceFacts(repository, state, appointed, targetObservation, handoff) {
|
|
64
61
|
if (appointed === undefined) {
|
|
65
62
|
return {
|
|
@@ -101,10 +98,10 @@ function afterEdges(state, endpoints) {
|
|
|
101
98
|
endpoint: afterEndpoint(endpoints.get(contractId)),
|
|
102
99
|
}));
|
|
103
100
|
}
|
|
104
|
-
function reverseDependents(id,
|
|
105
|
-
return
|
|
106
|
-
.filter((
|
|
107
|
-
.map((
|
|
101
|
+
function reverseDependents(id, states) {
|
|
102
|
+
return states
|
|
103
|
+
.filter(({ state }) => state.terminal === null && state.terms.after.includes(id))
|
|
104
|
+
.map(({ state }) => ({ contractId: state.id, phase: phaseFor(state) }))
|
|
108
105
|
.sort((left, right) => left.contractId.localeCompare(right.contractId));
|
|
109
106
|
}
|
|
110
107
|
async function rowFor(input) {
|
|
@@ -148,6 +145,25 @@ async function afterEndpointMap(observation, known, ids) {
|
|
|
148
145
|
const extra = await observeContractsForAdmissionInObservationAt(observation, missing);
|
|
149
146
|
return new Map([...known, ...[...extra.journals].map(([id, record]) => [id, record.state])]);
|
|
150
147
|
}
|
|
148
|
+
async function hydrateRows(observation, states, endpoints, dependentStates = []) {
|
|
149
|
+
const register = await readPlaceRegister(observation.repository);
|
|
150
|
+
const selected = states.map((value) => ({
|
|
151
|
+
...value,
|
|
152
|
+
workspace: appointedWorkspace(observation.repository, register, value.state),
|
|
153
|
+
}));
|
|
154
|
+
const handoffs = await readConflictHandoffs(observation.repository, observation.readBlobs, selected.flatMap(({ workspace }) => (workspace === undefined ? [] : [workspace])));
|
|
155
|
+
return await Promise.all(selected.map(async ({ state, bindAt, lastJournalAt, workspace }) => await rowFor({
|
|
156
|
+
repository: observation.repository,
|
|
157
|
+
state,
|
|
158
|
+
bindAt,
|
|
159
|
+
lastJournalAt,
|
|
160
|
+
targetObservation: await observeDeliveryTargetAt(observation, state),
|
|
161
|
+
workspace,
|
|
162
|
+
handoff: handoffs.get(state.id),
|
|
163
|
+
after: afterEdges(state, endpoints),
|
|
164
|
+
dependents: reverseDependents(state.id, dependentStates),
|
|
165
|
+
})));
|
|
166
|
+
}
|
|
151
167
|
/** Build the Contract board from one immutable git observation. */
|
|
152
168
|
export async function readContractBoard(observation, include) {
|
|
153
169
|
const observedAt = new Date().toISOString();
|
|
@@ -165,29 +181,8 @@ export async function readContractBoard(observation, include) {
|
|
|
165
181
|
endpoints = new Map(await afterEndpointMap(observation, endpoints, record.state.terms.after));
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
? []
|
|
171
|
-
: [
|
|
172
|
-
{
|
|
173
|
-
...value,
|
|
174
|
-
state: value.state,
|
|
175
|
-
workspace: appointedWorkspace(observation.repository, register, value.state),
|
|
176
|
-
},
|
|
177
|
-
]);
|
|
178
|
-
const handoffs = await readSelectedHandoffs(observation, selected.map(({ workspace }) => workspace));
|
|
179
|
-
const projected = await Promise.all(selected.map(async ({ state, entries, workspace }) => await rowFor({
|
|
180
|
-
repository: observation.repository,
|
|
181
|
-
state,
|
|
182
|
-
bindAt: entries[0].at,
|
|
183
|
-
lastJournalAt: lastJournalAtFor(entries),
|
|
184
|
-
targetObservation: await observeDeliveryTargetAt(observation, state),
|
|
185
|
-
workspace,
|
|
186
|
-
handoff: handoffs.get(state.id),
|
|
187
|
-
after: afterEdges(state, endpoints),
|
|
188
|
-
dependents: [],
|
|
189
|
-
})));
|
|
190
|
-
const rows = projected.map((row) => ({ ...row, dependents: reverseDependents(row.id, projected) }));
|
|
184
|
+
const selected = selectedContractStates(contracts);
|
|
185
|
+
const rows = await hydrateRows(observation, selected, endpoints, selected);
|
|
191
186
|
return {
|
|
192
187
|
root: observation.repository.primaryWorktree,
|
|
193
188
|
state: observed.snapshot,
|
|
@@ -199,8 +194,8 @@ function compareRecentContracts(left, right) {
|
|
|
199
194
|
return (right.lastJournalAt.localeCompare(left.lastJournalAt) ||
|
|
200
195
|
Buffer.compare(Buffer.from(left.state.id), Buffer.from(right.state.id)));
|
|
201
196
|
}
|
|
202
|
-
function
|
|
203
|
-
return [...contracts.values()].flatMap((record) => record.state === null
|
|
197
|
+
function selectedContractStates(contracts) {
|
|
198
|
+
return [...contracts.values()].flatMap((record) => record.state === null
|
|
204
199
|
? []
|
|
205
200
|
: [
|
|
206
201
|
{
|
|
@@ -210,37 +205,15 @@ function activeContractStates(contracts) {
|
|
|
210
205
|
},
|
|
211
206
|
]);
|
|
212
207
|
}
|
|
213
|
-
function reverseDependentsFromStates(id, states) {
|
|
214
|
-
return states
|
|
215
|
-
.filter(({ state }) => state.terms.after.includes(id))
|
|
216
|
-
.map(({ state }) => ({ contractId: state.id, phase: phaseFor(state) }))
|
|
217
|
-
.sort((left, right) => left.contractId.localeCompare(right.contractId));
|
|
218
|
-
}
|
|
219
208
|
/** Observe a bounded recent active Contract catalogue from one immutable git observation. */
|
|
220
209
|
export async function readContractCatalogue(observation, limit) {
|
|
221
210
|
const observedAt = new Date().toISOString();
|
|
222
211
|
const observed = await observeActiveContractWorld(observation);
|
|
223
|
-
const active =
|
|
212
|
+
const active = selectedContractStates(observed.contracts).filter(({ state }) => state.terminal === null);
|
|
224
213
|
const selected = projectBoundedList([...active].sort(compareRecentContracts), limit);
|
|
225
214
|
const afterIds = selected.rows.flatMap(({ state }) => state.terms.after);
|
|
226
215
|
const endpoints = await afterEndpointMap(observation, new Map(observed.eligibility), afterIds);
|
|
227
|
-
const
|
|
228
|
-
const selectedWorkspaces = selected.rows.map((value) => ({
|
|
229
|
-
...value,
|
|
230
|
-
workspace: appointedWorkspace(observation.repository, register, value.state),
|
|
231
|
-
}));
|
|
232
|
-
const handoffs = await readSelectedHandoffs(observation, selectedWorkspaces.map(({ workspace }) => workspace));
|
|
233
|
-
const rows = await Promise.all(selectedWorkspaces.map(async ({ state, bindAt, lastJournalAt, workspace }) => await rowFor({
|
|
234
|
-
repository: observation.repository,
|
|
235
|
-
state,
|
|
236
|
-
bindAt,
|
|
237
|
-
lastJournalAt,
|
|
238
|
-
targetObservation: await observeDeliveryTargetAt(observation, state),
|
|
239
|
-
workspace,
|
|
240
|
-
handoff: handoffs.get(state.id),
|
|
241
|
-
after: afterEdges(state, endpoints),
|
|
242
|
-
dependents: reverseDependentsFromStates(state.id, active),
|
|
243
|
-
})));
|
|
216
|
+
const rows = await hydrateRows(observation, selected.rows, endpoints, active);
|
|
244
217
|
return {
|
|
245
218
|
root: observation.repository.primaryWorktree,
|
|
246
219
|
state: observed.snapshot,
|
|
@@ -270,22 +243,10 @@ export async function readContractObservation(observation, id) {
|
|
|
270
243
|
if (state === null)
|
|
271
244
|
return { kind: "missing", id };
|
|
272
245
|
const endpoints = await afterEndpointMap(observation, new Map([[id, state]]), state.terms.after);
|
|
273
|
-
const
|
|
274
|
-
const workspace = appointedWorkspace(observation.repository, register, state);
|
|
275
|
-
const handoffs = await readSelectedHandoffs(observation, [workspace]);
|
|
246
|
+
const rows = await hydrateRows(observation, selectedContractStates(observed.journals), endpoints);
|
|
276
247
|
return {
|
|
277
248
|
kind: "present",
|
|
278
|
-
row:
|
|
279
|
-
repository: observation.repository,
|
|
280
|
-
state,
|
|
281
|
-
bindAt: record.entries[0].at,
|
|
282
|
-
lastJournalAt: lastJournalAtFor(record.entries),
|
|
283
|
-
targetObservation: await observeDeliveryTargetAt(observation, state),
|
|
284
|
-
workspace,
|
|
285
|
-
handoff: handoffs.get(state.id),
|
|
286
|
-
after: afterEdges(state, endpoints),
|
|
287
|
-
dependents: [],
|
|
288
|
-
}),
|
|
249
|
+
row: rows[0],
|
|
289
250
|
};
|
|
290
251
|
}
|
|
291
252
|
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
@@ -2,18 +2,11 @@ import { contractState } from "../core/facts/observation.js";
|
|
|
2
2
|
import { decideReintegrate } from "../core/verbs/reintegrate.js";
|
|
3
3
|
import { materializeReintegrationSnapshot, persistedTender, planIntegration, reusableIntegrationSnapshot, } from "../git/integration.js";
|
|
4
4
|
import { observeContractsForAdmissionAt } from "../git/observe.js";
|
|
5
|
-
import {
|
|
5
|
+
import { withPrivateStatePublicationSeat } from "../git/private-state-seat.js";
|
|
6
6
|
import { admitDecidedOffer, mintAttempts } from "./attempt.js";
|
|
7
7
|
import { recordedIntegrationSnapshots, timestamp } from "./operations.js";
|
|
8
|
-
import { externalPreparation, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
|
|
8
|
+
import { externalPreparation, protocolSeatClose, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
|
|
9
9
|
import { runUnderTargetPlacementFence } from "./placement.js";
|
|
10
|
-
function reintegrationResultWithSeatClose(outcome) {
|
|
11
|
-
return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
|
|
12
|
-
if (value.kind !== "accepted")
|
|
13
|
-
throw new Error(closeLag.diagnostic);
|
|
14
|
-
return { ...value, seatClose: appendPrivateStateSeatClose(value.seatClose, closeLag) };
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
10
|
/** Plan and materialize the target-specific reintegration artifacts outside the publication seat. */
|
|
18
11
|
async function prepareExternalReintegration(input) {
|
|
19
12
|
return await externalPreparation({ ...input, scope: input.repository }, (observation, state) => planReintegrationArtifacts(input, state, recordedIntegrationSnapshots(observation.journals.get(state.id)?.entries ?? [])));
|
|
@@ -54,7 +47,7 @@ async function runReintegration(input) {
|
|
|
54
47
|
for (let index = 0; index < attempts.length; index += 1) {
|
|
55
48
|
const attempt = attempts[index];
|
|
56
49
|
const external = await prepareExternalReintegration(input);
|
|
57
|
-
const result =
|
|
50
|
+
const result = protocolSeatClose(await withPrivateStatePublicationSeat(input.repository, async (seat) => {
|
|
58
51
|
const observation = await observeContractsForAdmissionAt(input.repository, input.channel, [input.contractId]);
|
|
59
52
|
const assembled = assembleReintegrationAttempt(input, observation, external);
|
|
60
53
|
if (assembled.kind === "stale")
|
|
@@ -4,14 +4,14 @@ import { worktreeChangeId } from "../git/integration.js";
|
|
|
4
4
|
import { captureTender, dirtyTenderDelta, dirtyTenderRefusal } from "../git/tender.js";
|
|
5
5
|
import { observeContractsForAdmissionAt } from "../git/observe.js";
|
|
6
6
|
import { unmergedWorkspacePaths, worktreePath } from "../git/workspace.js";
|
|
7
|
-
import { externalPreparation, privateStateSeatAttempt, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
|
|
7
|
+
import { externalPreparation, privateStateSeatAttempt, protocolSeatClose, runBoundedAttempts, sameWorktreeWitness, STALE_PRIVATE_STATE_PREPARATION, } from "./run.js";
|
|
8
8
|
import { dependencyKeySet } from "../core/subject.js";
|
|
9
9
|
import { contractState } from "../core/facts/observation.js";
|
|
10
10
|
import { gate } from "../core/facts/types.js";
|
|
11
11
|
import { decideAttestation } from "../core/verbs/attestation.js";
|
|
12
12
|
import { admitDecidedOffer, mintAttempts } from "./attempt.js";
|
|
13
13
|
import { appointmentFor, readPlaceRegister } from "../workspace-place.js";
|
|
14
|
-
import {
|
|
14
|
+
import { timestamp } from "./operations.js";
|
|
15
15
|
const REVIEWED = gate("reviewed");
|
|
16
16
|
const reviewWorkspaceEvidenceSchema = workspaceDirtyDeltaSchema
|
|
17
17
|
.extend({ unmergedPaths: z.array(z.string().refine((value) => value.trim() !== "")).readonly() })
|
|
@@ -153,7 +153,7 @@ async function reviewAttempt(input, attempt) {
|
|
|
153
153
|
if (assembled.kind === "stale")
|
|
154
154
|
return STALE_PRIVATE_STATE_PREPARATION;
|
|
155
155
|
return await decideAndAdmitReview(input, attempt, seat, observation, assembled);
|
|
156
|
-
},
|
|
156
|
+
}, protocolSeatClose);
|
|
157
157
|
}
|
|
158
158
|
export async function admitReviewOperation(input) {
|
|
159
159
|
const result = await runBoundedAttempts(mintAttempts({ entryCount: 1 }), (attempt) => reviewAttempt(input, attempt));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ProtocolProgress } from "./progress.js";
|
|
3
3
|
import { type GitDecisionObservation } from "../git/observe.js";
|
|
4
|
-
import { type PrivateStatePublicationSeat, type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
|
|
4
|
+
import { type PrivateStatePublicationSeat, type PrivateStateSeatCloseLag, type PrivateStateSeatOutcome } from "../git/private-state-seat.js";
|
|
5
5
|
import type { GitDecodeChannel, GitTreeSelection } from "../git/read-observation.js";
|
|
6
6
|
import type { GitRepository } from "../git/process.js";
|
|
7
7
|
import { type GitRefAssertion } from "../git/repository.js";
|
|
@@ -177,6 +177,10 @@ export declare function externalPreparation<Artifacts>(input: Readonly<{
|
|
|
177
177
|
artifacts: Artifacts;
|
|
178
178
|
}>>;
|
|
179
179
|
export declare function privateStateSeatAttempt<T>(repository: GitRepository, action: (seat: PrivateStatePublicationSeat) => Promise<T>, wrap: (outcome: PrivateStateSeatOutcome<T>) => T): Promise<T | AttemptTerminal>;
|
|
180
|
+
export declare function protocolSeatClose<T extends Readonly<{
|
|
181
|
+
kind: string;
|
|
182
|
+
seatClose?: readonly PrivateStateSeatCloseLag[];
|
|
183
|
+
}>>(outcome: PrivateStateSeatOutcome<T>): T;
|
|
180
184
|
/** Form one decided offer without admitting or reinterpreting it. */
|
|
181
185
|
export declare function prepareProtocolAttempt<Input extends Readonly<{
|
|
182
186
|
contractId: ContractId;
|
|
@@ -122,7 +122,7 @@ async function admitDecidedProtocolOffer(admission, primaryContract, seat, decis
|
|
|
122
122
|
assertions: decided.assertions,
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
|
-
function
|
|
125
|
+
export function protocolSeatClose(outcome) {
|
|
126
126
|
return mergePrivateStateSeatClose(outcome, (value, closeLag) => {
|
|
127
127
|
if (value.kind !== "accepted")
|
|
128
128
|
throw new Error(closeLag.diagnostic);
|
|
@@ -137,7 +137,7 @@ async function runDirectProtocolAttempt(input, attempt) {
|
|
|
137
137
|
input: input.input,
|
|
138
138
|
assertions: [],
|
|
139
139
|
});
|
|
140
|
-
},
|
|
140
|
+
}, protocolSeatClose);
|
|
141
141
|
}
|
|
142
142
|
/**
|
|
143
143
|
* One full attempt: repeatable preparation outside custody, then a single in-custody cycle of
|
|
@@ -160,7 +160,7 @@ async function runSplitProtocolAttempt(input, attempt) {
|
|
|
160
160
|
input: assembled.input,
|
|
161
161
|
assertions,
|
|
162
162
|
});
|
|
163
|
-
},
|
|
163
|
+
}, protocolSeatClose);
|
|
164
164
|
}
|
|
165
165
|
/** Form one decided offer without admitting or reinterpreting it. */
|
|
166
166
|
export async function prepareProtocolAttempt(input, baseAttempt) {
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrosheep/keiyaku",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.8",
|
|
4
4
|
"workspaces": [
|
|
5
5
|
"plugins/square"
|
|
6
6
|
],
|
|
7
7
|
"files": [
|
|
8
|
-
"build"
|
|
8
|
+
"build",
|
|
9
|
+
"plugins/pi",
|
|
10
|
+
"skills"
|
|
9
11
|
],
|
|
10
12
|
"main": "./build/src/index.js",
|
|
11
13
|
"types": "./build/src/index.d.ts",
|
|
@@ -75,6 +77,8 @@
|
|
|
75
77
|
"@anthropic-ai/claude-agent-sdk": "^0.3.226",
|
|
76
78
|
"@astrosheep/keiyaku-plugin-square": "0.1.8",
|
|
77
79
|
"@astrosheep/square": "^0.3.70",
|
|
80
|
+
"@getpaseo/client": "0.11.2",
|
|
81
|
+
"@getpaseo/protocol": "0.11.2",
|
|
78
82
|
"@opencode-ai/sdk": "1.18.3",
|
|
79
83
|
"cross-spawn": "^7.0.6",
|
|
80
84
|
"diff": "^8.0.4",
|
|
@@ -91,10 +95,10 @@
|
|
|
91
95
|
],
|
|
92
96
|
"pi": {
|
|
93
97
|
"extensions": [
|
|
94
|
-
"./
|
|
98
|
+
"./plugins/pi/keiyaku.ts"
|
|
95
99
|
],
|
|
96
100
|
"skills": [
|
|
97
|
-
"./
|
|
101
|
+
"./skills"
|
|
98
102
|
]
|
|
99
103
|
},
|
|
100
104
|
"author": "",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
type ExecResult = Readonly<{ stdout: string; stderr: string; code: number }>;
|
|
4
|
+
|
|
5
|
+
async function runStatus(pi: ExtensionAPI): Promise<ExecResult> {
|
|
6
|
+
return await pi.exec("keiyaku", ["status"]);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function lineForWidth(value: string, width: number): string {
|
|
10
|
+
const clean = value.replaceAll(/[\u0000-\u001f\u007f]/gu, " ");
|
|
11
|
+
return clean.length <= width ? clean : `${clean.slice(0, Math.max(0, width - 1))}…`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function overlay(lines: readonly string[], theme: Theme, done: () => void) {
|
|
15
|
+
return {
|
|
16
|
+
invalidate(): void {},
|
|
17
|
+
handleInput(data: string): void {
|
|
18
|
+
if (data === "\u001b" || data === "q" || data === "Q" || data === "\r") done();
|
|
19
|
+
},
|
|
20
|
+
render(width: number): string[] {
|
|
21
|
+
const inner = Math.max(1, Math.min(100, width - 2));
|
|
22
|
+
const border = theme.fg("border", "+");
|
|
23
|
+
const rule = theme.fg("border", "-".repeat(inner));
|
|
24
|
+
return [
|
|
25
|
+
`${border}${rule}${border}`,
|
|
26
|
+
`${theme.fg("border", "|")}${lineForWidth("Keiyaku", inner).padEnd(inner)}${theme.fg("border", "|")}`,
|
|
27
|
+
`${theme.fg("border", "|")}${" ".repeat(inner)}${theme.fg("border", "|")}`,
|
|
28
|
+
...lines.map(
|
|
29
|
+
(line) => `${theme.fg("border", "|")}${lineForWidth(line, inner).padEnd(inner)}${theme.fg("border", "|")}`,
|
|
30
|
+
),
|
|
31
|
+
`${theme.fg("border", "|")}${" ".repeat(inner)}${theme.fg("border", "|")}`,
|
|
32
|
+
`${theme.fg("border", "|")}${lineForWidth("esc/q/enter close", inner).padEnd(inner)}${theme.fg("border", "|")}`,
|
|
33
|
+
`${border}${rule}${border}`,
|
|
34
|
+
];
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default function keiyakuExtension(pi: ExtensionAPI): void {
|
|
40
|
+
pi.registerCommand("keiyaku", {
|
|
41
|
+
description: "Open the Kanshi world status",
|
|
42
|
+
handler: async (_args, ctx) => {
|
|
43
|
+
if (!ctx.hasUI) return;
|
|
44
|
+
let body: string[];
|
|
45
|
+
try {
|
|
46
|
+
const result = await runStatus(pi);
|
|
47
|
+
body = result.code === 0 ? result.stdout.trimEnd().split("\n") : [result.stderr.trim() || "status unavailable"];
|
|
48
|
+
} catch {
|
|
49
|
+
body = ["status unavailable"];
|
|
50
|
+
}
|
|
51
|
+
await ctx.ui.custom<void>((_tui, theme, _keybindings, done) => overlay(body, theme, done), {
|
|
52
|
+
overlay: true,
|
|
53
|
+
overlayOptions: { anchor: "center", width: 100, maxHeight: 40 },
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: keiyaku
|
|
3
|
+
description: >-
|
|
4
|
+
Keiyaku is a CLI that records plans, writes handoff terms for deliveries,
|
|
5
|
+
and calls delegates. Use this skill when you need to figure out which
|
|
6
|
+
Keiyaku skill or command to reach for.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Keiyaku
|
|
10
|
+
|
|
11
|
+
## Model
|
|
12
|
+
|
|
13
|
+
Keiyaku is three independent pillars, not a bundle: **Task** remembers plans
|
|
14
|
+
and dependencies, **Contract** makes acceptance standing and auditable,
|
|
15
|
+
**Akuma** invokes capability. Use any one alone; combine them only when the
|
|
16
|
+
work calls for it. Behind every Contract in flight there is one holder of its
|
|
17
|
+
fulfillment loop — whoever turns intent into commissions and returns into
|
|
18
|
+
decisions. The flagship holds it by default, and may hand a whole Contract's
|
|
19
|
+
loop to one Aku in a single commission; the harness serves both styles
|
|
20
|
+
equally. See `keiyaku-workflow` for the loop, `keiyaku-bind` for authoring,
|
|
21
|
+
`keiyaku-akuma` for invocation.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
keiyaku -C <repo> task add "title"
|
|
27
|
+
keiyaku -C <repo> task start <task-id>
|
|
28
|
+
keiyaku -C <repo> bind [--task <task-id>] -
|
|
29
|
+
keiyaku -C <repo> status
|
|
30
|
+
keiyaku -C <repo> deliver [<contract>|@<contract>]
|
|
31
|
+
keiyaku -C <repo> review [<contract>|@<contract>] --satisfied
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`-C` selects the invocation cwd and therefore the World. `--repo <path>` only
|
|
35
|
+
selects the Contract repository; it never retargets that World. `call
|
|
36
|
+
--workdir <path>` selects execution cwd (relative to the effective invocation
|
|
37
|
+
cwd). Without it, the call uses the invocation cwd; `--contract` associates a
|
|
38
|
+
Contract without selecting an execution directory.
|
|
39
|
+
|
|
40
|
+
`deliver`, `review`, and `audit` may take time after their leading admission.
|
|
41
|
+
Their witnessed progress is ephemeral stderr output; stdout remains one final
|
|
42
|
+
text or JSON result. Ctrl-C asks the owned operation to stop and waits for its
|
|
43
|
+
truthful final receipt, so it is not evidence that an already admitted action
|
|
44
|
+
was rolled back.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: keiyaku-akuma
|
|
3
|
+
description: >-
|
|
4
|
+
Use when the work involves Akuma or Aku, or when you want other hands on
|
|
5
|
+
it: delegating a job, or fanning out research, checks, or other parallel
|
|
6
|
+
work.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Keiyaku Akuma
|
|
10
|
+
|
|
11
|
+
Use Akumas to delegate work to another worker. `call` creates a new Akuma;
|
|
12
|
+
`tell` admits a Tell for an existing Akuma; `ask` admits one and observes its
|
|
13
|
+
exact answer. Keep the complete AkuId, such as `aku/worker/1234abcd`, when you
|
|
14
|
+
need to address the same worker later. An alias such as `@reviewer` is a
|
|
15
|
+
shorter, world-local name.
|
|
16
|
+
|
|
17
|
+
## Call a new Akuma
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
keiyaku call worker "Summarize the recent changes in src/cli"
|
|
21
|
+
keiyaku call worker --alias @reviewer --wait 10m - < brief.md
|
|
22
|
+
keiyaku call worker
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The prompt is optional for prompt-free birth. Otherwise it is the new Akuma's
|
|
26
|
+
first prompt: give it as one argument, or use `-` to read stdin, never both.
|
|
27
|
+
Calls are detached by default: they return the new identity after birth without
|
|
28
|
+
waiting for the first answer. Use explicit `--wait <duration>` when this
|
|
29
|
+
invocation should block while observing that initial work. `--wait` only bounds
|
|
30
|
+
this command; it never stops the Akuma. Read `call --help` for flag syntax,
|
|
31
|
+
defaults, and action vocabulary.
|
|
32
|
+
To hand a Contract role to an Akuma, use the grant table in `keiyaku-workflow`.
|
|
33
|
+
|
|
34
|
+
The selected Akuma name is a reusable worker configuration, not an individual.
|
|
35
|
+
Calling it again creates an independent Akuma. Use different names for
|
|
36
|
+
capabilities, not merely for parallelism.
|
|
37
|
+
|
|
38
|
+
## Commission Context
|
|
39
|
+
|
|
40
|
+
`--contract` only records the association. It does not tell the Akuma the
|
|
41
|
+
Contract or worktree. Put them in the prompt explicitly:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
keiyaku call worker --contract kei/add-rate-limit-a1b2 --workdir /path/to/worktree - <<'EOF'
|
|
45
|
+
Contract: kei/add-rate-limit-a1b2
|
|
46
|
+
Worktree: /path/to/worktree
|
|
47
|
+
This Arc: implement the limiter and its tests
|
|
48
|
+
EOF
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`--contract` does not choose a worktree. Use `--workdir <path>` when needed.
|
|
52
|
+
|
|
53
|
+
## Tell or ask an existing Akuma
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
keiyaku tell @reviewer "The candidate moved; re-examine the worktree"
|
|
57
|
+
keiyaku tell @reviewer --interrupt - < new-priority.md
|
|
58
|
+
keiyaku ask @reviewer --wait 10m "What is your verdict?"
|
|
59
|
+
keiyaku ask @reviewer --schema verdict.schema.json - < question.md
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`tell` admits the next instruction and returns its admission receipt; it does
|
|
63
|
+
not await an answer. `ask` admits a Tell and observes that exact answer,
|
|
64
|
+
unbounded unless `--wait` limits observation. Both require a prompt and accept
|
|
65
|
+
`--interrupt` to put down current work before admitting the new Tell. Schema
|
|
66
|
+
belongs only to `ask`; `tell --schema` and `tell --wait` refuse and point to
|
|
67
|
+
`ask`. A deadline never withdraws an admitted Tell. Read `tell --help` and
|
|
68
|
+
`ask --help` for the complete flag grammar.
|
|
69
|
+
|
|
70
|
+
## Observe work
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
keiyaku wait @deliverer @reviewer
|
|
74
|
+
keiyaku wait --all --timeout 30m @deliverer @reviewer
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use `wait` for one or more existing Akumas. The default is `--any`; use
|
|
78
|
+
`--all` for every selected Akuma. `--timeout` limits observation and does not
|
|
79
|
+
stop workers. A completed Akuma already counts, so repeating a wait can return
|
|
80
|
+
immediately. See `wait --help` for the complete grammar. Unlike `ask`, `wait`
|
|
81
|
+
observes existing Akuma-wide work, not the answer to a newly admitted Tell.
|
|
82
|
+
|
|
83
|
+
## Inspect and retrieve results
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
keiyaku status
|
|
87
|
+
keiyaku status @reviewer
|
|
88
|
+
keiyaku ls aku/
|
|
89
|
+
keiyaku ls "aku/*/*"
|
|
90
|
+
keiyaku history @reviewer --last
|
|
91
|
+
keiyaku history @reviewer --id turn/3
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`status` shows the roster or one Akuma's workdir and effective actions.
|
|
95
|
+
`ls aku/` shows callable names; `ls "aku/*/*"` shows born workers.
|
|
96
|
+
`history --last` reads the latest complete answer; `history --id` reads an
|
|
97
|
+
exact result named by status or wait. Use the complete AkuId when an alias may
|
|
98
|
+
move; see `history --help` for paging.
|
|
99
|
+
|
|
100
|
+
## Stop and branch
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
keiyaku kill @reviewer
|
|
104
|
+
keiyaku fork @reviewer --at turn/3
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`kill` stops current work without admitting a Tell, deleting the Akuma, or
|
|
108
|
+
removing its history. `fork` creates a new Akuma from one exact retained
|
|
109
|
+
answered history point; the source is unchanged, and providers that cannot
|
|
110
|
+
fork report that refusal. See `kill --help` and `fork --help` for the
|
|
111
|
+
complete grammar.
|
|
112
|
+
|
|
113
|
+
## JavaScript automation
|
|
114
|
+
|
|
115
|
+
Use [Automation With The Akuma API](references/automation.md) for a
|
|
116
|
+
task-specific JavaScript coordinator, structured answers, or multi-worker
|
|
117
|
+
orchestration. The CLI is enough for one commission and its return. A
|
|
118
|
+
prompt-free birth followed by one input-bound ask uses the same identity:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { Akuma, Akumas, World } from "@astrosheep/keiyaku";
|
|
122
|
+
|
|
123
|
+
const root = await World.at(process.cwd());
|
|
124
|
+
const called = await Akumas.of(root).call({ archetype: "worker" });
|
|
125
|
+
const worker = Akuma.select(root, called.akuma);
|
|
126
|
+
const result = await worker.ask("Inspect the change");
|
|
127
|
+
console.log(result.observation);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The automation guide covers schema-based answer handling and longer workflows.
|