@astrosheep/keiyaku 2.9.3 → 2.9.5
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/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +14 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +26 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +68 -5
- package/build/agents/harness/projection.js +179 -124
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +82 -53
- package/build/agents/providers/codex-app-server/events.js +90 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +10 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +8 -2
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +44 -8
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +5 -8
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +6 -5
- package/build/cli/commands/metadata.js +59 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +8 -3
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +7 -15
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +12 -8
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +6 -11
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +37 -6
- package/build/cli/help.js +7 -14
- package/build/cli/index.js +112 -154
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +33 -7
- package/build/cli/parse-metadata.js +3 -9
- package/build/cli/parse-selectors.js +2 -1
- package/build/cli/parse.js +35 -5
- package/build/cli/projection-address.js +12 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +58 -13
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +15 -6
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +56 -23
- package/build/cli/render/success-response.js +78 -0
- package/build/cli/render/task.js +66 -57
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +63 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +68 -38
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +3 -0
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +61 -18
- package/build/core/arc.js +33 -73
- package/build/core/audit.js +650 -0
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +22 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +22 -6
- package/build/core/draft.js +139 -19
- package/build/core/entry.js +3 -4
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/lex.js +2 -1
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +41 -52
- package/build/core/projection/generation/model.js +63 -2
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
- package/build/core/projection/generation/store.js +3 -3
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
- package/build/core/projection/projection-terminal-failure.js +106 -0
- package/build/core/projection/projection-wait.js +275 -0
- package/build/core/projection/projection-wake.js +227 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +448 -102
- package/build/core/scope.js +272 -68
- package/build/core/seal.js +165 -40
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
- package/build/core/{petition.js → settlement/petition.js} +21 -12
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +288 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +62 -41
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +6 -2
- package/build/core/task/board.js +41 -4
- package/build/core/task/commands.js +45 -28
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +12 -0
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +172 -0
- package/build/core/task/settlement-git.js +265 -74
- package/build/core/task/settlement-policy.js +67 -29
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +444 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +7 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +83 -39
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +9 -9
- package/build/keiyaku.js +2 -36
- package/build/telemetry/logger.js +4 -2
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +5 -4
- package/skills/keiyaku-akuma/SKILL.md +25 -11
- package/skills/keiyaku-task/SKILL.md +17 -8
- package/skills/keiyaku-workflow/SKILL.md +58 -9
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -1,185 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
z.number(),
|
|
6
|
-
z.boolean(),
|
|
7
|
-
z.array(tomlValueSchema),
|
|
8
|
-
z.record(z.string(), tomlValueSchema),
|
|
9
|
-
]));
|
|
10
|
-
const structuredTomlValueSchema = z.record(z.string(), tomlValueSchema);
|
|
11
|
-
const executableSchema = z.string().superRefine((value, ctx) => {
|
|
12
|
-
if (value.length === 0 || /\s/.test(value) || value.includes("\"") || value.includes("'")) {
|
|
13
|
-
ctx.addIssue({
|
|
14
|
-
code: z.ZodIssueCode.custom,
|
|
15
|
-
message: "must be a single program name token with no spaces or quotes.",
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const nonblankOptionalString = z
|
|
20
|
-
.string()
|
|
21
|
-
.refine((value) => value.trim().length > 0, { message: "must not be blank." })
|
|
22
|
-
.optional();
|
|
23
|
-
const providerCommonFields = {
|
|
24
|
-
description: nonblankOptionalString,
|
|
25
|
-
};
|
|
26
|
-
const providerEnvSchema = z.record(z.string(), z.string()).optional();
|
|
27
|
-
function refinePiEnvInjection(data, ctx) {
|
|
28
|
-
if (data.env === undefined)
|
|
29
|
-
return;
|
|
30
|
-
if (Object.keys(data.env).length === 0)
|
|
31
|
-
return;
|
|
32
|
-
ctx.addIssue({
|
|
33
|
-
code: z.ZodIssueCode.custom,
|
|
34
|
-
path: ["env"],
|
|
35
|
-
message: "env injection not supported for provider pi",
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
const CODEX_SDK_FORBIDDEN_THREAD_OPTIONS_KEYS = [
|
|
39
|
-
"model",
|
|
40
|
-
"modelReasoningEffort",
|
|
41
|
-
"sandboxMode",
|
|
42
|
-
"networkAccessEnabled",
|
|
43
|
-
"webSearchMode",
|
|
44
|
-
"approvalPolicy",
|
|
45
|
-
"workingDirectory",
|
|
46
|
-
"skipGitRepoCheck",
|
|
47
|
-
];
|
|
48
|
-
const FORBIDDEN_CONFIG_KEYS = [
|
|
49
|
-
"model",
|
|
50
|
-
"model_reasoning_effort",
|
|
51
|
-
];
|
|
52
|
-
function isConfigKeyForbidden(key) {
|
|
53
|
-
return FORBIDDEN_CONFIG_KEYS.includes(key);
|
|
54
|
-
}
|
|
55
|
-
const claudeSettingSourceSchema = z.enum(CLAUDE_SETTING_SOURCES);
|
|
56
|
-
const writableRootItemSchema = z.string().superRefine((value, ctx) => {
|
|
57
|
-
if (value.length === 0) {
|
|
58
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not be empty." });
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (value.startsWith("~")) {
|
|
62
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not begin with tilde." });
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (value.includes("\0")) {
|
|
66
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain NUL byte." });
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (/\$[A-Za-z_]/.test(value) || /\$\{/.test(value)) {
|
|
70
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain environment variable references." });
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
export const providerInstanceSchema = z.discriminatedUnion("kind", [
|
|
75
|
-
z
|
|
76
|
-
.object({
|
|
77
|
-
kind: z.literal("codex-sdk"),
|
|
78
|
-
...providerCommonFields,
|
|
79
|
-
executable: executableSchema.optional(),
|
|
80
|
-
profile: z.string().optional(),
|
|
81
|
-
config: structuredTomlValueSchema.optional(),
|
|
82
|
-
threadOptions: structuredTomlValueSchema.optional(),
|
|
83
|
-
})
|
|
84
|
-
.strict()
|
|
85
|
-
.superRefine((data, ctx) => {
|
|
86
|
-
if (data.threadOptions) {
|
|
87
|
-
for (const key of CODEX_SDK_FORBIDDEN_THREAD_OPTIONS_KEYS) {
|
|
88
|
-
if (key in data.threadOptions) {
|
|
89
|
-
ctx.addIssue({
|
|
90
|
-
code: z.ZodIssueCode.custom,
|
|
91
|
-
path: ["threadOptions", key],
|
|
92
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (data.config) {
|
|
98
|
-
for (const key of Object.keys(data.config)) {
|
|
99
|
-
if (isConfigKeyForbidden(key)) {
|
|
100
|
-
ctx.addIssue({
|
|
101
|
-
code: z.ZodIssueCode.custom,
|
|
102
|
-
path: ["config", key],
|
|
103
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}),
|
|
109
|
-
z
|
|
110
|
-
.object({
|
|
111
|
-
kind: z.literal("codex-app-server"),
|
|
112
|
-
...providerCommonFields,
|
|
113
|
-
executable: executableSchema.optional(),
|
|
114
|
-
profile: z.string().optional(),
|
|
115
|
-
config: structuredTomlValueSchema.optional(),
|
|
116
|
-
writableRoots: z.array(writableRootItemSchema).optional(),
|
|
117
|
-
env: providerEnvSchema,
|
|
118
|
-
})
|
|
119
|
-
.strict()
|
|
120
|
-
.superRefine((data, ctx) => {
|
|
121
|
-
if (data.config) {
|
|
122
|
-
for (const key of Object.keys(data.config)) {
|
|
123
|
-
if (isConfigKeyForbidden(key)) {
|
|
124
|
-
ctx.addIssue({
|
|
125
|
-
code: z.ZodIssueCode.custom,
|
|
126
|
-
path: ["config", key],
|
|
127
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}),
|
|
133
|
-
z
|
|
134
|
-
.object({
|
|
135
|
-
kind: z.literal("claude-agent-sdk"),
|
|
136
|
-
...providerCommonFields,
|
|
137
|
-
executable: executableSchema.optional(),
|
|
138
|
-
settingSources: z.array(claudeSettingSourceSchema).optional(),
|
|
139
|
-
env: providerEnvSchema,
|
|
140
|
-
})
|
|
141
|
-
.strict(),
|
|
142
|
-
z
|
|
143
|
-
.object({
|
|
144
|
-
kind: z.literal("opencode-sdk"),
|
|
145
|
-
...providerCommonFields,
|
|
146
|
-
executable: executableSchema.optional(),
|
|
147
|
-
env: providerEnvSchema,
|
|
148
|
-
})
|
|
149
|
-
.strict(),
|
|
150
|
-
z
|
|
151
|
-
.object({
|
|
152
|
-
kind: z.literal("pi"),
|
|
153
|
-
...providerCommonFields,
|
|
154
|
-
env: providerEnvSchema,
|
|
155
|
-
})
|
|
156
|
-
.strict()
|
|
157
|
-
.superRefine(refinePiEnvInjection),
|
|
158
|
-
]);
|
|
2
|
+
import { BUILTIN_PROVIDER_INSTANCE_CANDIDATES as REGISTRY_BUILTIN_PROVIDER_INSTANCE_CANDIDATES, providerInstanceSchema as registryProviderInstanceSchema, } from "../../agents/providers/registry.js";
|
|
3
|
+
export const providerInstanceSchema = registryProviderInstanceSchema;
|
|
4
|
+
export const BUILTIN_PROVIDER_INSTANCE_CANDIDATES = REGISTRY_BUILTIN_PROVIDER_INSTANCE_CANDIDATES;
|
|
159
5
|
const PROVIDER_INSTANCE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
160
6
|
export const providerInstanceNameSchema = z
|
|
161
7
|
.string()
|
|
162
8
|
.max(64, "must contain at most 64 characters.")
|
|
163
9
|
.regex(PROVIDER_INSTANCE_NAME_PATTERN, "must match ^[a-z0-9][a-z0-9-]*$.");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
name: "codex-app-server",
|
|
168
|
-
source: "builtin",
|
|
169
|
-
instance: { kind: "codex-app-server", executable: "codex" },
|
|
170
|
-
},
|
|
171
|
-
"claude-agent-sdk": {
|
|
172
|
-
name: "claude-agent-sdk",
|
|
173
|
-
source: "builtin",
|
|
174
|
-
instance: { kind: "claude-agent-sdk", executable: "claude", settingSources: ["project"] },
|
|
175
|
-
},
|
|
176
|
-
"opencode-sdk": {
|
|
177
|
-
name: "opencode-sdk",
|
|
178
|
-
source: "builtin",
|
|
179
|
-
instance: { kind: "opencode-sdk", executable: "opencode" },
|
|
180
|
-
},
|
|
181
|
-
pi: { name: "pi", source: "builtin", instance: { kind: "pi" } },
|
|
182
|
-
};
|
|
10
|
+
// Ensure the registry builtin map stays keyed by the closed provider vocabulary.
|
|
11
|
+
const _builtinCheck = BUILTIN_PROVIDER_INSTANCE_CANDIDATES;
|
|
12
|
+
void _builtinCheck;
|
|
183
13
|
const AGENT_NAME_PATTERN = /^[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9]+)*$/;
|
|
184
14
|
export const agentNameSchema = z
|
|
185
15
|
.string()
|
package/build/core/addressing.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { FlowError } from "../flow-error.js";
|
|
3
|
+
import { errorContainsAnyPattern, NOT_GIT_REPOSITORY_PATTERNS } from "../git/core.js";
|
|
4
|
+
import { commissionSlug, formatCommissionCoordinate } from "./ids.js";
|
|
3
5
|
import { listContractIds, readLedger } from "./ledger.js";
|
|
4
6
|
import { isResponseArtifactId } from "./response-artifact-id.js";
|
|
5
|
-
import { stableRepoRoot } from "./worktree-path.js";
|
|
7
|
+
import { activeContractBoundByEngineWorktree, stableRepoRoot } from "./worktree-path.js";
|
|
8
|
+
import { assertNoRenewRecoverySession } from "./renew-session.js";
|
|
6
9
|
import { deriveContractState, isTerminalState, } from "./status/lifecycle.js";
|
|
10
|
+
const AMBIGUOUS_OBJECTIVE_MAX_CHARS = 60;
|
|
7
11
|
function normalizeAddressQuery(raw) {
|
|
8
12
|
const value = raw.startsWith("@") ? raw.slice(1) : raw;
|
|
9
13
|
if (!value.trim()) {
|
|
@@ -17,8 +21,8 @@ class AddressedFlowError extends FlowError {
|
|
|
17
21
|
constructor(error, carrier) {
|
|
18
22
|
super(error.code, error.message, {
|
|
19
23
|
cause: error,
|
|
20
|
-
hints: error.hints,
|
|
21
24
|
review: error.review,
|
|
25
|
+
facts: error.facts,
|
|
22
26
|
});
|
|
23
27
|
this.name = error.name;
|
|
24
28
|
this[ADDRESS_CARRIER] = carrier;
|
|
@@ -108,9 +112,8 @@ export class AddressResolutionError extends FlowError {
|
|
|
108
112
|
this.attempt = attempt;
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
return separator > 0 ? contractId.slice(0, separator) : contractId;
|
|
115
|
+
function candidatePlace(candidate) {
|
|
116
|
+
return candidate.bind.data.workspace === "worktree" ? candidate.bind.data.place ?? null : null;
|
|
114
117
|
}
|
|
115
118
|
async function commissionAddressCandidates(cwd) {
|
|
116
119
|
const ids = await listContractIds(cwd);
|
|
@@ -135,9 +138,9 @@ function matchCommissionAddress(query, candidates) {
|
|
|
135
138
|
const matches = [];
|
|
136
139
|
if (candidate.contractId === query)
|
|
137
140
|
matches.push({ ...candidate, spelling: "id" });
|
|
138
|
-
if (
|
|
141
|
+
if (commissionSlug(candidate.contractId) === query)
|
|
139
142
|
matches.push({ ...candidate, spelling: "slug" });
|
|
140
|
-
if (candidate.active && candidate
|
|
143
|
+
if (candidate.active && candidatePlace(candidate) === query) {
|
|
141
144
|
matches.push({ ...candidate, spelling: "place" });
|
|
142
145
|
}
|
|
143
146
|
return matches;
|
|
@@ -146,16 +149,28 @@ function matchCommissionAddress(query, candidates) {
|
|
|
146
149
|
function attemptCandidates(candidates) {
|
|
147
150
|
return candidates.map((candidate) => ({
|
|
148
151
|
commissionId: candidate.contractId,
|
|
149
|
-
place: candidate
|
|
152
|
+
place: candidatePlace(candidate),
|
|
150
153
|
name: candidate.bind.data.name,
|
|
151
154
|
objective: candidate.bind.data.objective,
|
|
152
155
|
lifecycle: candidate.lifecycle,
|
|
153
156
|
target: { branch: candidate.bind.data.target },
|
|
154
157
|
}));
|
|
155
158
|
}
|
|
156
|
-
function
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
+
function truncateObjectiveFirstLine(objective) {
|
|
160
|
+
const firstLine = objective.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
161
|
+
if (firstLine.length <= AMBIGUOUS_OBJECTIVE_MAX_CHARS)
|
|
162
|
+
return firstLine;
|
|
163
|
+
return `${firstLine.slice(0, AMBIGUOUS_OBJECTIVE_MAX_CHARS)}…`;
|
|
164
|
+
}
|
|
165
|
+
function formatAmbiguousCandidate(candidate) {
|
|
166
|
+
const coordinate = formatCommissionCoordinate({
|
|
167
|
+
commissionId: candidate.commissionId,
|
|
168
|
+
place: candidate.place,
|
|
169
|
+
});
|
|
170
|
+
const objective = truncateObjectiveFirstLine(candidate.objective);
|
|
171
|
+
return [coordinate, objective || undefined, candidate.commissionId]
|
|
172
|
+
.filter((part) => part !== undefined)
|
|
173
|
+
.join(" · ");
|
|
159
174
|
}
|
|
160
175
|
async function resolvedRepository(cwd) {
|
|
161
176
|
return { kind: "repository", stableRoot: await stableRepoRoot(cwd) };
|
|
@@ -166,7 +181,7 @@ function buildResolvedAddress(input) {
|
|
|
166
181
|
workdir: input.workdir,
|
|
167
182
|
binding: { kind: "commission", commissionId: input.candidate.contractId },
|
|
168
183
|
spelling: { asTyped: input.asTyped, source: input.source, matchedBy: input.matchedBy },
|
|
169
|
-
place: { display: input.candidate
|
|
184
|
+
place: { display: candidatePlace(input.candidate) },
|
|
170
185
|
lifecycle: input.candidate.lifecycle,
|
|
171
186
|
target: { branch: input.candidate.bind.data.target },
|
|
172
187
|
inference: input.inference,
|
|
@@ -188,8 +203,8 @@ export function buildUncommissionedRepositoryAddress(input) {
|
|
|
188
203
|
inference: input.inference,
|
|
189
204
|
});
|
|
190
205
|
}
|
|
191
|
-
export async function resolveContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag") {
|
|
192
|
-
const workdir = path.resolve(
|
|
206
|
+
export async function resolveContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag", effectiveDirectory = cwd) {
|
|
207
|
+
const workdir = path.resolve(effectiveDirectory);
|
|
193
208
|
const repo = await resolvedRepository(cwd);
|
|
194
209
|
if (raw !== undefined) {
|
|
195
210
|
const query = normalizeAddressQuery(raw);
|
|
@@ -216,7 +231,7 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
216
231
|
candidates: matches.map((candidate) => ({
|
|
217
232
|
commissionId: candidate.contractId,
|
|
218
233
|
matchedBy: candidate.spelling,
|
|
219
|
-
place: candidate
|
|
234
|
+
place: candidatePlace(candidate),
|
|
220
235
|
name: candidate.bind.data.name,
|
|
221
236
|
objective: candidate.bind.data.objective,
|
|
222
237
|
lifecycle: candidate.lifecycle,
|
|
@@ -238,9 +253,34 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
238
253
|
if (matches.length === 0) {
|
|
239
254
|
throw new AddressResolutionError("EMPTY_PARAM", `unknown contract address @${query}`, attempt);
|
|
240
255
|
}
|
|
241
|
-
throw new AddressResolutionError("CONTRACT_AMBIGUOUS",
|
|
256
|
+
throw new AddressResolutionError("CONTRACT_AMBIGUOUS", `@${query} is ambiguous:\n${attempt.candidates.map((candidate) => ` ${formatAmbiguousCandidate(candidate)}`).join("\n")}\nuse a full @commission-id`, attempt);
|
|
242
257
|
}
|
|
243
258
|
const candidates = await commissionAddressCandidates(repo.stableRoot);
|
|
259
|
+
let boundContractId;
|
|
260
|
+
try {
|
|
261
|
+
const effectiveRepo = await stableRepoRoot(workdir);
|
|
262
|
+
if (effectiveRepo === repo.stableRoot) {
|
|
263
|
+
boundContractId = await activeContractBoundByEngineWorktree(workdir);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
if (!errorContainsAnyPattern(error, NOT_GIT_REPOSITORY_PATTERNS))
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
if (boundContractId) {
|
|
271
|
+
const candidate = candidates.find((item) => item.active && item.contractId === boundContractId);
|
|
272
|
+
if (candidate) {
|
|
273
|
+
return buildResolvedAddress({
|
|
274
|
+
repo,
|
|
275
|
+
workdir,
|
|
276
|
+
candidate,
|
|
277
|
+
matchedBy: "id",
|
|
278
|
+
asTyped: `@${candidate.contractId}`,
|
|
279
|
+
source: "worktree-binding",
|
|
280
|
+
inference: ["verified active engine worktree binding"],
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
244
284
|
const operable = candidates.filter((candidate) => candidate.active);
|
|
245
285
|
const attempt = {
|
|
246
286
|
repo,
|
|
@@ -265,3 +305,13 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
265
305
|
? "no active commission found; pass @place, @slug, full @commission-id, or --contract <addr>"
|
|
266
306
|
: "multiple active commissions found; pass @place, @slug, full @commission-id, or --contract <addr>", attempt);
|
|
267
307
|
}
|
|
308
|
+
export async function resolveExistingContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag", effectiveDirectory = cwd) {
|
|
309
|
+
const address = await resolveContractAddress(cwd, raw, source, effectiveDirectory);
|
|
310
|
+
try {
|
|
311
|
+
await assertNoRenewRecoverySession(address.repo.stableRoot, address.binding.commissionId);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
throw attachAddressCarrier(error, address);
|
|
315
|
+
}
|
|
316
|
+
return address;
|
|
317
|
+
}
|
package/build/core/amend.js
CHANGED
|
@@ -1,15 +1,63 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as path from "node:path";
|
|
3
1
|
import { FlowError } from "../flow-error.js";
|
|
4
2
|
import { getCurrentBranch, requireGitRepository } from "../git/branches.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { renderContractView } from "./contract-view.js";
|
|
3
|
+
import { activeLedgerRef, appendWithRetry } from "./ledger.js";
|
|
4
|
+
import { refreshContractView } from "./contract-view.js";
|
|
8
5
|
import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
|
|
9
6
|
import { resolveContractAddress, withResolvedAddress } from "./addressing.js";
|
|
10
7
|
import { resolveDefaultBranch } from "./status/drift.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { markdownSourceSections, normalizeScopePattern, validateScopeFragmentLines } from "./scope.js";
|
|
9
|
+
import { normalizeSectionTitle } from "./markdown/titles.js";
|
|
10
|
+
import { resolveContractDeliveryCwd } from "./worktree-path.js";
|
|
11
|
+
function amendScopeHeading(name) {
|
|
12
|
+
return `## Scope ${name[0].toUpperCase()}${name.slice(1)}`;
|
|
13
|
+
}
|
|
14
|
+
function parseAmendScopeSections(markdown) {
|
|
15
|
+
const sections = {};
|
|
16
|
+
for (const section of markdownSourceSections(markdown)) {
|
|
17
|
+
if (section.level !== 2)
|
|
18
|
+
continue;
|
|
19
|
+
const title = normalizeSectionTitle(section.title);
|
|
20
|
+
if (title === "scope add") {
|
|
21
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", "Scope Add is obsolete; use ## Scope Append with a fenced gitignore-subset block");
|
|
22
|
+
}
|
|
23
|
+
if (title !== "scope append")
|
|
24
|
+
continue;
|
|
25
|
+
if (sections.append) {
|
|
26
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", `amend input may contain ${amendScopeHeading("append")} at most once`);
|
|
27
|
+
}
|
|
28
|
+
sections.append = {
|
|
29
|
+
name: "append",
|
|
30
|
+
start: section.start,
|
|
31
|
+
contentStart: section.contentStart,
|
|
32
|
+
end: section.end,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
let prose = markdown;
|
|
36
|
+
for (const section of Object.values(sections).sort((left, right) => right.start - left.start)) {
|
|
37
|
+
prose = `${prose.slice(0, section.start)}${prose.slice(section.end)}`;
|
|
38
|
+
}
|
|
39
|
+
return { sections, prose };
|
|
40
|
+
}
|
|
41
|
+
function scopePatterns(markdown, section) {
|
|
42
|
+
return validateScopeFragmentLines(markdown.slice(section.contentStart, section.end).split(/\r?\n/), {
|
|
43
|
+
heading: amendScopeHeading(section.name),
|
|
44
|
+
emptyMessage: `amend input has an empty ${amendScopeHeading(section.name)} section`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export function buildAmendInput(markdown, cwd, contractId, contractAddressSource) {
|
|
48
|
+
const { sections, prose } = parseAmendScopeSections(markdown);
|
|
49
|
+
const append = sections.append ? scopePatterns(markdown, sections.append) : [];
|
|
50
|
+
if (!prose.trim()) {
|
|
51
|
+
throw new FlowError("EMPTY_PARAM", "amendment cannot be empty");
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
cwd,
|
|
55
|
+
...(contractId ? { contractId } : {}),
|
|
56
|
+
...(contractAddressSource ? { contractAddressSource } : {}),
|
|
57
|
+
amendment: prose,
|
|
58
|
+
...(sections.append ? { scopeDelta: { add: append } } : {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
13
61
|
function requireAmendment(value) {
|
|
14
62
|
if (!value.trim())
|
|
15
63
|
throw new FlowError("EMPTY_PARAM", "amendment cannot be empty");
|
|
@@ -24,13 +72,6 @@ function assertContractOperable(contractId, entries) {
|
|
|
24
72
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} is terminal (${state.state})`);
|
|
25
73
|
}
|
|
26
74
|
}
|
|
27
|
-
async function renderUpdatedContract(cwd, contractId) {
|
|
28
|
-
const ledger = await readLedger(cwd, contractId);
|
|
29
|
-
if (!ledger) {
|
|
30
|
-
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger disappeared before render`);
|
|
31
|
-
}
|
|
32
|
-
await fs.writeFile(path.join(cwd, KEIYAKU_FILE), renderContractView({ id: contractId, entries: ledger.entries }), "utf8");
|
|
33
|
-
}
|
|
34
75
|
function normalizeScopeDelta(scopeDelta) {
|
|
35
76
|
if (!scopeDelta)
|
|
36
77
|
return undefined;
|
|
@@ -43,6 +84,7 @@ function normalizeScopeDelta(scopeDelta) {
|
|
|
43
84
|
export async function amendContract(input) {
|
|
44
85
|
const amendment = requireAmendment(input.amendment);
|
|
45
86
|
const scopeDelta = normalizeScopeDelta(input.scopeDelta);
|
|
87
|
+
const renderCwd = input.renderCwd ?? input.cwd;
|
|
46
88
|
const at = new Date(input.nowMs).toISOString();
|
|
47
89
|
const ref = activeLedgerRef(input.contractId);
|
|
48
90
|
let amendmentNumber = 0;
|
|
@@ -67,20 +109,21 @@ export async function amendContract(input) {
|
|
|
67
109
|
if (amendmentNumber === 0) {
|
|
68
110
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} active ledger disappeared during amend`);
|
|
69
111
|
}
|
|
70
|
-
await
|
|
112
|
+
await refreshContractView({ ledgerCwd: input.cwd, renderCwd, contractId: input.contractId });
|
|
71
113
|
return { contractId: input.contractId, amendmentNumber, ledgerHead: result.head };
|
|
72
114
|
}
|
|
73
115
|
export async function amendKeiyaku(input) {
|
|
74
116
|
await requireGitRepository(input.cwd, "amend");
|
|
75
|
-
const address = await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
117
|
+
const address = input.address ?? await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
76
118
|
return await withResolvedAddress(address, async () => {
|
|
77
119
|
const contractId = address.binding.commissionId;
|
|
78
|
-
await
|
|
120
|
+
const renderCwd = await resolveContractDeliveryCwd(input.cwd, contractId);
|
|
79
121
|
const amendment = requireAmendment(input.amendment);
|
|
80
|
-
const currentBranch = await getCurrentBranch(
|
|
122
|
+
const currentBranch = await getCurrentBranch(renderCwd);
|
|
81
123
|
const baseBranch = (await resolveDefaultBranch(input.cwd))?.branch ?? currentBranch;
|
|
82
124
|
const amended = await amendContract({
|
|
83
125
|
cwd: input.cwd,
|
|
126
|
+
renderCwd,
|
|
84
127
|
contractId,
|
|
85
128
|
actor: "keiyaku",
|
|
86
129
|
nowMs: Date.now(),
|
package/build/core/arc.js
CHANGED
|
@@ -2,63 +2,18 @@ import * as fs from "node:fs/promises";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { requireText, FlowError } from "../flow-error.js";
|
|
4
4
|
import { getCurrentBranch, requireGitRepository } from "../git/branches.js";
|
|
5
|
-
import {
|
|
5
|
+
import { assertCleanTrackedWorkingTree } from "../git/worktree.js";
|
|
6
6
|
import { KEIYAKU_FILE, ACTOR_IDENTITY } from "../keiyaku.js";
|
|
7
|
-
import { buildDirtyWorktreeArtifactHint } from "./hints.js";
|
|
8
7
|
import { normalizeInlineTitle } from "./markdown/titles.js";
|
|
9
|
-
import { parseCommandMarkdown, requireMarkdownTextSection, requireMarkdownTitle, } from "./command-
|
|
8
|
+
import { parseCommandMarkdown, requireMarkdownTextSection, requireMarkdownTitle, } from "./command-markdown.js";
|
|
10
9
|
import { resolveContractAddress, withResolvedAddress } from "./addressing.js";
|
|
11
10
|
import { activeLedgerRef, appendWithRetry, readLedger } from "./ledger.js";
|
|
12
|
-
import {
|
|
13
|
-
import { findOpenArc, getMaxArc, sealCurrentArc } from "./seal.js";
|
|
11
|
+
import { refreshContractView } from "./contract-view.js";
|
|
12
|
+
import { appendScopeTerms, findOpenArc, getMaxArc, sealCurrentArc } from "./seal.js";
|
|
14
13
|
import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
|
|
15
14
|
import { resolveDefaultBranch } from "./status/drift.js";
|
|
16
15
|
import { persistResponseHistory } from "./transcripts.js";
|
|
17
|
-
|
|
18
|
-
const KEIYAKU_ARTIFACT_DIR_PREFIX = ".keiyaku/";
|
|
19
|
-
function normalizePathForDirtyMatch(cwd, filePath) {
|
|
20
|
-
const normalizedPath = filePath.trim();
|
|
21
|
-
if (!normalizedPath)
|
|
22
|
-
return "";
|
|
23
|
-
const repoRelativePath = path.isAbsolute(normalizedPath) ? path.relative(cwd, normalizedPath) : normalizedPath;
|
|
24
|
-
const platformNormalizedPath = path.normalize(repoRelativePath.replace(/[\\/]+/g, path.sep));
|
|
25
|
-
return platformNormalizedPath.split(path.sep).join("/").replace(/^\.\/+/, "").replace(/^\/+/, "");
|
|
26
|
-
}
|
|
27
|
-
function pathSegments(normalizedPath) {
|
|
28
|
-
return normalizedPath.split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
29
|
-
}
|
|
30
|
-
function matchesIgnorePattern(filePath, ignorePattern) {
|
|
31
|
-
const patternSegments = pathSegments(ignorePattern);
|
|
32
|
-
const fileSegments = pathSegments(filePath);
|
|
33
|
-
return patternSegments.length > 0
|
|
34
|
-
&& fileSegments.length >= patternSegments.length
|
|
35
|
-
&& patternSegments.every((segment, index) => fileSegments[index] === segment);
|
|
36
|
-
}
|
|
37
|
-
export function filterDirtyFilesByAllowlist(cwd, dirtyFiles, ignorePatterns) {
|
|
38
|
-
const ignoredPaths = Array.from(new Set((ignorePatterns ?? []).map((pattern) => normalizePathForDirtyMatch(cwd, pattern)).filter(Boolean)));
|
|
39
|
-
return {
|
|
40
|
-
dirtyFiles: dirtyFiles.filter((file) => {
|
|
41
|
-
const normalizedFilePath = normalizePathForDirtyMatch(cwd, file.path);
|
|
42
|
-
return !ignoredPaths.some((ignoredPath) => matchesIgnorePattern(normalizedFilePath, ignoredPath));
|
|
43
|
-
}),
|
|
44
|
-
ignoredPaths,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
export function filterBlockingDirtyFiles(dirtyFiles) {
|
|
48
|
-
return dirtyFiles.filter((file) => file.category !== DIRTY_FILE_CATEGORY.untracked);
|
|
49
|
-
}
|
|
50
|
-
export async function assertCleanWorkingTree(cwd, ignorePatterns) {
|
|
51
|
-
const blockingDirtyFiles = filterBlockingDirtyFiles(await getDirtyFiles(cwd));
|
|
52
|
-
const { dirtyFiles } = filterDirtyFilesByAllowlist(cwd, blockingDirtyFiles, ignorePatterns);
|
|
53
|
-
if (dirtyFiles.length === 0)
|
|
54
|
-
return;
|
|
55
|
-
const hasDirtyKeiyakuArtifacts = dirtyFiles.some((file) => normalizePathForDirtyMatch(cwd, file.path).startsWith(KEIYAKU_ARTIFACT_DIR_PREFIX));
|
|
56
|
-
const shown = dirtyFiles.slice(0, DIRTY_WORKTREE_LIST_LIMIT);
|
|
57
|
-
const list = shown.map((file) => ` ${renderDirtyFileStatusLine(file)}`).join("\n");
|
|
58
|
-
const overflowCount = dirtyFiles.length - shown.length;
|
|
59
|
-
const overflowLine = overflowCount > 0 ? `\n ... (+${overflowCount} more)` : "";
|
|
60
|
-
throw new FlowError("DIRTY_WORKTREE", `Uncommitted changes detected in working tree:\n${list}${overflowLine}\n\nBlocking changes must be committed or stashed before proceeding.`, hasDirtyKeiyakuArtifacts ? { hints: [buildDirtyWorktreeArtifactHint()] } : undefined);
|
|
61
|
-
}
|
|
16
|
+
import { resolveContractDeliveryCwd } from "./worktree-path.js";
|
|
62
17
|
export function buildArcViews(entries) {
|
|
63
18
|
const arcs = new Map();
|
|
64
19
|
for (const entry of entries) {
|
|
@@ -96,29 +51,31 @@ function assertArcOpenable(contractId, entries) {
|
|
|
96
51
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} cannot open arc from state ${state.state}`);
|
|
97
52
|
}
|
|
98
53
|
}
|
|
99
|
-
async function renderUpdatedContract(cwd, contractId) {
|
|
100
|
-
const ledger = await readLedger(cwd, contractId);
|
|
101
|
-
if (!ledger) {
|
|
102
|
-
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger disappeared before render`);
|
|
103
|
-
}
|
|
104
|
-
await fs.writeFile(path.join(cwd, KEIYAKU_FILE), renderContractView({ id: contractId, entries: ledger.entries }), "utf8");
|
|
105
|
-
}
|
|
106
54
|
export async function openArc(input) {
|
|
107
55
|
const title = requireText("title", input.title);
|
|
108
56
|
const objective = requireText("objective", input.objective);
|
|
109
57
|
const brief = requireText("brief", input.brief);
|
|
58
|
+
const renderCwd = input.renderCwd ?? input.cwd;
|
|
110
59
|
const ledger = await readLedger(input.cwd, input.contractId);
|
|
111
60
|
if (!ledger) {
|
|
112
61
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} not found or not active`);
|
|
113
62
|
}
|
|
114
63
|
assertArcOpenable(input.contractId, ledger.entries);
|
|
115
|
-
|
|
64
|
+
await appendScopeTerms({
|
|
116
65
|
cwd: input.cwd,
|
|
117
|
-
renderCwd
|
|
66
|
+
renderCwd,
|
|
67
|
+
contractId: input.contractId,
|
|
68
|
+
patterns: input.appendScope,
|
|
69
|
+
actor: input.actor,
|
|
70
|
+
nowMs: input.nowMs,
|
|
71
|
+
});
|
|
72
|
+
// Seal capture needs delivery HEAD; ledger append may use hub or delivery (shared refs).
|
|
73
|
+
const sealed = await sealCurrentArc({
|
|
74
|
+
cwd: renderCwd,
|
|
75
|
+
renderCwd,
|
|
118
76
|
contractId: input.contractId,
|
|
119
77
|
sealedBy: "arc",
|
|
120
78
|
nowMs: input.nowMs,
|
|
121
|
-
waivePaths: input.waivePaths,
|
|
122
79
|
});
|
|
123
80
|
const at = new Date(input.nowMs).toISOString();
|
|
124
81
|
let arcNumber = 0;
|
|
@@ -140,10 +97,10 @@ export async function openArc(input) {
|
|
|
140
97
|
if (!result.ok || arcNumber === 0) {
|
|
141
98
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} active ledger disappeared during arc`);
|
|
142
99
|
}
|
|
143
|
-
await
|
|
100
|
+
await refreshContractView({ ledgerCwd: input.cwd, renderCwd, contractId: input.contractId });
|
|
144
101
|
return { contractId: input.contractId, arc: arcNumber, ledgerHead: result.head, sealed };
|
|
145
102
|
}
|
|
146
|
-
export function buildArcInput(content, cwd,
|
|
103
|
+
export function buildArcInput(content, cwd, appendScope = [], contractId, contractAddressSource) {
|
|
147
104
|
const parts = parseCommandMarkdown(content);
|
|
148
105
|
return {
|
|
149
106
|
cwd,
|
|
@@ -152,7 +109,7 @@ export function buildArcInput(content, cwd, waivePaths = [], contractId, contrac
|
|
|
152
109
|
title: requireMarkdownTitle(parts),
|
|
153
110
|
objective: requireMarkdownTextSection(parts, "Objective"),
|
|
154
111
|
brief: requireMarkdownTextSection(parts, "Brief"),
|
|
155
|
-
|
|
112
|
+
appendScope,
|
|
156
113
|
};
|
|
157
114
|
}
|
|
158
115
|
async function readBranchLabels(cwd) {
|
|
@@ -162,11 +119,13 @@ async function readBranchLabels(cwd) {
|
|
|
162
119
|
}
|
|
163
120
|
export async function arcKeiyaku(input) {
|
|
164
121
|
await requireGitRepository(input.cwd, "arc");
|
|
165
|
-
const address = await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
122
|
+
const address = input.address ?? await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
166
123
|
return await withResolvedAddress(address, async () => {
|
|
167
|
-
|
|
124
|
+
const contractId = address.binding.commissionId;
|
|
125
|
+
const renderCwd = await resolveContractDeliveryCwd(input.cwd, contractId);
|
|
126
|
+
await assertCleanTrackedWorkingTree(renderCwd);
|
|
168
127
|
try {
|
|
169
|
-
await fs.access(path.join(
|
|
128
|
+
await fs.access(path.join(renderCwd, KEIYAKU_FILE));
|
|
170
129
|
}
|
|
171
130
|
catch {
|
|
172
131
|
throw new FlowError("MISSING_PROTOCOL_FILES", `missing protocol file for current keiyaku (${KEIYAKU_FILE})`);
|
|
@@ -174,22 +133,22 @@ export async function arcKeiyaku(input) {
|
|
|
174
133
|
const title = normalizeInlineTitle(requireText("title", input.title));
|
|
175
134
|
const objective = requireText("objective", input.objective);
|
|
176
135
|
const brief = requireText("brief", input.brief);
|
|
177
|
-
const
|
|
136
|
+
const nowMs = Date.now();
|
|
178
137
|
const opened = await openArc({
|
|
179
138
|
cwd: input.cwd,
|
|
139
|
+
renderCwd,
|
|
180
140
|
contractId,
|
|
181
141
|
actor: ACTOR_IDENTITY,
|
|
182
|
-
nowMs
|
|
142
|
+
nowMs,
|
|
183
143
|
title,
|
|
184
144
|
objective,
|
|
185
145
|
brief,
|
|
186
|
-
|
|
146
|
+
appendScope: input.appendScope,
|
|
187
147
|
});
|
|
188
|
-
const { currentBranch, baseBranch } = await readBranchLabels(
|
|
148
|
+
const { currentBranch, baseBranch } = await readBranchLabels(renderCwd);
|
|
189
149
|
const summary = opened.sealed
|
|
190
150
|
? `a${opened.sealed.arc} sealed; a${opened.arc} open: ${title}.`
|
|
191
151
|
: `a${opened.arc} open: ${title}.`;
|
|
192
|
-
const diff = opened.sealed?.incrementalDiff ?? "working tree untouched";
|
|
193
152
|
let responsePath;
|
|
194
153
|
let artifactId;
|
|
195
154
|
try {
|
|
@@ -202,7 +161,7 @@ export async function arcKeiyaku(input) {
|
|
|
202
161
|
brief,
|
|
203
162
|
ledgerCommit: opened.ledgerHead,
|
|
204
163
|
summary,
|
|
205
|
-
|
|
164
|
+
emptyDiffLabel: "working tree untouched",
|
|
206
165
|
...(opened.sealed ? { sealed: opened.sealed } : {}),
|
|
207
166
|
});
|
|
208
167
|
responsePath = persisted.responsePath;
|
|
@@ -217,7 +176,8 @@ export async function arcKeiyaku(input) {
|
|
|
217
176
|
currentBranch,
|
|
218
177
|
baseBranch,
|
|
219
178
|
commit: opened.ledgerHead,
|
|
220
|
-
|
|
179
|
+
// CLI/render synthesizes public face bytes from sealed typed facts.
|
|
180
|
+
diff: "",
|
|
221
181
|
summary,
|
|
222
182
|
title,
|
|
223
183
|
objective,
|