@sayknow-cli/coding-agent 0.5.10 → 0.5.13
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/CHANGELOG.md +42 -0
- package/dist/types/config/file-lock.d.ts +8 -0
- package/dist/types/config/model-profile-activation.d.ts +3 -1
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/session-import/redact.d.ts +1 -1
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +13 -1
- package/dist/types/skc-runtime/ultragoal-succession.d.ts +251 -0
- package/dist/types/skc-runtime/workflow-placeholder.d.ts +6 -0
- package/dist/types/tools/ask.d.ts +460 -172
- package/package.json +7 -7
- package/src/cli/telegram-cli.ts +1 -1
- package/src/config/file-lock-gc.ts +39 -2
- package/src/config/file-lock.ts +22 -1
- package/src/config/model-profile-activation.ts +7 -11
- package/src/config/model-registry.ts +192 -44
- package/src/config/model-resolver.ts +4 -2
- package/src/config/models-config-schema.ts +1 -0
- package/src/defaults/skc/skills/deep-interview/SKILL.md +12 -0
- package/src/defaults/skc/skills/ultragoal/SKILL.md +3 -0
- package/src/modes/components/settings-selector.ts +39 -21
- package/src/modes/controllers/selector-controller.ts +35 -15
- package/src/modes/rpc/rpc-client.ts +20 -4
- package/src/sdk/bus/index.ts +1 -3
- package/src/session-import/redact.ts +6 -3
- package/src/skc-runtime/state-writer.ts +24 -27
- package/src/skc-runtime/ultragoal-runtime.ts +125 -45
- package/src/skc-runtime/ultragoal-succession.ts +1667 -0
- package/src/skc-runtime/workflow-placeholder.ts +33 -0
- package/src/tools/ask.ts +366 -108
- package/src/tools/bisect.ts +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.5.13] - 2026-09-15
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Session-import's cross-process idempotency test no longer depends on Bun child stdout surviving a contended file lock. The child writes its result to a file as well as stdout, so a silent empty pipe on Linux CI cannot fail a successful import.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## [0.5.12] - 2026-09-15
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `skc ultragoal succession offer|adopt|status` gives an approved Ultragoal an explicit, audited path from the repository it was planned in to the repository its implementation belongs to (ported from upstream #5353). The source run fences the selected unfinished goals immediately; the target adopts a fresh pending plan with verbatim brief/objectives and unresolved obligations as provenance, not inherited completion authority.
|
|
15
|
+
- Custom OpenAI-compatible providers in `models.yml` auto-populate `/model` from their live `/v1/models` catalog without a manual `discovery:` block, and auto-classify each discovered model's wire API family (ported from upstream #5187). Explicit `discovery` config and the local `openaiCompat` proxy lane are unchanged.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Session import redaction now bounds the URL-credential scheme to 16 characters so large credential-free transcripts scan in linear time instead of quadratic (ported from upstream #5346). Markdown-wrapped `https://user:pass@host` credentials remain redacted.
|
|
20
|
+
- File-lock acquisition timeouts are a typed `FileLockAcquireError` with the lock path, retry count, and holder, instead of an untyped string. Empty `.lock` directories left by a crash between `mkdir` and writing `info` are reclaimable by GC (the SKC-shaped subset of upstream #5378/#5381; this tree has no `.lock.pending.<pid>.<uuid>` staging).
|
|
21
|
+
- `writeGuardedJsonAtomic` honors `lockHeld`, so callers already inside `withWorkflowStateLock` (succession offer/adopt, start/checkpoint) no longer self-deadlock.
|
|
22
|
+
- Under tmux, a successful sixel DA1 no longer turns INLINE transcript images back on. Ghostty answers that query with ";4" even though it never paints sixel, so every screenshot was smuggled through DCS passthrough onto the outer image plane and stacked over the chat. The probe now enables overlay sixel (the pet) only; inline sixel stays off unless tmux itself owns `terminal-features=sixel`.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## [0.5.11] - 2026-09-10
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Telegram tool activity and reasoning summaries flow again. The native notifications server (`crates/skc-notifications`) still admitted only the legacy `tool_activity_v1` token while the daemon and SDK host negotiated `tool_activity_v2`, so every tool-activity and reasoning-summary frame was silently dropped. Ported the upstream protocol constants: v2 is canonical, v1 stays receive-only for legacy clients.
|
|
30
|
+
- `bisect` recognizes git 2.55's quoted convergence line (`<sha> is the first 'bad' commit`). On newer git every bisect ran to the step limit and reported no conclusion.
|
|
31
|
+
- `/resume` with an explicit `--session-dir` no longer fails closed: the interactive selector called the managed-only candidate preparation unconditionally. It now lists through the read-only picker inventory, uses strict adoption only for managed destinations, and tags switches with the selector resume origin.
|
|
32
|
+
- Model registry: `getAvailable()` is memoized (keyed on disabled providers and credential env, invalidated on auth-generation changes and catalog rebuilds), provider-discovery 401/403 errors name the provider and the `providers.<id>.apiKey` / `apiKeyEnv` surface through a redacted URL, and the resolver forwards the session id so parent-session canonical stickiness reaches bare subagent overrides.
|
|
33
|
+
- Thinking/effort selector awaits the session's control-level change and surfaces errors instead of closing optimistically. Command palette hints use the configured key display strings.
|
|
34
|
+
- Status line custom editor caught up with upstream: usage-mode row, stable description-area height, parent preview refresh on edit and cancel, and `usage` merged into segment options.
|
|
35
|
+
- Hidden `__gateway` telegram subcommand imports `@sayknow-cli/telegram-remote` by package name instead of a cross-package relative path that does not exist in published installs.
|
|
36
|
+
- Deep-interview skill: ported the "Per-question advisory fanout lanes" subsection that the v0.5.0 sync missed.
|
|
37
|
+
- Stdio RPC client reports the child's exit code and stderr when the child exits before `ready`, instead of a misleading JSONL parse error.
|
|
38
|
+
- `ask` tool caught up with the SDK contract: the parameter schema is stage-gated for deep interviews (topology vs post-topology vs ordinary asks), and SDK-routed asks consume the typed `awaitAnswerRequest` receipt and settlement (commit / resolve-without-commit / invalid) instead of only the legacy `awaitAnswer` path, so remote answers fire at invocation time.
|
|
39
|
+
- Model profile activation raises typed `UnknownModelProfileError` / registry errors, so an SDK child that fails profile activation reports `code` and `details` through readiness and `BrokerResponse` instead of a bare `spawn_failed`.
|
|
40
|
+
- SDK host shutdown awaits the native notifications server's `stopAndWait()`; a failing stop is no longer recorded as a successful `hostStopped` during rollback.
|
|
41
|
+
- `mupdf` compiled-binary test and the Python SDK real-session tests run against whichever native addon variant CI built.
|
|
42
|
+
|
|
43
|
+
### CI
|
|
44
|
+
|
|
45
|
+
- Main CI is green again for the first time since the v0.11.6 sync. The `runtime-check` shard now downloads the native addon artifact, the planner (`scripts/ci-dev-affected.ts`) was rebuilt on the upstream v0.12.0 model with the fork's deltas (including the isolated production SDK host shard), the install smoke Dockerfile publishes the platform native packages, and roughly one hundred stale test contracts carried over from the v0.11.6/v0.12.0 syncs (rebrand strings, retired `--mode rpc`, catalog growth, default theme, golden HMAC domains) were realigned to the fork's intended behavior without removing or skipping tests.
|
|
46
|
+
|
|
5
47
|
## [0.5.10] - 2026-09-10
|
|
6
48
|
|
|
7
49
|
### Added
|
|
@@ -3,6 +3,14 @@ export interface FileLockOptions {
|
|
|
3
3
|
retries?: number;
|
|
4
4
|
retryDelayMs?: number;
|
|
5
5
|
}
|
|
6
|
+
export declare class FileLockAcquireError extends Error {
|
|
7
|
+
readonly filePath: string;
|
|
8
|
+
readonly lockPath: string;
|
|
9
|
+
readonly attempts: number;
|
|
10
|
+
readonly holder: string;
|
|
11
|
+
readonly code = "acquire_timeout";
|
|
12
|
+
constructor(filePath: string, lockPath: string, attempts: number, holder: string);
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* Returns the OS-provided process start timestamp for PID-reuse detection.
|
|
8
16
|
* `ps` is available on the supported Unix hosts (macOS and Linux), unlike
|
|
@@ -17,7 +17,9 @@ type ModelProfileActivationSession = Pick<AgentSession, "model" | "thinkingLevel
|
|
|
17
17
|
};
|
|
18
18
|
export interface PrepareModelProfileActivationOptions {
|
|
19
19
|
session: ModelProfileActivationSession;
|
|
20
|
-
modelRegistry: Pick<ModelRegistry, "getModelProfile" | "getModelProfiles" | "getAvailableModelProfileNames" | "getApiKeyForProvider" | "getAll" | "resolveCanonicalModel" | "getCanonicalVariants" | "getCanonicalId"
|
|
20
|
+
modelRegistry: Pick<ModelRegistry, "getModelProfile" | "getModelProfiles" | "getAvailableModelProfileNames" | "getApiKeyForProvider" | "getAll" | "resolveCanonicalModel" | "getCanonicalVariants" | "getCanonicalId"> & {
|
|
21
|
+
getError?: ModelRegistry["getError"];
|
|
22
|
+
};
|
|
21
23
|
settings: Pick<Settings, "get">;
|
|
22
24
|
profileName: string;
|
|
23
25
|
}
|
|
@@ -97,6 +97,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
97
97
|
auth?: "none" | "apiKey" | "oauth" | undefined;
|
|
98
98
|
discovery?: {
|
|
99
99
|
type: "ollama" | "lm-studio" | "omlx" | "sglang" | "llama.cpp" | "openai-models-list";
|
|
100
|
+
apiByModelPrefix?: Record<string, string> | undefined;
|
|
100
101
|
} | undefined;
|
|
101
102
|
requestTransform?: {
|
|
102
103
|
profile?: "openai-proxy" | undefined;
|
|
@@ -319,6 +320,8 @@ export interface ProviderDiscoveryState {
|
|
|
319
320
|
export interface CanonicalModelQueryOptions {
|
|
320
321
|
availableOnly?: boolean;
|
|
321
322
|
candidates?: readonly Model<Api>[];
|
|
323
|
+
/** Session whose canonical stickiness should scope the lookup, when the caller has one. */
|
|
324
|
+
sessionId?: string;
|
|
322
325
|
}
|
|
323
326
|
/**
|
|
324
327
|
* Model registry - loads and manages models, resolves API keys via AuthStorage.
|
|
@@ -265,6 +265,7 @@ export declare const ProviderDiscoverySchema: z.ZodObject<{
|
|
|
265
265
|
"llama.cpp": "llama.cpp";
|
|
266
266
|
"openai-models-list": "openai-models-list";
|
|
267
267
|
}>;
|
|
268
|
+
apiByModelPrefix: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
268
269
|
}, z.core.$strip>;
|
|
269
270
|
export declare const ProviderAuthSchema: z.ZodEnum<{
|
|
270
271
|
none: "none";
|
|
@@ -375,6 +376,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
375
376
|
"llama.cpp": "llama.cpp";
|
|
376
377
|
"openai-models-list": "openai-models-list";
|
|
377
378
|
}>;
|
|
379
|
+
apiByModelPrefix: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
378
380
|
}, z.core.$strip>>;
|
|
379
381
|
requestTransform: z.ZodOptional<z.ZodObject<{
|
|
380
382
|
profile: z.ZodOptional<z.ZodEnum<{
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const IMPORT_REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
10
10
|
/** Bumped when patterns change; persisted in import provenance. */
|
|
11
|
-
export declare const IMPORT_SANITIZER_VERSION =
|
|
11
|
+
export declare const IMPORT_SANITIZER_VERSION = 4;
|
|
12
12
|
export interface ImportRedactionResult {
|
|
13
13
|
value: string;
|
|
14
14
|
redacted: number;
|
|
@@ -264,7 +264,19 @@ export declare function recordUltragoalNudgeIfBudgetRemaining(input: {
|
|
|
264
264
|
reason: string;
|
|
265
265
|
currentGoalObjective?: string;
|
|
266
266
|
}): Promise<UltragoalNudgeOutcome>;
|
|
267
|
-
export declare function writePlan(cwd: string, plan: UltragoalPlan, sessionId?: string | null
|
|
267
|
+
export declare function writePlan(cwd: string, plan: UltragoalPlan, sessionId?: string | null, options?: {
|
|
268
|
+
lockHeld?: boolean;
|
|
269
|
+
}): Promise<void>;
|
|
270
|
+
/**
|
|
271
|
+
* The single exclusion that decides who owns an Ultragoal run.
|
|
272
|
+
*
|
|
273
|
+
* Establishing ownership is a read-decide-write sequence: a start reads the plan,
|
|
274
|
+
* checks the outgoing succession fence, then commits `active`. Every caller that
|
|
275
|
+
* decides ownership — source admission, succession offer, and successor
|
|
276
|
+
* publication — runs that decision inside this lock, keyed on the plan.
|
|
277
|
+
*/
|
|
278
|
+
export declare function withUltragoalPlanOwnership<T>(cwd: string, sessionId: string, fn: () => Promise<T>): Promise<T>;
|
|
279
|
+
export declare function resolveUltragoalOwnershipSession(cwd: string, sessionId?: string | null): Promise<string>;
|
|
268
280
|
export declare function nonEmptyString(value: unknown): string | null;
|
|
269
281
|
export declare function stringArray(value: unknown): string[] | null;
|
|
270
282
|
export declare function hashPipelineMetadata(metadata: Omit<UltragoalPipelineMetadata, "metadataHash">): string;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { type RepositoryBinding } from "./repository-binding";
|
|
2
|
+
import { type UltragoalCommandResult, type UltragoalGoalStatus, type UltragoalPlan, type UltragoalSkcGoalMode } from "./ultragoal-runtime";
|
|
3
|
+
export declare const ULTRAGOAL_SUCCESSION_OPERATION_SCHEMA: "skc.ultragoal_succession_operation.v1";
|
|
4
|
+
export declare const ULTRAGOAL_SUCCESSION_OFFER_SCHEMA: "skc.ultragoal_succession_offer.v1";
|
|
5
|
+
export declare const ULTRAGOAL_SUCCESSION_FENCE_SCHEMA: "skc.ultragoal_succession_fence.v1";
|
|
6
|
+
export declare const ULTRAGOAL_SUCCESSION_ADOPTION_SCHEMA: "skc.ultragoal_succession_adoption.v1";
|
|
7
|
+
export declare const ULTRAGOAL_SUCCESSION_CLAIM_SCHEMA: "skc.ultragoal_succession_claim.v1";
|
|
8
|
+
export declare const SUCCESSION_ADOPTED_EVENT: "succession_adopted";
|
|
9
|
+
export type UltragoalSuccessionErrorCode = "source_plan_missing" | "source_not_quiescent" | "invalid_selection" | "unsafe_target" | "authorization_required" | "divergent_operation" | "goal_handed_off" | "adoption_unpublished" | "publication_conflict" | "published_plan_missing" | "fence_missing" | "fence_mismatch" | "source_changed" | "offer_untrusted" | "offer_path_escape" | "target_mismatch" | "target_occupied" | "duplicate_adoption";
|
|
10
|
+
export declare class UltragoalSuccessionError extends Error {
|
|
11
|
+
readonly code: UltragoalSuccessionErrorCode;
|
|
12
|
+
constructor(code: UltragoalSuccessionErrorCode, message: string);
|
|
13
|
+
}
|
|
14
|
+
export interface UltragoalSuccessionArtifactDigests {
|
|
15
|
+
briefSha256: string;
|
|
16
|
+
goalsSha256: string;
|
|
17
|
+
ledgerSha256: string;
|
|
18
|
+
}
|
|
19
|
+
export interface UltragoalSuccessionCarriedGoal {
|
|
20
|
+
sourceGoalId: string;
|
|
21
|
+
title: string;
|
|
22
|
+
/** The source objective, verbatim. Never a summary. */
|
|
23
|
+
objective: string;
|
|
24
|
+
/** Historical provenance only; never a receipt. */
|
|
25
|
+
sourceStatusAtOffer: UltragoalGoalStatus;
|
|
26
|
+
unresolvedObligations: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Source dependency groups this goal belonged to, carried as an obligation
|
|
29
|
+
* with explicit id mapping. The group's *metadata* (batch hashes, receipts)
|
|
30
|
+
* is deliberately not carried — that would be inherited validation authority.
|
|
31
|
+
* What is carried is the requirement that these goals be validated together.
|
|
32
|
+
*/
|
|
33
|
+
dependencyGroups: UltragoalSuccessionDependencyGroup[];
|
|
34
|
+
}
|
|
35
|
+
export type UltragoalSuccessionDependencyGroupKind = "validation-batch" | "review-blocker";
|
|
36
|
+
export interface UltragoalSuccessionDependencyGroup {
|
|
37
|
+
kind: UltragoalSuccessionDependencyGroupKind;
|
|
38
|
+
groupId: string;
|
|
39
|
+
memberSourceGoalIds: string[];
|
|
40
|
+
/** For validation batches: the source goal that closed the batch. */
|
|
41
|
+
finalSourceGoalId?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Per-selected-goal snapshot of exactly what was offered.
|
|
45
|
+
*
|
|
46
|
+
* Admission compares *this*, not whole-file equality. The fence deliberately
|
|
47
|
+
* leaves unselected goals schedulable, so ordinary source progress moves
|
|
48
|
+
* `goals.json`/`ledger.jsonl` bytes; requiring whole-file equality would
|
|
49
|
+
* permanently strand the selected work through drift that never touched it
|
|
50
|
+
* (issue #5353 review item 3). Whole-file digests remain recorded as provenance
|
|
51
|
+
* and any observed drift is written into the adoption record.
|
|
52
|
+
*/
|
|
53
|
+
export interface UltragoalSuccessionSelectionSnapshot {
|
|
54
|
+
/** The brief carries global constraints, so it must not change. */
|
|
55
|
+
briefSha256: string;
|
|
56
|
+
goals: Array<{
|
|
57
|
+
sourceGoalId: string;
|
|
58
|
+
recordSha256: string;
|
|
59
|
+
obligationsSha256: string;
|
|
60
|
+
}>;
|
|
61
|
+
snapshotSha256: string;
|
|
62
|
+
}
|
|
63
|
+
export interface UltragoalSuccessionOffer {
|
|
64
|
+
schema: typeof ULTRAGOAL_SUCCESSION_OFFER_SCHEMA;
|
|
65
|
+
operationId: string;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
source: {
|
|
68
|
+
sessionId: string;
|
|
69
|
+
repository: RepositoryBinding;
|
|
70
|
+
/** Whole-file digests at offer time. Provenance; not the admission test. */
|
|
71
|
+
artifacts: UltragoalSuccessionArtifactDigests;
|
|
72
|
+
/** The authoritative admission test for "did the offered work change". */
|
|
73
|
+
selectionSnapshot: UltragoalSuccessionSelectionSnapshot;
|
|
74
|
+
skcGoalMode: UltragoalSkcGoalMode;
|
|
75
|
+
};
|
|
76
|
+
target: {
|
|
77
|
+
repository: RepositoryBinding;
|
|
78
|
+
};
|
|
79
|
+
selection: {
|
|
80
|
+
goalIds: string[];
|
|
81
|
+
};
|
|
82
|
+
carryover: {
|
|
83
|
+
/** The source brief, verbatim. */
|
|
84
|
+
brief: string;
|
|
85
|
+
goals: UltragoalSuccessionCarriedGoal[];
|
|
86
|
+
};
|
|
87
|
+
authorization: {
|
|
88
|
+
statement: string;
|
|
89
|
+
authorizedBy: string;
|
|
90
|
+
};
|
|
91
|
+
provenanceNotice: string;
|
|
92
|
+
}
|
|
93
|
+
export interface UltragoalSuccessionFence {
|
|
94
|
+
schema: typeof ULTRAGOAL_SUCCESSION_FENCE_SCHEMA;
|
|
95
|
+
operationId: string;
|
|
96
|
+
createdAt: string;
|
|
97
|
+
sourceSessionId: string;
|
|
98
|
+
sourceRepository: RepositoryBinding;
|
|
99
|
+
targetRepository: RepositoryBinding;
|
|
100
|
+
selectedGoalIds: string[];
|
|
101
|
+
sourceArtifacts: UltragoalSuccessionArtifactDigests;
|
|
102
|
+
offerPath: string;
|
|
103
|
+
offerSha256: string;
|
|
104
|
+
}
|
|
105
|
+
export interface UltragoalSuccessionGoalMapping {
|
|
106
|
+
sourceGoalId: string;
|
|
107
|
+
targetGoalId: string;
|
|
108
|
+
}
|
|
109
|
+
export interface UltragoalSuccessionAdoption {
|
|
110
|
+
schema: typeof ULTRAGOAL_SUCCESSION_ADOPTION_SCHEMA;
|
|
111
|
+
operationId: string;
|
|
112
|
+
status: "pending" | "published";
|
|
113
|
+
claimedAt: string;
|
|
114
|
+
publishedAt?: string;
|
|
115
|
+
targetSessionId: string;
|
|
116
|
+
targetRepository: RepositoryBinding;
|
|
117
|
+
source: {
|
|
118
|
+
sessionId: string;
|
|
119
|
+
repository: RepositoryBinding;
|
|
120
|
+
artifacts: UltragoalSuccessionArtifactDigests;
|
|
121
|
+
/** Whole-file digests observed at adoption; may differ from the offer. */
|
|
122
|
+
artifactsAtAdoption: UltragoalSuccessionArtifactDigests;
|
|
123
|
+
/** Whole-file drift on goals the offer did not select, recorded honestly. */
|
|
124
|
+
unselectedDrift: string[];
|
|
125
|
+
verifiedAt: string;
|
|
126
|
+
};
|
|
127
|
+
goalMap: UltragoalSuccessionGoalMapping[];
|
|
128
|
+
/**
|
|
129
|
+
* Content digest of the plan this operation is entitled to publish, recorded
|
|
130
|
+
* before publication. A pending replay may only proceed when the target plan
|
|
131
|
+
* is absent or matches this exactly; anything else is someone else's work.
|
|
132
|
+
*/
|
|
133
|
+
expectedPlanDigest: string;
|
|
134
|
+
/** Pinned so the published plan is a deterministic function of the claim. */
|
|
135
|
+
plannedAt: string;
|
|
136
|
+
offerPath: string;
|
|
137
|
+
offerSha256: string;
|
|
138
|
+
fencePath: string;
|
|
139
|
+
claimPath: string;
|
|
140
|
+
authorization: {
|
|
141
|
+
statement: string;
|
|
142
|
+
authorizedBy: string;
|
|
143
|
+
};
|
|
144
|
+
provenanceNotice: string;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Repository-wide adoption claim.
|
|
148
|
+
*
|
|
149
|
+
* The session-scoped adoption record cannot be the exclusion primitive: two
|
|
150
|
+
* simultaneous sessions in one repository each create their own file and both
|
|
151
|
+
* win. This claim is a single O_EXCL file per operation for the whole
|
|
152
|
+
* repository, so exclusion is atomic rather than scan-then-write.
|
|
153
|
+
*/
|
|
154
|
+
export interface UltragoalSuccessionRepositoryClaim {
|
|
155
|
+
schema: typeof ULTRAGOAL_SUCCESSION_CLAIM_SCHEMA;
|
|
156
|
+
operationId: string;
|
|
157
|
+
targetSessionId: string;
|
|
158
|
+
targetWorktreeRoot: string;
|
|
159
|
+
targetCommonDir: string | null;
|
|
160
|
+
claimedAt: string;
|
|
161
|
+
}
|
|
162
|
+
export declare function ultragoalSuccessionDir(cwd: string, sessionId: string): string;
|
|
163
|
+
export declare function ultragoalSuccessionFencePath(cwd: string, sessionId: string): string;
|
|
164
|
+
export declare function ultragoalSuccessionAdoptionPath(cwd: string, sessionId: string): string;
|
|
165
|
+
export declare function ultragoalSuccessionOfferPath(cwd: string, sessionId: string, operationId: string): string;
|
|
166
|
+
/**
|
|
167
|
+
* Repository-wide (deliberately NOT session-scoped) adoption claim.
|
|
168
|
+
*
|
|
169
|
+
* Session directories cannot express "this repository has already adopted this
|
|
170
|
+
* operation", so the exclusion primitive lives beside them under the shared
|
|
171
|
+
* ultragoal root that `getUltragoalPaths` already uses for session-less state.
|
|
172
|
+
*/
|
|
173
|
+
export declare function ultragoalSuccessionClaimPath(cwd: string, operationId: string): string;
|
|
174
|
+
/** Read the durable outgoing ownership fence for a source session, if any. */
|
|
175
|
+
export declare function readUltragoalSuccessionFence(cwd: string, sessionId: string): Promise<UltragoalSuccessionFence | null>;
|
|
176
|
+
/** Read the durable adoption claim for a target session, if any. */
|
|
177
|
+
export declare function readUltragoalSuccessionAdoption(cwd: string, sessionId: string): Promise<UltragoalSuccessionAdoption | null>;
|
|
178
|
+
/**
|
|
179
|
+
* Source admission guard: a goal that has been handed off to a successor run is
|
|
180
|
+
* no longer this run's to schedule or checkpoint.
|
|
181
|
+
*
|
|
182
|
+
* Goals outside the fenced selection stay fully schedulable — the fence defines
|
|
183
|
+
* one owner per goal, not a freeze of the whole source run.
|
|
184
|
+
*/
|
|
185
|
+
export declare function assertUltragoalGoalNotFenced(cwd: string, sessionId: string | null | undefined, goalId: string): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Target admission guard: an adoption that has not finished publishing does not
|
|
188
|
+
* yet own anything.
|
|
189
|
+
*
|
|
190
|
+
* Publication writes `goals.json` before it marks the claim published, so a
|
|
191
|
+
* crash leaves a *visible plan with an unpublished claim*. A visible plan is not
|
|
192
|
+
* admission evidence — the claim is. Without this, the target executes goals
|
|
193
|
+
* whose adoption was never completed, and the run's own completion receipts
|
|
194
|
+
* would rest on a transaction that never committed.
|
|
195
|
+
*
|
|
196
|
+
* Callers must invoke this before any mutation so a refusal leaves `goals.json`
|
|
197
|
+
* and `ledger.jsonl` untouched.
|
|
198
|
+
*/
|
|
199
|
+
export declare function assertUltragoalAdoptionPublished(cwd: string, sessionId: string | null | undefined): Promise<void>;
|
|
200
|
+
export interface UltragoalSuccessionOfferInput {
|
|
201
|
+
cwd: string;
|
|
202
|
+
sessionId?: string | null;
|
|
203
|
+
targetRepositoryPath: string;
|
|
204
|
+
goalIds: readonly string[];
|
|
205
|
+
authorization: string;
|
|
206
|
+
authorizedBy: string;
|
|
207
|
+
}
|
|
208
|
+
export interface UltragoalSuccessionOfferResult {
|
|
209
|
+
operationId: string;
|
|
210
|
+
offerPath: string;
|
|
211
|
+
fencePath: string;
|
|
212
|
+
offer: UltragoalSuccessionOffer;
|
|
213
|
+
/** True when an identical prior operation was reconciled instead of re-recorded. */
|
|
214
|
+
reconciled: boolean;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Record an explicit successor offer and fence the selected goals off from the
|
|
218
|
+
* source run. Writes nothing to the source brief, goals or ledger.
|
|
219
|
+
*/
|
|
220
|
+
export declare function offerUltragoalSuccession(input: UltragoalSuccessionOfferInput): Promise<UltragoalSuccessionOfferResult>;
|
|
221
|
+
export interface UltragoalSuccessionAdoptInput {
|
|
222
|
+
cwd: string;
|
|
223
|
+
sessionId?: string | null;
|
|
224
|
+
offerPath: string;
|
|
225
|
+
skcGoalMode?: UltragoalSkcGoalMode;
|
|
226
|
+
}
|
|
227
|
+
export interface UltragoalSuccessionAdoptResult {
|
|
228
|
+
operationId: string;
|
|
229
|
+
adoptionPath: string;
|
|
230
|
+
plan: UltragoalPlan;
|
|
231
|
+
goalMap: UltragoalSuccessionGoalMapping[];
|
|
232
|
+
reconciled: boolean;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Adopt an explicit successor offer into this repository/session.
|
|
236
|
+
*
|
|
237
|
+
* Fails closed on a forged or stale offer, a changed source, a missing source
|
|
238
|
+
* fence, an unnamed target, an occupied target, and any duplicate or divergent
|
|
239
|
+
* adoption anywhere in this repository. A retry reconciles the exact recorded
|
|
240
|
+
* operation or fails closed; it never resumes a different one.
|
|
241
|
+
*/
|
|
242
|
+
export declare function adoptUltragoalSuccession(input: UltragoalSuccessionAdoptInput): Promise<UltragoalSuccessionAdoptResult>;
|
|
243
|
+
/**
|
|
244
|
+
* `skc ultragoal succession <offer|adopt|status>`.
|
|
245
|
+
*
|
|
246
|
+
* Kept out of `RECONCILE_COMMANDS` on purpose: the reconcile pass appends a
|
|
247
|
+
* `reconcile_failed` ledger row on failure, which would move the very source
|
|
248
|
+
* digests this feature records. The target's workflow state and HUD reconcile on
|
|
249
|
+
* the next ordinary `skc ultragoal status`.
|
|
250
|
+
*/
|
|
251
|
+
export declare function runUltragoalSuccessionCommand(args: readonly string[], cwd: string): Promise<UltragoalCommandResult>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Shared placeholder semantics for model-authored workflow content. */
|
|
2
|
+
export declare const WORKFLOW_PLACEHOLDER_CORRECTION = "provide a specific, non-placeholder question or objective instead of empty, whitespace, unused, TODO, TBD, N/A, N-A, NA, none, placeholder, or stub";
|
|
3
|
+
/** Exact, case-insensitive placeholder detection; meaningful sentences remain valid. */
|
|
4
|
+
export declare function isWorkflowPlaceholderText(value: unknown): boolean;
|
|
5
|
+
/** Detect a legacy formatted deep-interview ask whose visible body is a placeholder. */
|
|
6
|
+
export declare function isLegacyDeepInterviewPlaceholder(value: unknown): boolean;
|