@astrosheep/keiyaku 4.0.2 → 4.0.4
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/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +9 -8
- package/build/src/akuma/akuma.d.ts +34 -11
- package/build/src/akuma/akuma.js +121 -61
- package/build/src/akuma/allowed.d.ts +7 -0
- package/build/src/akuma/allowed.js +40 -0
- package/build/src/akuma/archetype.d.ts +7 -4
- package/build/src/akuma/archetype.js +15 -16
- package/build/src/akuma/body.d.ts +3 -1
- package/build/src/akuma/body.js +19 -8
- package/build/src/akuma/heart/facts.d.ts +49 -7
- package/build/src/akuma/heart/index.d.ts +4 -8
- package/build/src/akuma/heart/index.js +76 -15
- package/build/src/akuma/heart/rows.d.ts +7 -5
- package/build/src/akuma/heart/rows.js +98 -11
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +15 -10
- package/build/src/akuma/heart/soul.js +3 -1
- package/build/src/akuma/heart/storage.d.ts +2 -0
- package/build/src/akuma/heart/storage.js +20 -0
- package/build/src/akuma/heart/timeline.d.ts +1 -5
- package/build/src/akuma/heart/timeline.js +8 -17
- package/build/src/akuma/index.d.ts +4 -1
- package/build/src/akuma/index.js +1 -0
- package/build/src/akuma/projection.d.ts +17 -3
- package/build/src/akuma/projection.js +40 -3
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +2 -1
- package/build/src/akuma/providers/acp/core.d.ts +3 -1
- package/build/src/akuma/providers/acp/core.js +4 -4
- package/build/src/akuma/providers/acp/events.d.ts +11 -3
- package/build/src/akuma/providers/acp/events.js +78 -4
- package/build/src/akuma/providers/claude/events.js +62 -3
- package/build/src/akuma/providers/codex-app-server/events.js +1 -13
- package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
- package/build/src/akuma/providers/grok-build/index.js +72 -2
- package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
- package/build/src/akuma/providers/pi/events.js +17 -3
- package/build/src/akuma/providers/unified-patch.d.ts +4 -0
- package/build/src/akuma/providers/unified-patch.js +14 -0
- package/build/src/akuma/publication.d.ts +1 -1
- package/build/src/akuma/publication.js +36 -7
- package/build/src/akuma/requests.d.ts +70 -4
- package/build/src/akuma/requests.js +288 -77
- package/build/src/akuma-body.d.ts +1 -0
- package/build/src/akuma-body.js +31 -0
- package/build/src/cli/accepted.d.ts +4 -1
- package/build/src/cli/accepted.js +26 -4
- package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
- package/build/src/cli/commands/akuma-invoke.js +18 -10
- package/build/src/cli/commands/akuma.d.ts +11 -2
- package/build/src/cli/commands/akuma.js +67 -28
- package/build/src/cli/commands/amend.d.ts +1 -1
- package/build/src/cli/commands/amend.js +1 -1
- package/build/src/cli/commands/contract.d.ts +3 -3
- package/build/src/cli/commands/contract.js +1 -1
- package/build/src/cli/commands/install.js +4 -4
- package/build/src/cli/commands/task-query.d.ts +1 -1
- package/build/src/cli/commands/task-query.js +11 -5
- package/build/src/cli/commands/task.js +4 -4
- package/build/src/cli/coordinates.d.ts +1 -0
- package/build/src/cli/coordinates.js +5 -1
- package/build/src/cli/invoke.d.ts +1 -0
- package/build/src/cli/invoke.js +90 -73
- package/build/src/cli/main.d.ts +2 -0
- package/build/src/cli/main.js +29 -4
- package/build/src/cli/parse.d.ts +1 -0
- package/build/src/cli/parse.js +8 -4
- package/build/src/cli/render/akuma.d.ts +2 -2
- package/build/src/cli/render/akuma.js +84 -13
- package/build/src/cli/render/audit.js +16 -2
- package/build/src/cli/render/contract.d.ts +2 -0
- package/build/src/cli/render/contract.js +203 -36
- package/build/src/cli/render/kanshi.js +64 -29
- package/build/src/cli/render/receipt.d.ts +2 -1
- package/build/src/cli/render/receipt.js +9 -1
- package/build/src/cli/render/text.js +3 -1
- package/build/src/cli/result.d.ts +38 -3
- package/build/src/cli/selectors.d.ts +1 -0
- package/build/src/cli/selectors.js +9 -6
- package/build/src/cli/usage.d.ts +2 -0
- package/build/src/cli/usage.js +4 -0
- package/build/src/contract-worktree.js +3 -0
- package/build/src/dispatch/index.js +50 -39
- package/build/src/git/hooks.d.ts +0 -4
- package/build/src/git/hooks.js +0 -36
- package/build/src/git/integration.d.ts +2 -6
- package/build/src/git/integration.js +8 -8
- package/build/src/git/read-observation.js +1 -0
- package/build/src/git/reconcile.d.ts +6 -1
- package/build/src/git/reconcile.js +55 -9
- package/build/src/git/tender.d.ts +19 -4
- package/build/src/git/tender.js +44 -13
- package/build/src/git/terminal-seal.d.ts +14 -0
- package/build/src/git/terminal-seal.js +15 -2
- package/build/src/git/workspace.d.ts +1 -0
- package/build/src/git/workspace.js +12 -4
- package/build/src/index.d.ts +1 -1
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +9 -1
- package/build/src/kanshi/read.js +91 -37
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/address.d.ts +5 -14
- package/build/src/library/address.js +20 -22
- package/build/src/library/akuma-creation.d.ts +4 -2
- package/build/src/library/akuma-creation.js +43 -26
- package/build/src/library/bind.js +3 -3
- package/build/src/library/catalog.d.ts +1 -2
- package/build/src/library/catalog.js +11 -6
- package/build/src/library/configuration.d.ts +4 -0
- package/build/src/library/configuration.js +19 -0
- package/build/src/library/contract.d.ts +15 -1
- package/build/src/library/contract.js +51 -4
- package/build/src/library/fleet.d.ts +47 -9
- package/build/src/library/fleet.js +184 -44
- package/build/src/library/input.js +1 -0
- package/build/src/library/keiyaku.d.ts +4 -4
- package/build/src/library/keiyaku.js +1 -2
- package/build/src/protocol/bind.d.ts +1 -2
- package/build/src/protocol/bind.js +2 -16
- package/build/src/protocol/operations.d.ts +4 -1
- package/build/src/protocol/operations.js +33 -27
- package/build/src/protocol/read/status.d.ts +3 -1
- package/build/src/protocol/read/status.js +24 -14
- package/build/src/runtime/proc/run.d.ts +1 -0
- package/build/src/runtime/proc/run.js +9 -2
- package/build/src/settlement/settle.d.ts +1 -0
- package/build/src/settlement/settle.js +4 -1
- package/build/src/task/board.d.ts +18 -3
- package/build/src/task/board.js +73 -26
- package/build/src/task/index.d.ts +3 -3
- package/build/src/task/index.js +7 -5
- package/build/src/task/operations.d.ts +2 -19
- package/build/src/task/operations.js +29 -7
- package/build/src/task/query.d.ts +9 -2
- package/build/src/task/query.js +32 -64
- package/build/src/verification/execution.js +2 -1
- package/package.json +3 -1
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { normalizeTargetBranch, observeBindCoordinates } from "../git/observe.js";
|
|
2
2
|
import { gitObjectIdForSnapshot } from "../git/identity.js";
|
|
3
|
-
import { contractIdFromSegment } from "../core/facts/types.js";
|
|
4
3
|
import { decideBind } from "../core/verbs/bind.js";
|
|
5
4
|
import { admitIntent } from "./intent.js";
|
|
6
5
|
import { complete } from "./outcome.js";
|
|
7
|
-
import { fitIdentityStem, normalizeIdentityStem } from "../identity/normalize.js";
|
|
8
|
-
const COLLISION_ATTEMPTS = 3;
|
|
9
|
-
function contractIdFor(title, suffix) {
|
|
10
|
-
const stem = fitIdentityStem({ stem: normalizeIdentityStem({ source: title }) || "contract", maxBytes: 48 });
|
|
11
|
-
return contractIdFromSegment(suffix === undefined ? stem : `${stem}-${suffix}`);
|
|
12
|
-
}
|
|
13
6
|
async function bindPreparation(input, target, seed) {
|
|
14
7
|
if (input.verification.kind === "refused") {
|
|
15
8
|
return { kind: "prepared", input: { ...seed, preparation: input.verification } };
|
|
@@ -50,7 +43,8 @@ export async function bindOperation(input) {
|
|
|
50
43
|
target = normalized;
|
|
51
44
|
}
|
|
52
45
|
const at = new Date().toISOString();
|
|
53
|
-
const
|
|
46
|
+
const id = input.contractId;
|
|
47
|
+
return complete(await admitIntent(input.channel, input.scope, {
|
|
54
48
|
contractId: id,
|
|
55
49
|
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
56
50
|
at,
|
|
@@ -59,12 +53,4 @@ export async function bindOperation(input) {
|
|
|
59
53
|
prepareInput: async (_observation, original) => bindPreparation(input, target, original),
|
|
60
54
|
...(input.decorateOffer === undefined ? {} : { decorateOffer: input.decorateOffer }),
|
|
61
55
|
}), { contractId: id });
|
|
62
|
-
if (input.contractId !== undefined)
|
|
63
|
-
return attempt(input.contractId);
|
|
64
|
-
let result = await attempt(contractIdFor(input.title));
|
|
65
|
-
for (let collision = 0; collision < COLLISION_ATTEMPTS && result.kind === "refused" && result.refusal.kind === "contract-exists"; collision += 1) {
|
|
66
|
-
result = await attempt(contractIdFor(input.title, randomBytes(8).toString("hex")));
|
|
67
|
-
}
|
|
68
|
-
return result;
|
|
69
56
|
}
|
|
70
|
-
import { randomBytes } from "node:crypto";
|
|
@@ -90,6 +90,7 @@ export type AuditReport = Readonly<{
|
|
|
90
90
|
export type VerificationReuse = CurrentVerifiedAttestation;
|
|
91
91
|
export type DocumentDerivation = Readonly<{
|
|
92
92
|
document: DocumentKey;
|
|
93
|
+
bytes: string;
|
|
93
94
|
title: string;
|
|
94
95
|
verification: VerificationDeclarationPreparation;
|
|
95
96
|
}>;
|
|
@@ -155,7 +156,7 @@ export type DeliverValue = DeliveryIdentity & Readonly<{
|
|
|
155
156
|
leak?: WorktreeLeak;
|
|
156
157
|
}>;
|
|
157
158
|
type DeliverOperationInput = MutationOperationInput & Readonly<{
|
|
158
|
-
deriveDocument
|
|
159
|
+
deriveDocument: (state: ContractState) => DocumentDerivation;
|
|
159
160
|
message?: string;
|
|
160
161
|
requireBranchesToBeUpToDate: boolean;
|
|
161
162
|
includeDirty: boolean;
|
|
@@ -169,6 +170,8 @@ export declare function prepareDelivery(repository: GitRepository, stage: Readon
|
|
|
169
170
|
}>;
|
|
170
171
|
}>, input: Readonly<{
|
|
171
172
|
title: string;
|
|
173
|
+
document: string;
|
|
174
|
+
actor?: ActorId;
|
|
172
175
|
message?: string;
|
|
173
176
|
requireBranchesToBeUpToDate?: boolean;
|
|
174
177
|
includeDirty?: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { materializeIntegrationSnapshot, planIntegration, readDeliveryDiff, readDeliveryScope, worktreeChangeId, } from "../git/integration.js";
|
|
2
|
-
import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, materializeTenderSnapshot, } from "../git/tender.js";
|
|
2
|
+
import { captureTender, dirtyTenderDelta, dirtyTenderRefusal, materializeTenderSnapshot, prepareDeliveryCommitMetadata, } from "../git/tender.js";
|
|
3
3
|
import { currentBranch, extendContractsForAdmissionAt, observeContractAt, observeContractWorld, observeContractsForAdmissionAt, } from "../git/observe.js";
|
|
4
4
|
import { reconcile, reconcileBatch, reconcileObservationFailure, } from "../git/reconcile.js";
|
|
5
5
|
import { NoGitWorldError, repositoryAt } from "../git/repository.js";
|
|
@@ -188,22 +188,22 @@ export async function prepareDelivery(repository, stage, input) {
|
|
|
188
188
|
if ((tender.data.dirty && input.includeDirty !== true) || tender.data.changes.submodules.length > 0) {
|
|
189
189
|
return { kind: "refused", refusal: await dirtyTenderRefusal(repository, contractId, tender.data) };
|
|
190
190
|
}
|
|
191
|
-
const
|
|
191
|
+
const commit = await prepareDeliveryCommitMetadata(repository, {
|
|
192
192
|
contractId,
|
|
193
193
|
title: input.title,
|
|
194
|
+
document: input.document,
|
|
195
|
+
at: tender.data.at,
|
|
196
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
194
197
|
...(input.message === undefined ? {} : { message: input.message }),
|
|
195
198
|
});
|
|
199
|
+
const tenderSnapshot = await materializeTenderSnapshot(repository, tender.data, commit);
|
|
196
200
|
const requireBranchesToBeUpToDate = input.requireBranchesToBeUpToDate ?? false;
|
|
197
201
|
const integration = await planIntegration(repository, { contractId, coordinates }, { ...tender.data, head: tenderSnapshot }, requireBranchesToBeUpToDate);
|
|
198
202
|
if (integration.kind === "refused")
|
|
199
203
|
return integration;
|
|
200
204
|
const integrationSnapshot = coordinates.target === undefined
|
|
201
205
|
? tenderSnapshot
|
|
202
|
-
: await materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor,
|
|
203
|
-
contractId,
|
|
204
|
-
title: input.title,
|
|
205
|
-
...(input.message === undefined ? {} : { message: input.message }),
|
|
206
|
-
});
|
|
206
|
+
: await materializeIntegrationSnapshot(repository, integration.data.tree, integration.data.predecessor, commit);
|
|
207
207
|
return {
|
|
208
208
|
kind: "prepared",
|
|
209
209
|
data: {
|
|
@@ -276,6 +276,8 @@ async function deliverAttempt(input, attempt) {
|
|
|
276
276
|
coordinates: state.coordinates,
|
|
277
277
|
}, {
|
|
278
278
|
title: derivation.title,
|
|
279
|
+
document: derivation.bytes,
|
|
280
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
279
281
|
...(input.message === undefined ? {} : { message: input.message }),
|
|
280
282
|
requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate,
|
|
281
283
|
includeDirty: input.includeDirty,
|
|
@@ -589,6 +591,25 @@ async function auditTargetAnswer(repository, state, candidate) {
|
|
|
589
591
|
candidate: candidate.integration.snapshot,
|
|
590
592
|
});
|
|
591
593
|
}
|
|
594
|
+
function blockedAudit(refusal) {
|
|
595
|
+
return {
|
|
596
|
+
candidate: { kind: "blocked", refusal },
|
|
597
|
+
verification: { kind: "not-run" },
|
|
598
|
+
target: { kind: "not-observed" },
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function completedAudit(state, verified, value) {
|
|
602
|
+
const obligations = {
|
|
603
|
+
...(verified?.cleanup === undefined ? {} : { cleanup: verified.cleanup }),
|
|
604
|
+
...(verified?.leak === undefined ? {} : { leak: verified.leak }),
|
|
605
|
+
};
|
|
606
|
+
return verified?.admission === undefined
|
|
607
|
+
? accepted(state, [], value, undefined, obligations)
|
|
608
|
+
: {
|
|
609
|
+
...admitted(verified.admission, value),
|
|
610
|
+
...obligations,
|
|
611
|
+
};
|
|
612
|
+
}
|
|
592
613
|
export async function auditOperation(input) {
|
|
593
614
|
const observed = await observeContractsForAdmissionAt(input.scope, input.channel, [input.contractId]);
|
|
594
615
|
const state = activeContract(observed.decision, input.contractId);
|
|
@@ -603,11 +624,7 @@ export async function auditOperation(input) {
|
|
|
603
624
|
}
|
|
604
625
|
const workspace = await auditWorkspace(input.scope, state);
|
|
605
626
|
if (workspace.kind === "unappointed") {
|
|
606
|
-
return accepted(state, [], {
|
|
607
|
-
candidate: { kind: "blocked", refusal: { kind: "worktree-missing", contractId: state.id } },
|
|
608
|
-
verification: { kind: "not-run" },
|
|
609
|
-
target: { kind: "not-observed" },
|
|
610
|
-
});
|
|
627
|
+
return accepted(state, [], blockedAudit({ kind: "worktree-missing", contractId: state.id }));
|
|
611
628
|
}
|
|
612
629
|
const prepared = await prepareDelivery(input.scope, {
|
|
613
630
|
contractId: state.id,
|
|
@@ -615,15 +632,13 @@ export async function auditOperation(input) {
|
|
|
615
632
|
...(workspace.appointment === undefined ? {} : { appointment: workspace.appointment }),
|
|
616
633
|
}, {
|
|
617
634
|
title: derivation.title,
|
|
635
|
+
document: derivation.bytes,
|
|
636
|
+
...(input.actor === undefined ? {} : { actor: input.actor }),
|
|
618
637
|
requireBranchesToBeUpToDate: input.requireBranchesToBeUpToDate ?? false,
|
|
619
638
|
includeDirty: input.includeDirty ?? false,
|
|
620
639
|
});
|
|
621
640
|
if (prepared.kind === "refused") {
|
|
622
|
-
return accepted(state, [],
|
|
623
|
-
candidate: { kind: "blocked", refusal: prepared.refusal },
|
|
624
|
-
verification: { kind: "not-run" },
|
|
625
|
-
target: { kind: "not-observed" },
|
|
626
|
-
});
|
|
641
|
+
return accepted(state, [], blockedAudit(prepared.refusal));
|
|
627
642
|
}
|
|
628
643
|
const verified = derivation.verification.data === null
|
|
629
644
|
? undefined
|
|
@@ -638,16 +653,7 @@ export async function auditOperation(input) {
|
|
|
638
653
|
: await auditTargetAnswer(input.scope, state, prepared.data),
|
|
639
654
|
...(delivery === undefined ? {} : { delivery }),
|
|
640
655
|
};
|
|
641
|
-
|
|
642
|
-
...(verified?.cleanup === undefined ? {} : { cleanup: verified.cleanup }),
|
|
643
|
-
...(verified?.leak === undefined ? {} : { leak: verified.leak }),
|
|
644
|
-
};
|
|
645
|
-
return verified?.admission === undefined
|
|
646
|
-
? accepted(state, [], value, undefined, obligations)
|
|
647
|
-
: {
|
|
648
|
-
...admitted(verified.admission, value),
|
|
649
|
-
...obligations,
|
|
650
|
-
};
|
|
656
|
+
return completedAudit(state, verified, value);
|
|
651
657
|
}
|
|
652
658
|
export async function reconcileOperation(input) {
|
|
653
659
|
try {
|
|
@@ -46,6 +46,8 @@ export type ContractObservation = Readonly<{
|
|
|
46
46
|
}>;
|
|
47
47
|
export declare function phaseAtFor(state: Pick<ContractState, "terminal" | "delivery" | "bound">, bindAt: string): string;
|
|
48
48
|
/** Build the Contract board from one immutable git observation. */
|
|
49
|
-
export declare function readContractBoard(observation: GitReadObservation): Promise<ContractBoard>;
|
|
49
|
+
export declare function readContractBoard(observation: GitReadObservation, selected?: ContractId): Promise<ContractBoard>;
|
|
50
|
+
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
51
|
+
export declare function readContractObservation(observation: GitReadObservation, id: ContractId): Promise<ContractObservation>;
|
|
50
52
|
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
51
53
|
export declare function readContractObservationAt(repository: GitRepository, channel: GitDecodeChannel, id: ContractId): Promise<ContractObservation>;
|
|
@@ -76,7 +76,15 @@ async function rowFor(repository, state, bindAt, targetObservation, register) {
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
/** Build the Contract board from one immutable git observation. */
|
|
79
|
-
export async function readContractBoard(observation) {
|
|
79
|
+
export async function readContractBoard(observation, selected) {
|
|
80
|
+
if (selected !== undefined) {
|
|
81
|
+
const contract = await readContractObservation(observation, selected);
|
|
82
|
+
return {
|
|
83
|
+
root: observation.repository.primaryWorktree,
|
|
84
|
+
state: observation.snapshot.commit,
|
|
85
|
+
rows: contract.kind === "missing" ? [] : [contract.row],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
80
88
|
const observed = await observeActiveContractWorld(observation);
|
|
81
89
|
const register = await readPlaceRegister(observation.repository);
|
|
82
90
|
const rows = [];
|
|
@@ -90,18 +98,20 @@ export async function readContractBoard(observation) {
|
|
|
90
98
|
return { root: observation.repository.primaryWorktree, state: observed.snapshot, rows: await Promise.all(rows) };
|
|
91
99
|
}
|
|
92
100
|
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
101
|
+
export async function readContractObservation(observation, id) {
|
|
102
|
+
const observed = await observeContractsForAdmissionInObservationAt(observation, [id]);
|
|
103
|
+
const record = observed.journals.get(id);
|
|
104
|
+
if (record === undefined)
|
|
105
|
+
throw new Error(`missing requested Contract observation: ${id}`);
|
|
106
|
+
const state = record.state;
|
|
107
|
+
return state === null
|
|
108
|
+
? { kind: "missing", id }
|
|
109
|
+
: {
|
|
110
|
+
kind: "present",
|
|
111
|
+
row: await rowFor(observation.repository, state, record.entries[0].at, await observeDeliveryTargetAt(observation, state), await readPlaceRegister(observation.repository)),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** Observe one Contract and its target from one fresh ref epoch. */
|
|
93
115
|
export async function readContractObservationAt(repository, channel, id) {
|
|
94
|
-
return withContractReadObservationAt(repository, channel, id, async (observation) =>
|
|
95
|
-
const observed = await observeContractsForAdmissionInObservationAt(observation, [id]);
|
|
96
|
-
const record = observed.journals.get(id);
|
|
97
|
-
if (record === undefined)
|
|
98
|
-
throw new Error(`missing requested Contract observation: ${id}`);
|
|
99
|
-
const state = record.state;
|
|
100
|
-
return state === null
|
|
101
|
-
? { kind: "missing", id }
|
|
102
|
-
: {
|
|
103
|
-
kind: "present",
|
|
104
|
-
row: await rowFor(observation.repository, state, record.entries[0].at, await observeDeliveryTargetAt(observation, state), await readPlaceRegister(observation.repository)),
|
|
105
|
-
};
|
|
106
|
-
});
|
|
116
|
+
return withContractReadObservationAt(repository, channel, id, async (observation) => await readContractObservation(observation, id));
|
|
107
117
|
}
|
|
@@ -51,6 +51,7 @@ export type OwnedProcess = Readonly<{
|
|
|
51
51
|
export declare function terminateOwnedProcess(child: ChildProcess, force?: boolean): Promise<void>;
|
|
52
52
|
export declare function spawnDetachedProcess(input: DetachedProcessInput): Promise<OwnedProcess>;
|
|
53
53
|
export declare function runProcess(input: ProcessInput): Promise<ProcessOutcome>;
|
|
54
|
+
export declare function runCrossPlatformProcess(input: ProcessInput): Promise<ProcessOutcome>;
|
|
54
55
|
export declare function runProcessToExit(input: ProcessLaunch): Promise<ProcessOutcome>;
|
|
55
56
|
export declare function consumeProcessStdout(input: ProcessInput, consume: (chunk: Buffer) => void): Promise<ProcessConsumption>;
|
|
56
57
|
export {};
|
|
@@ -2,6 +2,7 @@ import { execFile, spawn } from "node:child_process";
|
|
|
2
2
|
import { open } from "node:fs/promises";
|
|
3
3
|
import { setTimeout as delay } from "node:timers/promises";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
|
+
import crossSpawn from "cross-spawn";
|
|
5
6
|
const TERMINATION_GRACE_MS = 250;
|
|
6
7
|
const STREAM_TAIL_BYTES = 16 * 1024;
|
|
7
8
|
function tailCapture(limit) {
|
|
@@ -138,10 +139,10 @@ function terminalOutcome(code, stdout, stderr, consuming) {
|
|
|
138
139
|
truncated: (consuming ? false : stdout.truncated) || stderr.truncated,
|
|
139
140
|
};
|
|
140
141
|
}
|
|
141
|
-
async function executeProcess(input, timeoutMs, consumeStdout) {
|
|
142
|
+
async function executeProcess(input, timeoutMs, consumeStdout, spawnProcess = spawn) {
|
|
142
143
|
if (input.signal?.aborted === true)
|
|
143
144
|
return { outcome: { kind: "cancelled" }, pid: null };
|
|
144
|
-
const child =
|
|
145
|
+
const child = spawnProcess(input.argv[0], input.argv.slice(1), {
|
|
145
146
|
cwd: input.cwd,
|
|
146
147
|
env: input.env,
|
|
147
148
|
detached: true,
|
|
@@ -223,6 +224,12 @@ export async function runProcess(input) {
|
|
|
223
224
|
throw new Error("buffered process produced a stream consumer error");
|
|
224
225
|
return result.outcome;
|
|
225
226
|
}
|
|
227
|
+
export async function runCrossPlatformProcess(input) {
|
|
228
|
+
const result = await executeProcess(input, input.timeoutMs, undefined, crossSpawn);
|
|
229
|
+
if (result.outcome.kind === "stream-error")
|
|
230
|
+
throw new Error("buffered process produced a stream consumer error");
|
|
231
|
+
return result.outcome;
|
|
232
|
+
}
|
|
226
233
|
export async function runProcessToExit(input) {
|
|
227
234
|
const result = await executeProcess(input, undefined);
|
|
228
235
|
if (result.outcome.kind === "stream-error")
|
|
@@ -29,6 +29,7 @@ export declare function deferredTaskHolderSettlement(input: Readonly<{
|
|
|
29
29
|
taskId: TaskId;
|
|
30
30
|
diagnostic: string;
|
|
31
31
|
}>): SettlementReport;
|
|
32
|
+
export declare function contractNamespace(id: ContractId): readonly [string];
|
|
32
33
|
export type SettlementInput = Readonly<{
|
|
33
34
|
repository: GitRepository;
|
|
34
35
|
channel: GitDecodeChannel;
|
|
@@ -7,6 +7,9 @@ import { World } from "../world.js";
|
|
|
7
7
|
export function deferredTaskHolderSettlement(input) {
|
|
8
8
|
return { actions: [], lags: [{ kind: "settlement-failed", surface: "task-holder", ...input }] };
|
|
9
9
|
}
|
|
10
|
+
export function contractNamespace(id) {
|
|
11
|
+
return [contractSegment(id)];
|
|
12
|
+
}
|
|
10
13
|
function diagnostic(error) {
|
|
11
14
|
return error instanceof Error ? error.message : String(error);
|
|
12
15
|
}
|
|
@@ -79,7 +82,7 @@ async function settleNamespace(state, effects, actions, lags) {
|
|
|
79
82
|
actions.push({
|
|
80
83
|
kind: "namespace-context",
|
|
81
84
|
path: effect.path,
|
|
82
|
-
action: await repairNamespaceContext(world,
|
|
85
|
+
action: await repairNamespaceContext(world, contractNamespace(state.id)),
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
88
|
catch (error) {
|
|
@@ -54,11 +54,20 @@ export type TaskDoctorIssue = Readonly<{
|
|
|
54
54
|
relation: "needs" | "parent" | "supersedes";
|
|
55
55
|
tasks: readonly TaskId[];
|
|
56
56
|
}>;
|
|
57
|
+
export declare function taskRef(board: TaskBoard, id: TaskId): TaskRef;
|
|
58
|
+
export type TaskRelationProjection = Readonly<{
|
|
59
|
+
children(id: TaskId): readonly TaskRef[];
|
|
60
|
+
blocks(id: TaskId): readonly TaskRef[];
|
|
61
|
+
supersededBy(id: TaskId): readonly TaskRef[];
|
|
62
|
+
related(id: TaskId): readonly TaskRef[];
|
|
63
|
+
}>;
|
|
64
|
+
export declare function createTaskRelations(board: TaskBoard): TaskRelationProjection;
|
|
57
65
|
export declare function taskDisposition(board: TaskBoard, task: TaskDocument): TaskDisposition;
|
|
58
|
-
export declare function
|
|
66
|
+
export declare function taskBlocked(board: TaskBoard, task: TaskDocument): boolean;
|
|
67
|
+
export declare function projectDetailFacts(board: TaskBoard, id: TaskId, relations: TaskRelationProjection): TaskDetailFacts | null;
|
|
59
68
|
export declare function projectRows(board: TaskBoard, scope: readonly string[] | null, selection: "active" | "closed" | "all"): readonly TaskRow[];
|
|
60
69
|
export declare function projectReady(board: TaskBoard, scope: readonly string[] | null): readonly TaskRow[];
|
|
61
|
-
export declare function projectBlocked(board: TaskBoard, scope: readonly string[] | null): readonly BlockedTaskRow[];
|
|
70
|
+
export declare function projectBlocked(board: TaskBoard, scope: readonly string[] | null, relations: TaskRelationProjection): readonly BlockedTaskRow[];
|
|
62
71
|
export declare function projectStatusRows(board: TaskBoard, scope: readonly string[] | null): (Readonly<{
|
|
63
72
|
id: TaskId;
|
|
64
73
|
title: string;
|
|
@@ -77,7 +86,13 @@ export declare function projectStatusRows(board: TaskBoard, scope: readonly stri
|
|
|
77
86
|
priority: TaskPriority;
|
|
78
87
|
disposition: TaskDisposition;
|
|
79
88
|
})[];
|
|
89
|
+
export type TaskBoardObservation = Readonly<{
|
|
90
|
+
statusRows: ReturnType<typeof projectStatusRows>;
|
|
91
|
+
selectNamespace(namespace: readonly string[]): readonly TaskRow[];
|
|
92
|
+
selectCreatedBy(createdBy: string): readonly TaskRow[];
|
|
93
|
+
}>;
|
|
94
|
+
export declare function projectTaskBoardObservation(board: TaskBoard): TaskBoardObservation;
|
|
80
95
|
export declare function relationProblem(board: TaskBoard, before: TaskDocument | null, after: TaskDocument): string | null;
|
|
81
96
|
export declare function diagnoseBoard(board: TaskBoard): readonly TaskDoctorIssue[];
|
|
82
|
-
export declare function buildTree(board: TaskBoard, root: TaskId): TaskTreeNode | null;
|
|
97
|
+
export declare function buildTree(board: TaskBoard, root: TaskId, relations: TaskRelationProjection): TaskTreeNode | null;
|
|
83
98
|
export {};
|
package/build/src/task/board.js
CHANGED
|
@@ -1,42 +1,81 @@
|
|
|
1
1
|
import { parseTaskId, sameNamespace } from "./identity.js";
|
|
2
2
|
const terminal = (state) => state === "done" || state === "drop";
|
|
3
|
+
const none = Object.freeze([]);
|
|
3
4
|
const sorted = (values) => [...values].sort((a, b) => Buffer.compare(Buffer.from(a.id), Buffer.from(b.id)));
|
|
4
|
-
function taskRef(board, id) {
|
|
5
|
+
export function taskRef(board, id) {
|
|
5
6
|
const task = board.tasks.get(id);
|
|
6
7
|
return task === undefined ? { id, title: null, state: "missing" } : { id, title: task.title, state: task.state };
|
|
7
8
|
}
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
function append(index, key, value) {
|
|
10
|
+
const values = index.get(key);
|
|
11
|
+
if (values === undefined)
|
|
12
|
+
index.set(key, [value]);
|
|
13
|
+
else
|
|
14
|
+
values.push(value);
|
|
11
15
|
}
|
|
12
|
-
function
|
|
13
|
-
return
|
|
16
|
+
function freezeRefs(board, index) {
|
|
17
|
+
return new Map([...index].map(([id, targets]) => [id, sorted(targets.map((target) => taskRef(board, target)))]));
|
|
14
18
|
}
|
|
15
|
-
function
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
export function createTaskRelations(board) {
|
|
20
|
+
const children = new Map();
|
|
21
|
+
const blocks = new Map();
|
|
22
|
+
const supersededBy = new Map();
|
|
23
|
+
const incoming = new Map();
|
|
24
|
+
for (const task of board.tasks.values()) {
|
|
25
|
+
if (task.parent !== null)
|
|
26
|
+
append(children, task.parent, task.id);
|
|
27
|
+
for (const need of task.needs)
|
|
28
|
+
append(blocks, need, task.id);
|
|
29
|
+
for (const target of task.supersedes)
|
|
30
|
+
append(supersededBy, target, task.id);
|
|
31
|
+
for (const target of task.relates)
|
|
32
|
+
append(incoming, target, task.id);
|
|
33
|
+
}
|
|
34
|
+
const childRefs = freezeRefs(board, children);
|
|
35
|
+
const blockRefs = freezeRefs(board, blocks);
|
|
36
|
+
const successorRefs = freezeRefs(board, supersededBy);
|
|
37
|
+
const incomingRefs = freezeRefs(board, incoming);
|
|
38
|
+
return {
|
|
39
|
+
children: (id) => childRefs.get(id) ?? none,
|
|
40
|
+
blocks: (id) => blockRefs.get(id) ?? none,
|
|
41
|
+
supersededBy: (id) => successorRefs.get(id) ?? none,
|
|
42
|
+
related: (id) => {
|
|
43
|
+
const task = board.tasks.get(id);
|
|
44
|
+
const ids = new Set(task?.relates ?? []);
|
|
45
|
+
for (const ref of incomingRefs.get(id) ?? none)
|
|
46
|
+
ids.add(ref.id);
|
|
47
|
+
return ids.size === 0 ? none : sorted([...ids].map((related) => taskRef(board, related)));
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function needReleased(board, id) {
|
|
52
|
+
const target = board.tasks.get(id);
|
|
53
|
+
return target !== undefined && terminal(target.state);
|
|
54
|
+
}
|
|
55
|
+
function hasUnresolvedNeeds(board, task) {
|
|
56
|
+
return task.needs.some((id) => !needReleased(board, id));
|
|
21
57
|
}
|
|
22
58
|
export function taskDisposition(board, task) {
|
|
23
59
|
if (task.state !== "open")
|
|
24
60
|
return task.state;
|
|
25
|
-
return
|
|
61
|
+
return hasUnresolvedNeeds(board, task) ? "blocked" : "ready";
|
|
26
62
|
}
|
|
27
|
-
export function
|
|
63
|
+
export function taskBlocked(board, task) {
|
|
64
|
+
return (task.state === "open" || task.state === "in_progress") && hasUnresolvedNeeds(board, task);
|
|
65
|
+
}
|
|
66
|
+
export function projectDetailFacts(board, id, relations) {
|
|
28
67
|
const task = board.tasks.get(id);
|
|
29
68
|
if (task === undefined)
|
|
30
69
|
return null;
|
|
31
|
-
const needs = task.needs.map((need) => ({ ...taskRef(board, need), released: board
|
|
70
|
+
const needs = task.needs.map((need) => ({ ...taskRef(board, need), released: needReleased(board, need) }));
|
|
32
71
|
return {
|
|
33
72
|
task,
|
|
34
73
|
needs,
|
|
35
74
|
blockers: needs.filter((need) => !need.released).map(({ released: _released, ...ref }) => ref),
|
|
36
|
-
blocks:
|
|
37
|
-
parent: task.parent === null ? null : taskRef(board, task.parent), children: children(
|
|
38
|
-
supersedes: task.supersedes.map((target) => taskRef(board, target)), supersededBy:
|
|
39
|
-
related: related(
|
|
75
|
+
blocks: relations.blocks(id),
|
|
76
|
+
parent: task.parent === null ? null : taskRef(board, task.parent), children: relations.children(id),
|
|
77
|
+
supersedes: task.supersedes.map((target) => taskRef(board, target)), supersededBy: relations.supersededBy(id),
|
|
78
|
+
related: relations.related(id),
|
|
40
79
|
};
|
|
41
80
|
}
|
|
42
81
|
function inScope(task, scope) { return scope === null || sameNamespace(parseTaskId(task.id).namespace, scope); }
|
|
@@ -50,21 +89,29 @@ export function projectRows(board, scope, selection) {
|
|
|
50
89
|
export function projectReady(board, scope) {
|
|
51
90
|
return projectRows(board, scope, "active").filter((row) => row.disposition === "ready");
|
|
52
91
|
}
|
|
53
|
-
export function projectBlocked(board, scope) {
|
|
92
|
+
export function projectBlocked(board, scope, relations) {
|
|
54
93
|
return projectRows(board, scope, "active").flatMap((row) => {
|
|
55
|
-
if (
|
|
94
|
+
if (!taskBlocked(board, board.tasks.get(row.id)))
|
|
56
95
|
return [];
|
|
57
|
-
|
|
58
|
-
return blockers.length === 0 ? [] : [{ ...row, blockers }];
|
|
96
|
+
return [{ ...row, blockers: projectDetailFacts(board, row.id, relations).blockers }];
|
|
59
97
|
});
|
|
60
98
|
}
|
|
61
99
|
export function projectStatusRows(board, scope) {
|
|
62
|
-
const
|
|
100
|
+
const relations = createTaskRelations(board);
|
|
101
|
+
const blockers = new Map(projectBlocked(board, scope, relations).map((row) => [row.id, row.blockers]));
|
|
63
102
|
return projectRows(board, scope, "all").map((row) => {
|
|
64
103
|
const unresolved = blockers.get(row.id);
|
|
65
104
|
return unresolved === undefined ? row : { ...row, blockers: unresolved };
|
|
66
105
|
});
|
|
67
106
|
}
|
|
107
|
+
export function projectTaskBoardObservation(board) {
|
|
108
|
+
const rows = projectRows(board, null, "all");
|
|
109
|
+
return {
|
|
110
|
+
statusRows: projectStatusRows(board, null),
|
|
111
|
+
selectNamespace: (namespace) => projectRows(board, namespace, "all"),
|
|
112
|
+
selectCreatedBy: (createdBy) => rows.filter((row) => board.tasks.get(row.id)?.createdBy === createdBy),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
68
115
|
function relationIds(task, relation) {
|
|
69
116
|
return relation === "parent" ? task.parent === null ? [] : [task.parent] : task[relation];
|
|
70
117
|
}
|
|
@@ -147,7 +194,7 @@ export function diagnoseBoard(board) {
|
|
|
147
194
|
}
|
|
148
195
|
return issues;
|
|
149
196
|
}
|
|
150
|
-
export function buildTree(board, root) {
|
|
197
|
+
export function buildTree(board, root, relations) {
|
|
151
198
|
if (!board.tasks.has(root))
|
|
152
199
|
return null;
|
|
153
200
|
const walk = (id, path) => {
|
|
@@ -156,7 +203,7 @@ export function buildTree(board, root) {
|
|
|
156
203
|
const node = { task: { ...ref, priority: task?.priority ?? null } };
|
|
157
204
|
if (path.includes(id))
|
|
158
205
|
return { ...node, cycle: true, children: [] };
|
|
159
|
-
return { ...node, children: children(
|
|
206
|
+
return { ...node, children: relations.children(id).map((child) => walk(child.id, [...path, id])) };
|
|
160
207
|
};
|
|
161
208
|
return walk(root, []);
|
|
162
209
|
}
|
|
@@ -5,7 +5,7 @@ import { type TaskCompositionResult } from "./compose.js";
|
|
|
5
5
|
import { TaskAuthorityCorruptionError, type TaskPriority, type TaskState } from "./document.js";
|
|
6
6
|
import { type TaskId } from "./identity.js";
|
|
7
7
|
import { type AddTaskDocumentInput, type AddTaskInput, type TaskBatchResult, type TaskMutationResult, type TaskOutcome, type TaskRefusal, type TaskRetry, type TaskUpdateResult, type TaskView, type UpdateTaskInput } from "./operations.js";
|
|
8
|
-
import { type TaskPage, type TaskQueryExpression, type TaskQueryPredicate, type TaskQueryRow, type TaskQuerySort } from "./query.js";
|
|
8
|
+
import { TASK_RELATION_PREDICATE_FIELDS, type TaskPage, type TaskQueryExpression, type TaskQueryPredicate, type TaskQueryRow, type TaskQuerySort, type TaskRelationPredicateField } from "./query.js";
|
|
9
9
|
export type TaskDetail = Omit<TaskDetailFacts, "task"> & Readonly<{
|
|
10
10
|
task: TaskView;
|
|
11
11
|
}>;
|
|
@@ -17,8 +17,8 @@ export type TaskDoctorReport = Readonly<{
|
|
|
17
17
|
issues: readonly TaskDoctorIssue[];
|
|
18
18
|
}>;
|
|
19
19
|
export type TaskDecompositionTree = TaskOutcome<TaskTreeNode>;
|
|
20
|
-
export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort };
|
|
21
|
-
export { TaskAuthorityCorruptionError };
|
|
20
|
+
export type { AddTaskDocumentInput, AddTaskInput, BlockedTaskRow, TaskBatchResult, TaskCompositionResult, TaskDoctorIssue, TaskId, TaskMutationResult, TaskOutcome, TaskPriority, TaskRef, TaskRefusal, TaskRetry, TaskRow, TaskState, TaskTreeNode, TaskUpdateResult, TaskView, UpdateTaskInput, TaskPage, TaskQueryExpression, TaskQueryPredicate, TaskQueryRow, TaskQuerySort, TaskRelationPredicateField, };
|
|
21
|
+
export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
|
|
22
22
|
declare class TaskHandle {
|
|
23
23
|
readonly id: TaskId;
|
|
24
24
|
private readonly world;
|
package/build/src/task/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { buildTree, diagnoseBoard, projectDetailFacts } from "./board.js";
|
|
1
|
+
import { buildTree, createTaskRelations, diagnoseBoard, projectDetailFacts, } from "./board.js";
|
|
2
2
|
import { composeTasks } from "./compose.js";
|
|
3
3
|
import { TaskAuthorityCorruptionError } from "./document.js";
|
|
4
4
|
import { isTaskSegment, parseTaskId } from "./identity.js";
|
|
5
5
|
import { addTask, addTaskDocument, batchTasks, blockedTasks, currentNamespace, lifecycleTask, listTasks, queryTasks, readyTasks, setCurrentNamespace, taskView, updateTask, } from "./operations.js";
|
|
6
6
|
import { readBoard } from "./store.js";
|
|
7
|
-
import { isValidTaskLimit, normalizeTaskQuery, MAX_TASK_LIMIT, DEFAULT_TASK_LIMIT } from "./query.js";
|
|
8
|
-
export { TaskAuthorityCorruptionError };
|
|
7
|
+
import { isValidTaskLimit, normalizeTaskQuery, TASK_RELATION_PREDICATE_FIELDS, MAX_TASK_LIMIT, DEFAULT_TASK_LIMIT, } from "./query.js";
|
|
8
|
+
export { TaskAuthorityCorruptionError, TASK_RELATION_PREDICATE_FIELDS };
|
|
9
9
|
function record(value, label) {
|
|
10
10
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
11
11
|
throw new TypeError(`${label} must be an object`);
|
|
@@ -139,13 +139,15 @@ class TaskHandle {
|
|
|
139
139
|
this.world = world;
|
|
140
140
|
}
|
|
141
141
|
async read() {
|
|
142
|
-
const
|
|
142
|
+
const board = (await readBoard(this.world)).board;
|
|
143
|
+
const facts = projectDetailFacts(board, this.id, createTaskRelations(board));
|
|
143
144
|
return facts === null ? null : { ...facts, task: taskView(facts.task) };
|
|
144
145
|
}
|
|
145
146
|
async tree() {
|
|
146
147
|
if (arguments.length > 0)
|
|
147
148
|
throw new TypeError("tree accepts no input");
|
|
148
|
-
const
|
|
149
|
+
const board = (await readBoard(this.world)).board;
|
|
150
|
+
const node = buildTree(board, this.id, createTaskRelations(board));
|
|
149
151
|
return node === null ? { kind: "refused", refusal: { kind: "task-missing", taskId: this.id } } : { kind: "accepted", value: node };
|
|
150
152
|
}
|
|
151
153
|
update(input) { return updateTask(this.world, this.id, updateInput(input)); }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BlockedTaskRow, type TaskRow } from "./board.js";
|
|
1
|
+
import { type BlockedTaskRow, type TaskBoardObservation, type TaskRow } from "./board.js";
|
|
2
2
|
import { type TaskDocument, type TaskPriority, type TaskState } from "./document.js";
|
|
3
3
|
import { type TaskId } from "./identity.js";
|
|
4
4
|
import type { WorldRoot } from "../world.js";
|
|
@@ -116,24 +116,7 @@ export declare function readyTasks(world: WorldRoot, scope?: "namespace" | "worl
|
|
|
116
116
|
export declare function blockedTasks(world: WorldRoot, scope?: "namespace" | "world", parent?: TaskId, limit?: number): Promise<TaskOutcome<TaskPage<BlockedTaskRow>>>;
|
|
117
117
|
export declare function queryTasks(world: WorldRoot, expression: TaskQueryExpression, scope?: "namespace" | "world", sort?: TaskQuerySort, limit?: number): Promise<TaskOutcome<TaskPage<TaskQueryRow>>>;
|
|
118
118
|
/** Internal composite observation from one complete Task board read. */
|
|
119
|
-
export declare function
|
|
120
|
-
id: TaskId;
|
|
121
|
-
title: string;
|
|
122
|
-
state: TaskState;
|
|
123
|
-
priority: TaskPriority;
|
|
124
|
-
disposition: import("./board.js").TaskDisposition;
|
|
125
|
-
}> | {
|
|
126
|
-
blockers: readonly Readonly<{
|
|
127
|
-
id: TaskId;
|
|
128
|
-
title: string | null;
|
|
129
|
-
state: TaskState | "missing";
|
|
130
|
-
}>[];
|
|
131
|
-
id: TaskId;
|
|
132
|
-
title: string;
|
|
133
|
-
state: TaskState;
|
|
134
|
-
priority: TaskPriority;
|
|
135
|
-
disposition: import("./board.js").TaskDisposition;
|
|
136
|
-
})[]>;
|
|
119
|
+
export declare function observeTaskBoard(world: WorldRoot): Promise<TaskBoardObservation>;
|
|
137
120
|
/** Internal identity catalog from one complete Task board read. */
|
|
138
121
|
export declare function observeTaskCatalogRows(world: WorldRoot): Promise<readonly TaskRow[]>;
|
|
139
122
|
export declare function setCurrentNamespace(world: WorldRoot, namespace: readonly string[]): Promise<void>;
|