@astrosheep/keiyaku 4.1.0 → 4.1.2
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 +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
- package/build/src/akuma/akuma-errors.d.ts +6 -0
- package/build/src/akuma/akuma-errors.js +9 -0
- package/build/src/akuma/akuma-handle.d.ts +39 -0
- package/build/src/akuma/akuma-handle.js +263 -0
- package/build/src/akuma/akuma-observe.d.ts +19 -0
- package/build/src/akuma/akuma-observe.js +74 -0
- package/build/src/akuma/akuma-product-symbols.d.ts +1 -0
- package/build/src/akuma/akuma-product-symbols.js +1 -0
- package/build/src/akuma/akuma-product.d.ts +18 -0
- package/build/src/akuma/akuma-product.js +154 -0
- package/build/src/akuma/akuma.d.ts +37 -81
- package/build/src/akuma/akuma.js +39 -447
- package/build/src/akuma/allowed.d.ts +1 -0
- package/build/src/akuma/allowed.js +6 -0
- package/build/src/akuma/archetype.js +8 -5
- package/build/src/akuma/body-supervisor.d.ts +26 -0
- package/build/src/akuma/body-supervisor.js +89 -0
- package/build/src/akuma/body.d.ts +45 -4
- package/build/src/akuma/body.js +145 -35
- package/build/src/akuma/coordinate.js +17 -7
- package/build/src/akuma/heart/facts.js +1 -1
- package/build/src/akuma/heart/index.d.ts +1 -1
- package/build/src/akuma/heart/index.js +2 -4
- package/build/src/akuma/heart/request-authority.js +4 -4
- package/build/src/akuma/heart/request-rows.js +27 -16
- package/build/src/akuma/heart/rows.js +79 -41
- package/build/src/akuma/heart/soul.js +1 -1
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +76 -11
- package/build/src/akuma/heart/tells.js +35 -18
- package/build/src/akuma/heart/timeline.js +19 -11
- package/build/src/akuma/identity.d.ts +1 -0
- package/build/src/akuma/identity.js +1 -0
- package/build/src/akuma/index.d.ts +3 -3
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/nuke.js +106 -14
- package/build/src/akuma/projection-read.d.ts +17 -0
- package/build/src/akuma/projection-read.js +135 -0
- package/build/src/akuma/projection.d.ts +1 -16
- package/build/src/akuma/projection.js +77 -154
- package/build/src/akuma/provider-recipe.js +11 -5
- package/build/src/akuma/provider.js +105 -62
- package/build/src/akuma/providers/acp/config.js +5 -6
- package/build/src/akuma/providers/acp/core.js +17 -10
- package/build/src/akuma/providers/acp/events.js +38 -29
- package/build/src/akuma/providers/acp/index.js +13 -9
- package/build/src/akuma/providers/claude/events.js +8 -12
- package/build/src/akuma/providers/claude/index.d.ts +1 -0
- package/build/src/akuma/providers/claude/index.js +55 -26
- package/build/src/akuma/providers/claude/input.js +6 -2
- package/build/src/akuma/providers/codex-app-server/events.js +61 -36
- package/build/src/akuma/providers/codex-app-server/index.js +25 -13
- package/build/src/akuma/providers/grok-build/index.js +22 -25
- package/build/src/akuma/providers/index.js +2 -18
- package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
- package/build/src/akuma/providers/opencode-sdk/index.js +26 -17
- package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
- package/build/src/akuma/providers/pi/events.js +26 -19
- package/build/src/akuma/providers/pi/index.js +58 -40
- package/build/src/akuma/publication.js +9 -9
- package/build/src/akuma/request-execution.d.ts +6 -0
- package/build/src/akuma/request-execution.js +86 -0
- package/build/src/akuma/request-serve.d.ts +12 -1
- package/build/src/akuma/request-serve.js +19 -122
- package/build/src/akuma/request-wire.d.ts +2 -2
- package/build/src/akuma/request-wire.js +75 -102
- package/build/src/akuma/requests.js +2 -2
- package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +2 -25
- package/build/src/akuma/{body-turn.js → turn-drive.js} +20 -103
- package/build/src/akuma-body.js +6 -5
- package/build/src/body/amend.d.ts +4 -1
- package/build/src/body/amend.js +14 -6
- package/build/src/body/decode.js +2 -4
- package/build/src/body/envelope.js +2 -4
- package/build/src/body/region.d.ts +1 -2
- package/build/src/body/region.js +2 -70
- package/build/src/body/render.js +17 -12
- package/build/src/body/shape.js +1 -7
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +8 -1
- package/build/src/cli/commands/akuma-invoke.js +18 -6
- package/build/src/cli/commands/akuma.d.ts +0 -6
- package/build/src/cli/commands/akuma.js +11 -24
- package/build/src/cli/commands/amend.d.ts +2 -2
- package/build/src/cli/commands/amend.js +2 -4
- package/build/src/cli/commands/bind.d.ts +4 -4
- package/build/src/cli/commands/bind.js +16 -6
- package/build/src/cli/commands/contract-invoke.d.ts +25 -0
- package/build/src/cli/commands/contract-invoke.js +193 -0
- package/build/src/cli/commands/contract.d.ts +109 -10
- package/build/src/cli/commands/contract.js +339 -16
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +23 -15
- package/build/src/cli/commands/task-invoke.js +187 -67
- package/build/src/cli/commands/task-query.js +48 -24
- package/build/src/cli/commands/task.js +150 -38
- package/build/src/cli/coordinates.js +2 -4
- package/build/src/cli/invoke.js +92 -208
- package/build/src/cli/main.js +4 -2
- package/build/src/cli/parse.d.ts +3 -90
- package/build/src/cli/parse.js +27 -233
- package/build/src/cli/render/akuma-activity.d.ts +38 -0
- package/build/src/cli/render/akuma-activity.js +362 -0
- package/build/src/cli/render/akuma-tool-command.js +6 -7
- package/build/src/cli/render/akuma-tool.js +10 -8
- package/build/src/cli/render/akuma.d.ts +1 -1
- package/build/src/cli/render/akuma.js +61 -353
- package/build/src/cli/render/audit.js +5 -15
- package/build/src/cli/render/board.d.ts +1 -0
- package/build/src/cli/render/board.js +17 -0
- package/build/src/cli/render/catalog.js +81 -8
- package/build/src/cli/render/contract-history.d.ts +2 -0
- package/build/src/cli/render/contract-history.js +83 -0
- package/build/src/cli/render/contract-observation.d.ts +10 -0
- package/build/src/cli/render/contract-observation.js +58 -0
- package/build/src/cli/render/contract.d.ts +1 -2
- package/build/src/cli/render/contract.js +41 -142
- package/build/src/cli/render/kanshi.js +239 -215
- package/build/src/cli/render/receipt.js +2 -9
- package/build/src/cli/render/refusal.js +10 -15
- package/build/src/cli/render/region.js +22 -6
- package/build/src/cli/render/settings.js +4 -4
- package/build/src/cli/render/task.js +34 -14
- package/build/src/cli/render/terminal.js +16 -5
- package/build/src/cli/result.d.ts +3 -3
- package/build/src/cli/runtime.d.ts +6 -1
- package/build/src/cli/runtime.js +84 -63
- package/build/src/cli/selectors.js +2 -4
- package/build/src/cli/usage.js +6 -5
- package/build/src/contract-worktree.d.ts +1 -23
- package/build/src/contract-worktree.js +79 -155
- package/build/src/coordination/durable-file.js +7 -3
- package/build/src/coordination/sqlite-transaction-lock.js +29 -12
- package/build/src/core/facts/codec.js +7 -3
- package/build/src/core/facts/types.d.ts +1 -1
- package/build/src/core/subject.js +16 -9
- package/build/src/core/verbs/abandon.d.ts +1 -1
- package/build/src/core/verbs/abandon.js +1 -1
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +7 -7
- package/build/src/core/verbs/attestation.js +4 -1
- package/build/src/core/verbs/bind.d.ts +1 -1
- package/build/src/core/verbs/bind.js +1 -1
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +10 -8
- package/build/src/dispatch/index.js +8 -6
- package/build/src/duration.js +5 -1
- package/build/src/git/admission.js +5 -3
- package/build/src/git/hooks.d.ts +8 -0
- package/build/src/git/hooks.js +63 -14
- package/build/src/git/identity.js +1 -4
- package/build/src/git/integration.d.ts +2 -3
- package/build/src/git/integration.js +32 -39
- package/build/src/git/nuke.d.ts +1 -1
- package/build/src/git/nuke.js +110 -57
- package/build/src/git/observe.d.ts +13 -1
- package/build/src/git/observe.js +51 -44
- package/build/src/git/process.js +4 -2
- package/build/src/git/read-observation.js +10 -8
- package/build/src/git/reconcile.d.ts +22 -2
- package/build/src/git/reconcile.js +38 -274
- package/build/src/git/repository.d.ts +2 -0
- package/build/src/git/repository.js +13 -22
- package/build/src/git/scratch.d.ts +8 -5
- package/build/src/git/scratch.js +29 -2
- package/build/src/git/target-placement.d.ts +9 -10
- package/build/src/git/target-placement.js +59 -62
- package/build/src/git/tender.js +13 -46
- package/build/src/git/terminal-reconcile.d.ts +21 -0
- package/build/src/git/terminal-reconcile.js +278 -0
- package/build/src/git/terminal-seal.js +15 -12
- package/build/src/git/tree.js +5 -2
- package/build/src/git/workspace.d.ts +24 -2
- package/build/src/git/workspace.js +120 -16
- package/build/src/identity/coordinates.js +3 -1
- package/build/src/identity/selector.js +6 -3
- package/build/src/kanshi/fleet.d.ts +6 -0
- package/build/src/kanshi/fleet.js +27 -0
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +60 -48
- package/build/src/kanshi/report.d.ts +11 -23
- package/build/src/kanshi/select.js +25 -24
- package/build/src/library/address.d.ts +2 -1
- package/build/src/library/address.js +7 -8
- package/build/src/library/akuma-creation.js +20 -12
- package/build/src/library/audit.d.ts +0 -1
- package/build/src/library/audit.js +1 -2
- package/build/src/library/bind.d.ts +53 -5
- package/build/src/library/bind.js +98 -22
- package/build/src/library/catalog.d.ts +1 -0
- package/build/src/library/catalog.js +6 -3
- package/build/src/library/configuration.js +3 -1
- package/build/src/library/continuation.d.ts +15 -4
- package/build/src/library/continuation.js +24 -16
- package/build/src/library/contract-bind.d.ts +26 -0
- package/build/src/library/contract-bind.js +106 -0
- package/build/src/library/contract-operations.d.ts +77 -0
- package/build/src/library/contract-operations.js +130 -0
- package/build/src/library/contract-types.d.ts +95 -0
- package/build/src/library/contract-types.js +1 -0
- package/build/src/library/contract.d.ts +19 -154
- package/build/src/library/contract.js +46 -261
- package/build/src/library/fleet.d.ts +1 -1
- package/build/src/library/fleet.js +19 -11
- package/build/src/library/input.d.ts +2 -0
- package/build/src/library/input.js +14 -0
- package/build/src/library/keiyaku.d.ts +8 -7
- package/build/src/library/keiyaku.js +3 -3
- package/build/src/library/nuke.js +14 -5
- package/build/src/library/reconcile.d.ts +9 -4
- package/build/src/library/reconcile.js +30 -24
- package/build/src/library/refusal.d.ts +13 -5
- package/build/src/library/refusal.js +7 -0
- package/build/src/library/region.d.ts +8 -7
- package/build/src/library/region.js +31 -11
- package/build/src/library/repo.js +2 -2
- package/build/src/markdown/lex.js +9 -2
- package/build/src/markdown/parse.js +11 -7
- package/build/src/markdown/query.js +4 -2
- package/build/src/protocol/amend.js +3 -1
- package/build/src/protocol/attempt.d.ts +7 -3
- package/build/src/protocol/attempt.js +9 -5
- package/build/src/protocol/audit.d.ts +1 -1
- package/build/src/protocol/audit.js +4 -14
- package/build/src/protocol/bind.d.ts +19 -6
- package/build/src/protocol/bind.js +28 -13
- package/build/src/protocol/completion.d.ts +0 -1
- package/build/src/protocol/completion.js +1 -3
- package/build/src/protocol/deliver.d.ts +1 -3
- package/build/src/protocol/deliver.js +15 -39
- package/build/src/protocol/intent.d.ts +1 -0
- package/build/src/protocol/intent.js +9 -7
- package/build/src/protocol/operations.d.ts +3 -7
- package/build/src/protocol/operations.js +5 -3
- package/build/src/protocol/placement.d.ts +0 -1
- package/build/src/protocol/placement.js +6 -6
- package/build/src/protocol/read/observation.d.ts +11 -0
- package/build/src/protocol/read/observation.js +37 -0
- package/build/src/protocol/read/status.d.ts +23 -12
- package/build/src/protocol/read/status.js +90 -72
- package/build/src/protocol/reconcile.d.ts +1 -0
- package/build/src/protocol/reconcile.js +2 -3
- package/build/src/protocol/reintegrate.js +1 -1
- package/build/src/protocol/review.d.ts +0 -1
- package/build/src/protocol/review.js +15 -22
- package/build/src/protocol/run.d.ts +1 -0
- package/build/src/protocol/run.js +4 -5
- package/build/src/runtime/proc/launch.d.ts +33 -0
- package/build/src/runtime/proc/launch.js +98 -0
- package/build/src/runtime/proc/line-rpc.js +9 -3
- package/build/src/runtime/proc/run.d.ts +12 -6
- package/build/src/runtime/proc/run.js +78 -21
- package/build/src/runtime/proc/stdio.js +7 -10
- package/build/src/settings.js +6 -2
- package/build/src/settlement/holder.js +13 -10
- package/build/src/settlement/settle.js +39 -6
- package/build/src/task/board.js +12 -6
- package/build/src/task/compose.js +85 -22
- package/build/src/task/context.js +21 -8
- package/build/src/task/document.js +46 -10
- package/build/src/task/identity.js +5 -2
- package/build/src/task/index.d.ts +0 -1
- package/build/src/task/index.js +119 -34
- package/build/src/task/input.js +29 -7
- package/build/src/task/mutation.js +61 -19
- package/build/src/task/operations.d.ts +6 -1
- package/build/src/task/operations.js +83 -29
- package/build/src/task/query.js +55 -26
- package/build/src/task/store.d.ts +3 -1
- package/build/src/task/store.js +81 -17
- package/build/src/verification/execution.js +14 -11
- package/build/src/workspace-place.js +19 -7
- package/build/src/world.js +16 -6
- package/package.json +8 -3
|
@@ -6,15 +6,21 @@ import { parseTreeObject, prepareTreeUpdate, treeUpdate, validPath, } from "./tr
|
|
|
6
6
|
export const GIT_REF = "refs/heads/keiyaku-state";
|
|
7
7
|
export const DELIVERY_REF_NAMESPACE = "refs/heads/keiyaku-delivery";
|
|
8
8
|
export const CANDIDATE_PIN_REF_NAMESPACE = "refs/heads/keiyaku-candidate";
|
|
9
|
+
export const MIGRATION_DELIVERY_REF_NAMESPACE = "refs/keiyaku/delivery";
|
|
10
|
+
export const MIGRATION_CANDIDATE_PIN_REF_NAMESPACE = "refs/keiyaku/candidate";
|
|
9
11
|
export const GIT_FORMAT_PATH = "meta/format.json";
|
|
10
12
|
const CURRENT_FORMAT_VERSION = 4;
|
|
11
13
|
export const GIT_FORMAT_BYTES = `{"version":${CURRENT_FORMAT_VERSION}}\n`;
|
|
12
14
|
export function isKeiyakuOwnedRef(ref) {
|
|
13
|
-
return ref === GIT_REF
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
return (ref === GIT_REF ||
|
|
16
|
+
ref === DELIVERY_REF_NAMESPACE ||
|
|
17
|
+
ref.startsWith(`${DELIVERY_REF_NAMESPACE}/`) ||
|
|
18
|
+
ref === CANDIDATE_PIN_REF_NAMESPACE ||
|
|
19
|
+
ref.startsWith(`${CANDIDATE_PIN_REF_NAMESPACE}/`) ||
|
|
20
|
+
ref === MIGRATION_DELIVERY_REF_NAMESPACE ||
|
|
21
|
+
ref.startsWith(`${MIGRATION_DELIVERY_REF_NAMESPACE}/`) ||
|
|
22
|
+
ref === MIGRATION_CANDIDATE_PIN_REF_NAMESPACE ||
|
|
23
|
+
ref.startsWith(`${MIGRATION_CANDIDATE_PIN_REF_NAMESPACE}/`));
|
|
18
24
|
}
|
|
19
25
|
export class NoGitWorldError extends Error {
|
|
20
26
|
path;
|
|
@@ -181,15 +187,7 @@ export async function readGitPaths(repository, requestedPaths) {
|
|
|
181
187
|
if (commit === null)
|
|
182
188
|
return { commit: null, tree: null, paths: new Map() };
|
|
183
189
|
const tree = await readTreeForCommit(repository, commit);
|
|
184
|
-
const paths = parseTreeEntries(await runGit(repository, [
|
|
185
|
-
"ls-tree",
|
|
186
|
-
"-z",
|
|
187
|
-
"--full-tree",
|
|
188
|
-
tree,
|
|
189
|
-
"--",
|
|
190
|
-
GIT_FORMAT_PATH,
|
|
191
|
-
...requestedPaths,
|
|
192
|
-
]));
|
|
190
|
+
const paths = parseTreeEntries(await runGit(repository, ["ls-tree", "-z", "--full-tree", tree, "--", GIT_FORMAT_PATH, ...requestedPaths]));
|
|
193
191
|
await validateGitFormat(repository, paths);
|
|
194
192
|
return { commit, tree, paths };
|
|
195
193
|
}
|
|
@@ -394,14 +392,7 @@ export async function updateRefsAtomically(repository, updates, assertions = [])
|
|
|
394
392
|
if (git === undefined || git.ref !== GIT_REF) {
|
|
395
393
|
throw new Error(`the first atomic update must be the Git ref: ${GIT_REF}`);
|
|
396
394
|
}
|
|
397
|
-
const lines = [
|
|
398
|
-
"start",
|
|
399
|
-
...assertions.map(refAssertionLine),
|
|
400
|
-
...updates.map(refUpdateLine),
|
|
401
|
-
"prepare",
|
|
402
|
-
"commit",
|
|
403
|
-
"",
|
|
404
|
-
];
|
|
395
|
+
const lines = ["start", ...assertions.map(refAssertionLine), ...updates.map(refUpdateLine), "prepare", "commit", ""];
|
|
405
396
|
try {
|
|
406
397
|
await runGit(repository, ["update-ref", "--stdin"], lines.join("\n"));
|
|
407
398
|
return { kind: "published" };
|
|
@@ -4,14 +4,17 @@ export type MaterializedScratchCandidate = Readonly<{
|
|
|
4
4
|
cwd: string;
|
|
5
5
|
dispose: () => Promise<WorktreeLeak | null>;
|
|
6
6
|
}>;
|
|
7
|
-
export type CollectableScratchWorktree = Readonly<{
|
|
8
|
-
path: string;
|
|
9
|
-
release(): void;
|
|
10
|
-
}>;
|
|
11
7
|
export type WorktreeLeak = Readonly<{
|
|
12
8
|
path: string;
|
|
13
9
|
diagnostic: string;
|
|
14
10
|
}>;
|
|
15
|
-
|
|
11
|
+
type CollectableScratchRemoval = Readonly<{
|
|
12
|
+
path: string;
|
|
13
|
+
action: "removed" | "unchanged";
|
|
14
|
+
retained: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
/** Remove only abandoned Verification scratch worktrees whose ownership locks are held. */
|
|
17
|
+
export declare function removeCollectableScratchWorktrees(repository: GitRepository, paths: Set<string>): Promise<readonly CollectableScratchRemoval[]>;
|
|
16
18
|
/** Materialize a disposable candidate worktree and own only its removal. */
|
|
17
19
|
export declare function materializeScratchCandidate(repository: GitRepository, candidate: SnapshotId): Promise<MaterializedScratchCandidate>;
|
|
20
|
+
export {};
|
package/build/src/git/scratch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { realpath } from "node:fs/promises";
|
|
2
|
+
import { access, realpath } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { basename, dirname, join } from "node:path";
|
|
5
5
|
import { tryAcquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
|
|
@@ -17,7 +17,7 @@ function ownershipLockPath(path) {
|
|
|
17
17
|
const match = SCRATCH_PATTERN.exec(basename(path));
|
|
18
18
|
return match === null ? null : join(SCRATCH_ROOT, `.${SCRATCH_PREFIX}${match[1]}.owner.sqlite`);
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
async function collectableScratchWorktrees(paths) {
|
|
21
21
|
const collectable = [];
|
|
22
22
|
for (const path of paths) {
|
|
23
23
|
const lockPath = ownershipLockPath(path);
|
|
@@ -29,6 +29,33 @@ export async function collectableScratchWorktrees(paths) {
|
|
|
29
29
|
}
|
|
30
30
|
return collectable;
|
|
31
31
|
}
|
|
32
|
+
const pathExists = (path) => access(path).then(() => true, () => false);
|
|
33
|
+
/** Remove only abandoned Verification scratch worktrees whose ownership locks are held. */
|
|
34
|
+
export async function removeCollectableScratchWorktrees(repository, paths) {
|
|
35
|
+
const removals = [];
|
|
36
|
+
for (const scratch of await collectableScratchWorktrees(paths)) {
|
|
37
|
+
try {
|
|
38
|
+
if (!(await pathExists(scratch.path))) {
|
|
39
|
+
await runGit(repository, ["worktree", "remove", scratch.path]);
|
|
40
|
+
paths.delete(scratch.path);
|
|
41
|
+
removals.push({ path: scratch.path, action: "removed", retained: false });
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await runGit(repository, ["worktree", "remove", "--force", scratch.path]);
|
|
46
|
+
paths.delete(scratch.path);
|
|
47
|
+
removals.push({ path: scratch.path, action: "removed", retained: false });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
removals.push({ path: scratch.path, action: "unchanged", retained: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
scratch.release();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return removals;
|
|
58
|
+
}
|
|
32
59
|
/** Materialize a disposable candidate worktree and own only its removal. */
|
|
33
60
|
export async function materializeScratchCandidate(repository, candidate) {
|
|
34
61
|
const cwd = scratchPath();
|
|
@@ -2,12 +2,6 @@ import { type HeldSqliteTransactionLock } from "../coordination/sqlite-transacti
|
|
|
2
2
|
import type { ContractId, ContractState, SnapshotId } from "../core/facts/types.js";
|
|
3
3
|
import type { RefOperation } from "../core/facts/offer.js";
|
|
4
4
|
import { type GitRepository } from "./process.js";
|
|
5
|
-
export type WorkspaceNotOnTargetRefusal = Readonly<{
|
|
6
|
-
kind: "workspace-not-on-target";
|
|
7
|
-
contractId: ContractId;
|
|
8
|
-
target: string;
|
|
9
|
-
branch: string | null;
|
|
10
|
-
}>;
|
|
11
5
|
export type CheckoutNotFollowableRefusal = Readonly<{
|
|
12
6
|
kind: "checkout-not-followable";
|
|
13
7
|
contractId: ContractId;
|
|
@@ -16,7 +10,7 @@ export type CheckoutNotFollowableRefusal = Readonly<{
|
|
|
16
10
|
reason: "staged" | "conflict" | "untracked";
|
|
17
11
|
paths: readonly string[];
|
|
18
12
|
}>;
|
|
19
|
-
export type TargetPlacementRefusal = CheckoutNotFollowableRefusal
|
|
13
|
+
export type TargetPlacementRefusal = CheckoutNotFollowableRefusal;
|
|
20
14
|
export type TargetCheckoutEffect = Readonly<{
|
|
21
15
|
kind: "target-checkout";
|
|
22
16
|
path: string;
|
|
@@ -34,7 +28,7 @@ export type TargetPlacementPhysicalResult = Readonly<{
|
|
|
34
28
|
lag: readonly TargetCheckoutLag[];
|
|
35
29
|
}>;
|
|
36
30
|
type FollowArm = Readonly<{
|
|
37
|
-
kind: "ordinary"
|
|
31
|
+
kind: "ordinary";
|
|
38
32
|
path: string;
|
|
39
33
|
}>;
|
|
40
34
|
export type PreparedTargetPlacement = Readonly<{
|
|
@@ -58,7 +52,6 @@ export type TargetPlacementObservationInput = Readonly<{
|
|
|
58
52
|
coordinates: TargetedContractCoordinates;
|
|
59
53
|
predecessor: SnapshotId;
|
|
60
54
|
candidate: SnapshotId;
|
|
61
|
-
hereWorkspacePath?: string;
|
|
62
55
|
}>;
|
|
63
56
|
export type TargetPlacementObservation = Readonly<{
|
|
64
57
|
kind: "ready";
|
|
@@ -87,7 +80,13 @@ export type AuditTargetAnswer = Readonly<{
|
|
|
87
80
|
}>;
|
|
88
81
|
/** Adjudicate the complete post-Verification audit target answer without placing. */
|
|
89
82
|
export declare function adjudicateAuditTarget(repository: GitRepository, input: TargetPlacementObservationInput): Promise<AuditTargetAnswer>;
|
|
90
|
-
export declare function prepareTargetPlacement(repository: GitRepository, state: ContractState, target: RefOperation
|
|
83
|
+
export declare function prepareTargetPlacement(repository: GitRepository, state: ContractState, target: RefOperation): Promise<TargetPlacementPreparation>;
|
|
91
84
|
export declare function followTargetPlacement(repository: GitRepository, prepared: PreparedTargetPlacement): Promise<TargetPlacementPhysicalResult>;
|
|
85
|
+
/** Judge the target-checkout shape without mutating refs, worktrees, or indexes. */
|
|
86
|
+
export declare function observeTargetCheckoutShape(repository: GitRepository, input: Readonly<{
|
|
87
|
+
path: string;
|
|
88
|
+
predecessor: SnapshotId;
|
|
89
|
+
candidate: SnapshotId;
|
|
90
|
+
}>): Promise<"complete" | "recoverable" | "retained">;
|
|
92
91
|
export declare function recoverTargetPlacement(repository: GitRepository, state: ContractState): Promise<TargetPlacementPhysicalResult>;
|
|
93
92
|
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { lstat } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { acquireSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
|
|
3
|
+
import { acquireSqliteTransactionLock, } from "../coordination/sqlite-transaction-lock.js";
|
|
4
4
|
import { gitObjectId, gitObjectIdForSnapshot, gitRefLocator, mintSnapshotId } from "./identity.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { consumeGitStdout, GitPlumbingError, runGit, } from "./process.js";
|
|
5
|
+
import { commonGitDirectory, readRef, registeredWorktrees } from "./repository.js";
|
|
6
|
+
import { consumeGitStdout, GitPlumbingError, runGit } from "./process.js";
|
|
8
7
|
import { captureWorkspaceTree } from "./workspace.js";
|
|
9
8
|
export async function observeTargetHead(repository, target) {
|
|
10
9
|
const value = await readRef(repository, target);
|
|
@@ -26,9 +25,7 @@ function literalPath(path) {
|
|
|
26
25
|
return `:(literal)${path}`;
|
|
27
26
|
}
|
|
28
27
|
async function commitTree(repository, snapshot) {
|
|
29
|
-
return gitObjectId((await runGit(repository, ["show", "-s", "--format=%T", gitObjectIdForSnapshot(snapshot)]))
|
|
30
|
-
.toString("utf8")
|
|
31
|
-
.trim(), "commit tree");
|
|
28
|
+
return gitObjectId((await runGit(repository, ["show", "-s", "--format=%T", gitObjectIdForSnapshot(snapshot)])).toString("utf8").trim(), "commit tree");
|
|
32
29
|
}
|
|
33
30
|
function checkoutRefusal(contractId, target, path, reason, paths) {
|
|
34
31
|
return { kind: "checkout-not-followable", contractId, target: target.target, path, reason, paths };
|
|
@@ -64,11 +61,18 @@ async function dryRunRefusal(input, scopes) {
|
|
|
64
61
|
const dirty = await gitPaths(repository, path, ["diff-files", "--name-only", "-z", "--", ...pathspecs]);
|
|
65
62
|
if (dirty.length > 0)
|
|
66
63
|
return checkoutRefusal(contractId, target, path, "conflict", dirty);
|
|
67
|
-
const unmerged = await gitPaths(repository, path, [
|
|
64
|
+
const unmerged = await gitPaths(repository, path, [
|
|
65
|
+
"diff",
|
|
66
|
+
"--name-only",
|
|
67
|
+
"--diff-filter=U",
|
|
68
|
+
"-z",
|
|
69
|
+
"--",
|
|
70
|
+
...pathspecs,
|
|
71
|
+
]);
|
|
68
72
|
if (unmerged.length > 0)
|
|
69
73
|
return checkoutRefusal(contractId, target, path, "conflict", unmerged);
|
|
70
|
-
return await untrackedRefusalWithinScopes(input, scopes, false)
|
|
71
|
-
|
|
74
|
+
return ((await untrackedRefusalWithinScopes(input, scopes, false)) ??
|
|
75
|
+
checkoutRefusal(contractId, target, path, "conflict", []));
|
|
72
76
|
}
|
|
73
77
|
async function physicalScope(worktree, candidatePath) {
|
|
74
78
|
const components = candidatePath.split("/");
|
|
@@ -93,7 +97,10 @@ async function physicalScope(worktree, candidatePath) {
|
|
|
93
97
|
}
|
|
94
98
|
async function candidateEntryIsBlob(repository, path, candidate, candidatePath) {
|
|
95
99
|
const output = await runGit(repository, ["-C", path, "ls-tree", "-z", candidate, "--", literalPath(candidatePath)]);
|
|
96
|
-
const records = output
|
|
100
|
+
const records = output
|
|
101
|
+
.toString("utf8")
|
|
102
|
+
.split("\0")
|
|
103
|
+
.filter((record) => record.length > 0);
|
|
97
104
|
if (records.length !== 1)
|
|
98
105
|
throw new Error(`candidate path has no unique Git entry: ${candidatePath}`);
|
|
99
106
|
const separator = records[0].indexOf("\t");
|
|
@@ -142,13 +149,7 @@ async function untrackedRefusalWithinScopes(input, scopes, ignored) {
|
|
|
142
149
|
if (scope.kind !== "directory")
|
|
143
150
|
continue;
|
|
144
151
|
let found = false;
|
|
145
|
-
await consumeGitStdout(repository, [
|
|
146
|
-
"-C",
|
|
147
|
-
path,
|
|
148
|
-
...args,
|
|
149
|
-
"--",
|
|
150
|
-
literalPath(scope.path),
|
|
151
|
-
], (chunk) => {
|
|
152
|
+
await consumeGitStdout(repository, ["-C", path, ...args, "--", literalPath(scope.path)], (chunk) => {
|
|
152
153
|
if (chunk.length > 0)
|
|
153
154
|
found = true;
|
|
154
155
|
});
|
|
@@ -158,10 +159,11 @@ async function untrackedRefusalWithinScopes(input, scopes, ignored) {
|
|
|
158
159
|
return null;
|
|
159
160
|
}
|
|
160
161
|
async function indexMatchesTreeOnPaths(repository, path, tree, paths) {
|
|
161
|
-
return (await gitPaths(repository, path, ["diff-index", "--cached", "--name-only", "-z", tree, "--", ...paths])).length ===
|
|
162
|
+
return ((await gitPaths(repository, path, ["diff-index", "--cached", "--name-only", "-z", tree, "--", ...paths])).length ===
|
|
163
|
+
0);
|
|
162
164
|
}
|
|
163
165
|
async function workspaceMatchesTreeOnPaths(repository, path, tree, workspaceTree, paths) {
|
|
164
|
-
return (await gitPaths(repository, path, ["diff", "--name-only", "-z", tree, workspaceTree, "--", ...paths])).length === 0;
|
|
166
|
+
return ((await gitPaths(repository, path, ["diff", "--name-only", "-z", tree, workspaceTree, "--", ...paths])).length === 0);
|
|
165
167
|
}
|
|
166
168
|
async function ordinaryPrecheck(repository, contractId, target, path) {
|
|
167
169
|
const predecessor = gitObjectIdForSnapshot(target.expectedOid);
|
|
@@ -199,35 +201,13 @@ export async function observeTargetPlacement(repository, input) {
|
|
|
199
201
|
const worktrees = (await registeredWorktrees(repository))
|
|
200
202
|
.filter((worktree) => worktree.branch === target.target)
|
|
201
203
|
.sort((left, right) => left.path.localeCompare(right.path));
|
|
202
|
-
const hereSource = input.coordinates.workspace === "here" ? input.hereWorkspacePath ?? null : null;
|
|
203
|
-
if (hereSource !== null) {
|
|
204
|
-
const branch = await currentBranch(repository, hereSource);
|
|
205
|
-
if (branch !== target.target) {
|
|
206
|
-
return {
|
|
207
|
-
kind: "refused",
|
|
208
|
-
refusal: {
|
|
209
|
-
kind: "workspace-not-on-target",
|
|
210
|
-
contractId: input.contractId,
|
|
211
|
-
target: target.target,
|
|
212
|
-
branch,
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
204
|
const arms = [];
|
|
218
205
|
for (const worktree of worktrees) {
|
|
219
|
-
const
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return { kind: "refused", refusal };
|
|
224
|
-
}
|
|
225
|
-
arms.push({ kind, path: worktree.path });
|
|
206
|
+
const refusal = await ordinaryPrecheck(repository, input.contractId, target, worktree.path);
|
|
207
|
+
if (refusal !== null)
|
|
208
|
+
return { kind: "refused", refusal };
|
|
209
|
+
arms.push({ kind: "ordinary", path: worktree.path });
|
|
226
210
|
}
|
|
227
|
-
if (input.coordinates.workspace === "here" && hereSource === null)
|
|
228
|
-
throw new Error("targeted here workspace is unappointed");
|
|
229
|
-
if (hereSource !== null && !arms.some((arm) => arm.kind === "here"))
|
|
230
|
-
throw new Error("targeted here workspace is not a registered checkout of its target");
|
|
231
211
|
return { kind: "ready", arms };
|
|
232
212
|
}
|
|
233
213
|
/** Adjudicate the complete post-Verification audit target answer without placing. */
|
|
@@ -252,7 +232,7 @@ export async function adjudicateAuditTarget(repository, input) {
|
|
|
252
232
|
return { kind: "failed", diagnostic: error.message };
|
|
253
233
|
}
|
|
254
234
|
}
|
|
255
|
-
export async function prepareTargetPlacement(repository, state, target
|
|
235
|
+
export async function prepareTargetPlacement(repository, state, target) {
|
|
256
236
|
if (state.coordinates.target !== target.target || state.currentIntegration?.snapshot !== target.newOid) {
|
|
257
237
|
throw new Error("placement state does not match its offered target movement");
|
|
258
238
|
}
|
|
@@ -261,7 +241,6 @@ export async function prepareTargetPlacement(repository, state, target, hereWork
|
|
|
261
241
|
coordinates: { ...state.coordinates, target: target.target },
|
|
262
242
|
predecessor: target.expectedOid,
|
|
263
243
|
candidate: target.newOid,
|
|
264
|
-
...(hereWorkspacePath === undefined ? {} : { hereWorkspacePath }),
|
|
265
244
|
});
|
|
266
245
|
return observation.kind === "refused"
|
|
267
246
|
? observation
|
|
@@ -274,10 +253,7 @@ export async function followTargetPlacement(repository, prepared) {
|
|
|
274
253
|
const candidate = gitObjectIdForSnapshot(prepared.target.newOid);
|
|
275
254
|
for (const arm of prepared.arms) {
|
|
276
255
|
try {
|
|
277
|
-
|
|
278
|
-
await runGit(repository, ["-C", arm.path, "read-tree", candidate]);
|
|
279
|
-
else
|
|
280
|
-
await runGit(repository, ["-C", arm.path, "read-tree", "-m", "-u", predecessor, candidate]);
|
|
256
|
+
await runGit(repository, ["-C", arm.path, "read-tree", "-m", "-u", predecessor, candidate]);
|
|
281
257
|
effects.push({ kind: "target-checkout", path: arm.path, target: prepared.target.target, action: "followed" });
|
|
282
258
|
}
|
|
283
259
|
catch (error) {
|
|
@@ -294,22 +270,46 @@ export async function followTargetPlacement(repository, prepared) {
|
|
|
294
270
|
function recoveryLag(path, target, detail) {
|
|
295
271
|
return { kind: "target-checkout-retained", path, target, diagnostic: detail };
|
|
296
272
|
}
|
|
297
|
-
async function
|
|
298
|
-
const { repository, path,
|
|
273
|
+
async function classifyCheckout(input) {
|
|
274
|
+
const { repository, path, predecessorTree, candidateTree } = input;
|
|
299
275
|
const changedPaths = await gitPaths(repository, path, ["diff", "--name-only", "-z", predecessorTree, candidateTree]);
|
|
300
276
|
if (changedPaths.length === 0)
|
|
301
|
-
return "complete";
|
|
277
|
+
return { kind: "complete" };
|
|
302
278
|
const workspaceTree = (await captureWorkspaceTree(repository, path)).tree;
|
|
303
279
|
const candidateIndex = await indexMatchesTreeOnPaths(repository, path, candidateTree, changedPaths);
|
|
304
280
|
const candidateWorkspace = await workspaceMatchesTreeOnPaths(repository, path, candidateTree, workspaceTree, changedPaths);
|
|
305
281
|
if (candidateIndex && candidateWorkspace)
|
|
282
|
+
return { kind: "complete" };
|
|
283
|
+
if (workspaceTree === candidateTree)
|
|
284
|
+
return { kind: "recoverable", action: "candidate-index" };
|
|
285
|
+
const predecessorIndex = await indexMatchesTreeOnPaths(repository, path, predecessorTree, changedPaths);
|
|
286
|
+
if (predecessorIndex && candidateWorkspace)
|
|
287
|
+
return { kind: "recoverable", action: "index-merge" };
|
|
288
|
+
return !predecessorIndex ||
|
|
289
|
+
!(await workspaceMatchesTreeOnPaths(repository, path, predecessorTree, workspaceTree, changedPaths))
|
|
290
|
+
? { kind: "retained" }
|
|
291
|
+
: { kind: "recoverable", action: "worktree-merge" };
|
|
292
|
+
}
|
|
293
|
+
/** Judge the target-checkout shape without mutating refs, worktrees, or indexes. */
|
|
294
|
+
export async function observeTargetCheckoutShape(repository, input) {
|
|
295
|
+
const [predecessorTree, candidateTree] = await Promise.all([
|
|
296
|
+
commitTree(repository, input.predecessor),
|
|
297
|
+
commitTree(repository, input.candidate),
|
|
298
|
+
]);
|
|
299
|
+
return (await classifyCheckout({ repository, ...input, predecessorTree, candidateTree })).kind;
|
|
300
|
+
}
|
|
301
|
+
async function recoverCheckout(input) {
|
|
302
|
+
const classified = await classifyCheckout(input);
|
|
303
|
+
if (classified.kind === "complete")
|
|
306
304
|
return "complete";
|
|
307
|
-
if (
|
|
305
|
+
if (classified.kind === "retained")
|
|
306
|
+
return "retained";
|
|
307
|
+
const { repository, path, predecessor, candidate } = input;
|
|
308
|
+
if (classified.action === "candidate-index") {
|
|
308
309
|
await runGit(repository, ["-C", path, "read-tree", gitObjectIdForSnapshot(candidate)]);
|
|
309
310
|
return "recovered";
|
|
310
311
|
}
|
|
311
|
-
|
|
312
|
-
if (predecessorIndex && candidateWorkspace) {
|
|
312
|
+
if (classified.action === "index-merge") {
|
|
313
313
|
await runGit(repository, [
|
|
314
314
|
"-C",
|
|
315
315
|
path,
|
|
@@ -321,9 +321,6 @@ async function recoverCheckout(input) {
|
|
|
321
321
|
]);
|
|
322
322
|
return "recovered";
|
|
323
323
|
}
|
|
324
|
-
const predecessorWorkspace = await workspaceMatchesTreeOnPaths(repository, path, predecessorTree, workspaceTree, changedPaths);
|
|
325
|
-
if (!predecessorIndex || !predecessorWorkspace)
|
|
326
|
-
return "retained";
|
|
327
324
|
await runGit(repository, [
|
|
328
325
|
"-C",
|
|
329
326
|
path,
|
|
@@ -341,7 +338,7 @@ export async function recoverTargetPlacement(repository, state) {
|
|
|
341
338
|
if (state.terminal?.kind !== "claimed" || target === undefined || delivery === null)
|
|
342
339
|
return { effects: [], lag: [] };
|
|
343
340
|
const integration = state.currentIntegration;
|
|
344
|
-
if (integration === null || await readRef(repository, target) !== integration.snapshot)
|
|
341
|
+
if (integration === null || (await readRef(repository, target)) !== integration.snapshot)
|
|
345
342
|
return { effects: [], lag: [] };
|
|
346
343
|
const candidateTree = await commitTree(repository, integration.snapshot);
|
|
347
344
|
const predecessorTree = await commitTree(repository, integration.predecessor);
|
package/build/src/git/tender.js
CHANGED
|
@@ -1,46 +1,20 @@
|
|
|
1
1
|
import { access } from "node:fs/promises";
|
|
2
2
|
import { gitObjectIdForSnapshot, mintSnapshotId } from "./identity.js";
|
|
3
|
-
import { decodeGitNumstat, registeredWorktreePaths
|
|
4
|
-
import { GitPlumbingError, runGit, runGitWithEnvironment
|
|
5
|
-
import { captureWorkspaceTree, worktreePath } from "./workspace.js";
|
|
6
|
-
async function workspaceExists(repository,
|
|
3
|
+
import { decodeGitNumstat, registeredWorktreePaths } from "./repository.js";
|
|
4
|
+
import { GitPlumbingError, runGit, runGitWithEnvironment } from "./process.js";
|
|
5
|
+
import { captureWorkspaceTree, unmergedWorkspacePaths, workspaceMergeHead, worktreePath } from "./workspace.js";
|
|
6
|
+
async function workspaceExists(repository, path) {
|
|
7
7
|
const exists = await access(path).then(() => true, () => false);
|
|
8
|
-
return
|
|
9
|
-
|| (exists && (await registeredWorktreePaths(repository)).includes(path));
|
|
8
|
+
return exists && (await registeredWorktreePaths(repository)).includes(path);
|
|
10
9
|
}
|
|
11
10
|
function workspaceFor(repository, input) {
|
|
12
11
|
if (input.workspacePath !== undefined)
|
|
13
12
|
return input.workspacePath;
|
|
14
13
|
return input.place === undefined ? undefined : worktreePath(repository, input.place);
|
|
15
14
|
}
|
|
16
|
-
async function workspaceMergeHead(repository, workspace) {
|
|
17
|
-
try {
|
|
18
|
-
return mintSnapshotId((await runGit(repository, ["-C", workspace, "rev-parse", "-q", "--verify", "MERGE_HEAD"]))
|
|
19
|
-
.toString("utf8")
|
|
20
|
-
.trim());
|
|
21
|
-
}
|
|
22
|
-
catch (error) {
|
|
23
|
-
if (error instanceof GitPlumbingError && error.status === 1)
|
|
24
|
-
return undefined;
|
|
25
|
-
throw error;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function unmergedWorkspacePaths(repository, workspace) {
|
|
29
|
-
const records = (await runGit(repository, ["-C", workspace, "ls-files", "--unmerged", "-z"]))
|
|
30
|
-
.toString("utf8")
|
|
31
|
-
.split("\0");
|
|
32
|
-
const paths = new Set();
|
|
33
|
-
for (const record of records.slice(0, -1)) {
|
|
34
|
-
const separator = record.indexOf("\t");
|
|
35
|
-
if (separator < 0)
|
|
36
|
-
throw new Error(`malformed unmerged index record: ${record}`);
|
|
37
|
-
paths.add(record.slice(separator + 1));
|
|
38
|
-
}
|
|
39
|
-
return [...paths].sort();
|
|
40
|
-
}
|
|
41
15
|
export async function captureTender(repository, input) {
|
|
42
16
|
const workspace = workspaceFor(repository, input);
|
|
43
|
-
if (workspace === undefined || !(await workspaceExists(repository,
|
|
17
|
+
if (workspace === undefined || !(await workspaceExists(repository, workspace))) {
|
|
44
18
|
return { kind: "refused", refusal: { kind: "worktree-missing", contractId: input.contractId } };
|
|
45
19
|
}
|
|
46
20
|
if (input.rejectUnmerged === true) {
|
|
@@ -49,22 +23,14 @@ export async function captureTender(repository, input) {
|
|
|
49
23
|
return { kind: "refused", refusal: { kind: "unmerged-paths", contractId: input.contractId, paths } };
|
|
50
24
|
}
|
|
51
25
|
const captured = await captureWorkspaceTree(repository, workspace);
|
|
52
|
-
const mergeHead = input.captureMergeState === true
|
|
53
|
-
? await workspaceMergeHead(repository, workspace)
|
|
54
|
-
: undefined;
|
|
26
|
+
const mergeHead = input.captureMergeState === true ? await workspaceMergeHead(repository, workspace) : undefined;
|
|
55
27
|
return {
|
|
56
28
|
kind: "prepared",
|
|
57
29
|
data: { ...captured, ...(mergeHead === undefined ? {} : { mergeHead }) },
|
|
58
30
|
};
|
|
59
31
|
}
|
|
60
32
|
async function dirtyShortStat(repository, tender) {
|
|
61
|
-
return decodeGitNumstat(await runGit(repository, [
|
|
62
|
-
"diff",
|
|
63
|
-
"--numstat",
|
|
64
|
-
"-z",
|
|
65
|
-
gitObjectIdForSnapshot(tender.head),
|
|
66
|
-
tender.tree,
|
|
67
|
-
]));
|
|
33
|
+
return decodeGitNumstat(await runGit(repository, ["diff", "--numstat", "-z", gitObjectIdForSnapshot(tender.head), tender.tree]));
|
|
68
34
|
}
|
|
69
35
|
export async function dirtyTenderRefusal(repository, contractId, tender) {
|
|
70
36
|
return {
|
|
@@ -104,9 +70,8 @@ export async function prepareDeliveryCommitMetadata(repository, input) {
|
|
|
104
70
|
effectiveConfig(repository, "user.name"),
|
|
105
71
|
effectiveConfig(repository, "user.email"),
|
|
106
72
|
]);
|
|
107
|
-
identity =
|
|
108
|
-
? { name, email }
|
|
109
|
-
: { name: "Keiyaku", email: "keiyaku@localhost" };
|
|
73
|
+
identity =
|
|
74
|
+
name !== undefined && email !== undefined ? { name, email } : { name: "Keiyaku", email: "keiyaku@localhost" };
|
|
110
75
|
}
|
|
111
76
|
const subject = input.message ?? `${input.contractId}: ${input.title}`;
|
|
112
77
|
return {
|
|
@@ -129,6 +94,8 @@ export async function materializeTenderSnapshot(repository, tender, commit) {
|
|
|
129
94
|
GIT_COMMITTER_EMAIL: commit.identity.email,
|
|
130
95
|
GIT_AUTHOR_DATE: commit.at,
|
|
131
96
|
GIT_COMMITTER_DATE: commit.at,
|
|
132
|
-
}))
|
|
97
|
+
}))
|
|
98
|
+
.toString("utf8")
|
|
99
|
+
.trim();
|
|
133
100
|
return mintSnapshotId(oid);
|
|
134
101
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ContractState, SnapshotId } from "../core/facts/types.js";
|
|
2
|
+
import type { GitDecodeChannel } from "./read-observation.js";
|
|
3
|
+
import { type WorktreeHooks } from "./hooks.js";
|
|
4
|
+
import { type GitRepository } from "./process.js";
|
|
5
|
+
import type { Effect, ReconcileAccumulation, ReconcileResult, WorktreeTopology } from "./reconcile.js";
|
|
6
|
+
type TerminalReconcileInput = Readonly<{
|
|
7
|
+
repository: GitRepository;
|
|
8
|
+
channel: GitDecodeChannel;
|
|
9
|
+
hooks: WorktreeHooks;
|
|
10
|
+
retryHooks: boolean;
|
|
11
|
+
retainTerminalWorktree?: boolean;
|
|
12
|
+
place?: string;
|
|
13
|
+
}>;
|
|
14
|
+
type TerminalCustodyRefs = Readonly<{
|
|
15
|
+
ref: string;
|
|
16
|
+
pin: string;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function updateRef(repository: GitRepository, ref: string, desired: SnapshotId): Promise<Effect>;
|
|
19
|
+
export declare function removeRef(repository: GitRepository, ref: string): Promise<Effect>;
|
|
20
|
+
export declare function reconcileTerminalManagedWorktree({ repository, channel, hooks, retryHooks, retainTerminalWorktree, place }: TerminalReconcileInput, state: ContractState, topology: WorktreeTopology, acc: ReconcileAccumulation, { ref, pin }: TerminalCustodyRefs): Promise<ReconcileResult>;
|
|
21
|
+
export {};
|