@gajae-code/coding-agent 0.2.5 → 0.3.0
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 +10 -0
- package/dist/types/async/job-manager.d.ts +84 -2
- package/dist/types/commands/harness.d.ts +37 -0
- package/dist/types/config/settings-schema.d.ts +6 -0
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/deep-interview/render-middleware.d.ts +5 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -0
- package/dist/types/gjc-runtime/state-graph.d.ts +4 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +24 -0
- package/dist/types/gjc-runtime/state-renderer.d.ts +65 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/state-validation.d.ts +6 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +137 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +54 -0
- package/dist/types/harness-control-plane/classifier.d.ts +13 -0
- package/dist/types/harness-control-plane/control-endpoint.d.ts +30 -0
- package/dist/types/harness-control-plane/finalize.d.ts +47 -0
- package/dist/types/harness-control-plane/frame-mapper.d.ts +29 -0
- package/dist/types/harness-control-plane/operate.d.ts +35 -0
- package/dist/types/harness-control-plane/owner.d.ts +46 -0
- package/dist/types/harness-control-plane/preserve.d.ts +19 -0
- package/dist/types/harness-control-plane/receipts.d.ts +88 -0
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +66 -0
- package/dist/types/harness-control-plane/seams.d.ts +21 -0
- package/dist/types/harness-control-plane/session-lease.d.ts +65 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +19 -0
- package/dist/types/harness-control-plane/storage.d.ts +53 -0
- package/dist/types/harness-control-plane/types.d.ts +162 -0
- package/dist/types/hooks/skill-keywords.d.ts +2 -1
- package/dist/types/hooks/skill-state.d.ts +2 -29
- package/dist/types/modes/components/hook-selector.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +8 -0
- package/dist/types/skill-state/active-state.d.ts +2 -0
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
- package/dist/types/skill-state/workflow-state-contract.d.ts +24 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/types.d.ts +55 -3
- package/dist/types/tools/subagent.d.ts +11 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +298 -6
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/config-cli.ts +10 -2
- package/src/cli.ts +2 -0
- package/src/commands/harness.ts +592 -0
- package/src/commands/team.ts +36 -39
- package/src/config/settings-schema.ts +7 -0
- package/src/config/settings.ts +5 -0
- package/src/deep-interview/render-middleware.ts +366 -0
- package/src/defaults/gjc/skills/team/SKILL.md +47 -21
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +78 -11
- package/src/extensibility/custom-tools/types.ts +1 -0
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/extensibility/shared-events.ts +1 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +40 -21
- package/src/gjc-runtime/goal-mode-request.ts +11 -3
- package/src/gjc-runtime/ralplan-runtime.ts +25 -10
- package/src/gjc-runtime/state-graph.ts +86 -0
- package/src/gjc-runtime/state-migrations.ts +132 -0
- package/src/gjc-runtime/state-renderer.ts +345 -0
- package/src/gjc-runtime/state-runtime.ts +733 -21
- package/src/gjc-runtime/state-validation.ts +49 -0
- package/src/gjc-runtime/state-writer.ts +718 -0
- package/src/gjc-runtime/team-runtime.ts +1083 -89
- package/src/gjc-runtime/ultragoal-runtime.ts +348 -19
- package/src/gjc-runtime/workflow-manifest.generated.json +1497 -0
- package/src/gjc-runtime/workflow-manifest.ts +425 -0
- package/src/harness-control-plane/classifier.ts +128 -0
- package/src/harness-control-plane/control-endpoint.ts +137 -0
- package/src/harness-control-plane/finalize.ts +222 -0
- package/src/harness-control-plane/frame-mapper.ts +286 -0
- package/src/harness-control-plane/operate.ts +225 -0
- package/src/harness-control-plane/owner.ts +553 -0
- package/src/harness-control-plane/preserve.ts +102 -0
- package/src/harness-control-plane/receipts.ts +216 -0
- package/src/harness-control-plane/rpc-adapter.ts +276 -0
- package/src/harness-control-plane/seams.ts +39 -0
- package/src/harness-control-plane/session-lease.ts +388 -0
- package/src/harness-control-plane/state-machine.ts +97 -0
- package/src/harness-control-plane/storage.ts +257 -0
- package/src/harness-control-plane/types.ts +214 -0
- package/src/hooks/skill-keywords.ts +4 -2
- package/src/hooks/skill-state.ts +24 -41
- package/src/internal-urls/docs-index.generated.ts +1 -1
- package/src/modes/components/assistant-message.ts +5 -1
- package/src/modes/components/hook-selector.ts +72 -2
- package/src/modes/controllers/event-controller.ts +71 -6
- package/src/modes/controllers/extension-ui-controller.ts +6 -0
- package/src/modes/controllers/input-controller.ts +9 -1
- package/src/modes/controllers/selector-controller.ts +2 -1
- package/src/modes/interactive-mode.ts +1 -0
- package/src/modes/types.ts +1 -0
- package/src/prompts/agents/executor.md +13 -0
- package/src/prompts/tools/subagent.md +33 -3
- package/src/sdk.ts +4 -0
- package/src/session/agent-session.ts +231 -33
- package/src/session/session-manager.ts +13 -1
- package/src/skill-state/active-state.ts +58 -65
- package/src/skill-state/deep-interview-mutation-guard.ts +91 -13
- package/src/skill-state/initial-phase.ts +2 -0
- package/src/skill-state/workflow-state-contract.ts +26 -0
- package/src/task/executor.ts +50 -8
- package/src/task/index.ts +120 -8
- package/src/task/render.ts +6 -3
- package/src/task/types.ts +56 -3
- package/src/tools/ask.ts +28 -7
- package/src/tools/subagent.ts +255 -64
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-06-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added runtime-enforced Ultragoal executor QA/red-team evidence matrices for completion checkpoints, with plan-first contract coverage, user-surface evidence, adversarial cases, artifact references, scoped Executor red-team guidance, and focused rejection tests for shallow or contradictory QA evidence.
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Clarified that `gjc team` requires an existing tmux-backed leader session from `gjc --tmux`, with actionable help, docs, and failure text.
|
|
13
|
+
- Kept deep-interview ask options visible for long prompts by adding an opt-in scrollable selector title panel with selector-local `PageUp`/`PageDown` prompt scrolling, while leaving normal ask dialogs and global keybinding configuration unchanged.
|
|
14
|
+
|
|
5
15
|
## [0.2.5] - 2026-06-02
|
|
6
16
|
|
|
7
17
|
### Added
|
|
@@ -2,7 +2,7 @@ import type { AgentSource } from "../task/types";
|
|
|
2
2
|
export interface AsyncJob {
|
|
3
3
|
id: string;
|
|
4
4
|
type: "bash" | "task";
|
|
5
|
-
status: "running" | "completed" | "failed" | "cancelled";
|
|
5
|
+
status: "running" | "completed" | "failed" | "cancelled" | "paused";
|
|
6
6
|
startTime: number;
|
|
7
7
|
label: string;
|
|
8
8
|
abortController: AbortController;
|
|
@@ -27,6 +27,61 @@ export interface AsyncJobMetadata {
|
|
|
27
27
|
assignment?: string;
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Typed outcome a subagent task run may produce. A `paused` outcome is
|
|
32
|
+
* non-terminal and non-delivering: the run suspended at a safe boundary and the
|
|
33
|
+
* subagent can be resumed from its persisted sessionFile. `completed` always
|
|
34
|
+
* wins a race with a late pause because the run returns it once it has actually
|
|
35
|
+
* finished.
|
|
36
|
+
*/
|
|
37
|
+
export type SubagentRunOutcome = {
|
|
38
|
+
kind: "completed";
|
|
39
|
+
text: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "paused";
|
|
42
|
+
note?: string;
|
|
43
|
+
};
|
|
44
|
+
/** Canonical lifecycle of a subagent across pause/resume cycles. */
|
|
45
|
+
export type SubagentLifecycle = "running" | "paused" | "queued" | "completed" | "failed" | "cancelled";
|
|
46
|
+
/**
|
|
47
|
+
* Live, executor-owned control handle for a RUNNING subagent. Registered when a
|
|
48
|
+
* subagent run starts and removed on pause/terminal so a paused subagent retains
|
|
49
|
+
* no live `AgentSession` reference (leak-free).
|
|
50
|
+
*/
|
|
51
|
+
export interface SubagentLiveHandle {
|
|
52
|
+
/** Request a cooperative safe-boundary pause (never aborts the in-flight tool). */
|
|
53
|
+
requestPause(): void;
|
|
54
|
+
/** Inject a steering message into the live session. */
|
|
55
|
+
injectMessage(content: string, deliverAs: "steer" | "followUp" | "nextTurn"): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Canonical, stable-id-keyed record for a subagent. Survives `AsyncJob`
|
|
59
|
+
* eviction so resume stays addressable by subagent id, and is the single source
|
|
60
|
+
* of truth for control-plane status and identity.
|
|
61
|
+
*/
|
|
62
|
+
export interface SubagentRecord {
|
|
63
|
+
subagentId: string;
|
|
64
|
+
ownerId?: string;
|
|
65
|
+
/** Current live/last AsyncJob id; null while queued with no active job. */
|
|
66
|
+
currentJobId: string | null;
|
|
67
|
+
historicalJobIds: string[];
|
|
68
|
+
status: SubagentLifecycle;
|
|
69
|
+
sessionFile: string | null;
|
|
70
|
+
/** False for ephemeral sessions (no persistent artifacts dir). */
|
|
71
|
+
resumable: boolean;
|
|
72
|
+
queued?: {
|
|
73
|
+
ownerId?: string;
|
|
74
|
+
seq: number;
|
|
75
|
+
message?: string;
|
|
76
|
+
createdAt: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Lightweight, manager-owned resume payload. The async layer treats `data` as opaque. */
|
|
80
|
+
export interface ResumeDescriptor {
|
|
81
|
+
subagentId: string;
|
|
82
|
+
ownerId?: string;
|
|
83
|
+
data: unknown;
|
|
84
|
+
}
|
|
30
85
|
export interface AsyncJobManagerOptions {
|
|
31
86
|
onJobComplete: (jobId: string, text: string, job?: AsyncJob) => void | Promise<void>;
|
|
32
87
|
maxRunningJobs?: number;
|
|
@@ -88,13 +143,40 @@ export declare class AsyncJobManager {
|
|
|
88
143
|
jobId: string;
|
|
89
144
|
signal: AbortSignal;
|
|
90
145
|
reportProgress: (text: string, details?: Record<string, unknown>) => Promise<void>;
|
|
91
|
-
}) => Promise<string>, options?: AsyncJobRegisterOptions): string;
|
|
146
|
+
}) => Promise<string | SubagentRunOutcome>, options?: AsyncJobRegisterOptions): string;
|
|
92
147
|
/**
|
|
93
148
|
* Cancel a single job by id. When `filter.ownerId` is set and does not
|
|
94
149
|
* match the job's owner, the call is treated as not-found (returns false)
|
|
95
150
|
* so cross-agent cancellation is rejected at the manager level.
|
|
96
151
|
*/
|
|
97
152
|
cancel(id: string, filter?: AsyncJobFilter): boolean;
|
|
153
|
+
/** Register or replace the canonical record for a subagent. */
|
|
154
|
+
registerSubagentRecord(record: SubagentRecord): void;
|
|
155
|
+
getSubagentRecord(subagentId: string, filter?: AsyncJobFilter): SubagentRecord | undefined;
|
|
156
|
+
getSubagentRecords(filter?: AsyncJobFilter): SubagentRecord[];
|
|
157
|
+
registerLiveHandle(subagentId: string, handle: SubagentLiveHandle): void;
|
|
158
|
+
getLiveHandle(subagentId: string): SubagentLiveHandle | undefined;
|
|
159
|
+
removeLiveHandle(subagentId: string): void;
|
|
160
|
+
/** Install the TaskTool-owned resume runner. Returns the new job id, or undefined on failure. */
|
|
161
|
+
setResumeRunner(runner: (subagentId: string, message?: string, descriptor?: ResumeDescriptor) => string | undefined): void;
|
|
162
|
+
registerResumeDescriptor(descriptor: ResumeDescriptor): void;
|
|
163
|
+
getResumeDescriptor(subagentId: string, filter?: AsyncJobFilter): ResumeDescriptor | undefined;
|
|
164
|
+
/** Request a graceful safe-boundary pause of a running subagent. */
|
|
165
|
+
pauseSubagent(subagentId: string, filter?: AsyncJobFilter): {
|
|
166
|
+
ok: boolean;
|
|
167
|
+
status?: SubagentLifecycle;
|
|
168
|
+
reason?: string;
|
|
169
|
+
};
|
|
170
|
+
/** Resume a non-running subagent from its sessionFile, optionally injecting a message first. */
|
|
171
|
+
resumeSubagent(subagentId: string, filter?: AsyncJobFilter, message?: string): {
|
|
172
|
+
ok: boolean;
|
|
173
|
+
status?: SubagentLifecycle;
|
|
174
|
+
jobId?: string;
|
|
175
|
+
queued?: boolean;
|
|
176
|
+
reason?: string;
|
|
177
|
+
};
|
|
178
|
+
/** Cancel a subagent by stable id across running/paused/queued states (keeps the session file). */
|
|
179
|
+
cancelSubagent(subagentId: string, filter?: AsyncJobFilter): boolean;
|
|
98
180
|
getJob(id: string): AsyncJob | undefined;
|
|
99
181
|
getRunningJobs(filter?: AsyncJobFilter): AsyncJob[];
|
|
100
182
|
getRecentJobs(limit?: number, filter?: AsyncJobFilter): AsyncJob[];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Command } from "@gajae-code/utils/cli";
|
|
2
|
+
export default class Harness extends Command {
|
|
3
|
+
#private;
|
|
4
|
+
static description: string;
|
|
5
|
+
static strict: boolean;
|
|
6
|
+
static args: {
|
|
7
|
+
verb: import("@gajae-code/utils/cli").ArgDescriptor & {
|
|
8
|
+
description: string;
|
|
9
|
+
required: true;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
static flags: {
|
|
13
|
+
input: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
14
|
+
description: string;
|
|
15
|
+
default: string;
|
|
16
|
+
};
|
|
17
|
+
session: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
18
|
+
char: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
cursor: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
22
|
+
description: string;
|
|
23
|
+
default: string;
|
|
24
|
+
};
|
|
25
|
+
follow: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
|
|
26
|
+
description: string;
|
|
27
|
+
default: boolean;
|
|
28
|
+
};
|
|
29
|
+
json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
|
|
30
|
+
char: string;
|
|
31
|
+
description: string;
|
|
32
|
+
default: boolean;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
static examples: string[];
|
|
36
|
+
run(): Promise<void>;
|
|
37
|
+
}
|
|
@@ -74,6 +74,7 @@ interface StringDef {
|
|
|
74
74
|
interface NumberDef {
|
|
75
75
|
type: "number";
|
|
76
76
|
default: number;
|
|
77
|
+
validate?: (value: number) => boolean;
|
|
77
78
|
ui?: UiNumber;
|
|
78
79
|
}
|
|
79
80
|
interface EnumDef<T extends readonly string[]> {
|
|
@@ -200,6 +201,11 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
200
201
|
readonly type: "array";
|
|
201
202
|
readonly default: string[];
|
|
202
203
|
};
|
|
204
|
+
readonly "gjc.deepInterview.ambiguityThreshold": {
|
|
205
|
+
readonly type: "number";
|
|
206
|
+
readonly default: 0.05;
|
|
207
|
+
readonly validate: (value: number) => boolean;
|
|
208
|
+
};
|
|
203
209
|
readonly "theme.dark": {
|
|
204
210
|
readonly type: "string";
|
|
205
211
|
readonly default: "red-claw";
|
|
@@ -54,6 +54,8 @@ export declare class Settings {
|
|
|
54
54
|
* Returns the merged value from global + project + overrides, or the default.
|
|
55
55
|
*/
|
|
56
56
|
get<P extends SettingPath>(path: P): SettingValue<P>;
|
|
57
|
+
/** Check whether a setting is present in loaded settings/overrides rather than coming from schema defaults. */
|
|
58
|
+
has(path: SettingPath): boolean;
|
|
57
59
|
/**
|
|
58
60
|
* Set a setting value (sync).
|
|
59
61
|
* Updates global settings and queues a background save.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Component } from "@gajae-code/tui";
|
|
2
|
+
import { type Theme } from "../modes/theme/theme";
|
|
3
|
+
export declare function renderDeepInterviewAssistantText(text: string, uiTheme: Theme): Component | null;
|
|
4
|
+
export declare function renderDeepInterviewAskQuestion(question: string, uiTheme: Theme): Component | null;
|
|
5
|
+
export declare function formatDeepInterviewSelectorPrompt(question: string): string | null;
|
|
@@ -56,6 +56,12 @@ export interface ExtensionUIDialogOptions {
|
|
|
56
56
|
* hint; non-TUI bridges (RPC, ACP) drop it and do not serialize it.
|
|
57
57
|
*/
|
|
58
58
|
wrapFocused?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* For interactive TUI select dialogs, cap the title/prompt area to this
|
|
61
|
+
* many rows and let PageUp/PageDown scroll that prompt locally. This is a
|
|
62
|
+
* select-only rendering hint; non-TUI bridges drop it and do not serialize it.
|
|
63
|
+
*/
|
|
64
|
+
scrollTitleRows?: number;
|
|
59
65
|
}
|
|
60
66
|
/** Raw terminal input listener for extensions. */
|
|
61
67
|
export type TerminalInputHandler = (data: string) => {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
2
|
+
export type StateGraphSkill = CanonicalGjcWorkflowSkill | "all";
|
|
3
|
+
export type StateGraphFormat = "ascii" | "mermaid" | "dot";
|
|
4
|
+
export declare function renderStateGraph(skill: StateGraphSkill, format?: string): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface NormalizeLegacyStateResult {
|
|
2
|
+
state: Record<string, unknown>;
|
|
3
|
+
changed: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface MigrateAndPersistLegacyStateArgs {
|
|
6
|
+
cwd: string;
|
|
7
|
+
skill: string;
|
|
8
|
+
statePath: string;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface MigrateAndPersistLegacyStateResult {
|
|
12
|
+
migrated: boolean;
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Pure legacy state normalizer for background/internal readers.
|
|
17
|
+
*
|
|
18
|
+
* Readers that need compatibility with old on-disk workflow state shapes must call
|
|
19
|
+
* this in-memory helper and must never call `migrateAndPersistLegacyState`. The
|
|
20
|
+
* persist variant is reserved for explicit state migration commands because it is
|
|
21
|
+
* the only path allowed to write normalized upgrades back to `.gjc/state/**`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeLegacyState(raw: Record<string, unknown>, skill: string): NormalizeLegacyStateResult;
|
|
24
|
+
export declare function migrateAndPersistLegacyState(args: MigrateAndPersistLegacyStateArgs): Promise<MigrateAndPersistLegacyStateResult>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
2
|
+
import type { SkillManifest } from "./workflow-manifest";
|
|
3
|
+
export declare const STATE_FIELD_ALLOWLIST: readonly ["skill", "phase", "current_phase", "next", "active", "status", "fresh", "fresh_until", "receipt", "artifact_path", "plan_path", "spec_path", "run_id", "stage", "stage_n", "session_id", "updated_at", "handoff_to", "handoff_from", "counts", "hud"];
|
|
4
|
+
export type StateProjectionField = (typeof STATE_FIELD_ALLOWLIST)[number];
|
|
5
|
+
export interface StateStatusSummary {
|
|
6
|
+
skill: CanonicalGjcWorkflowSkill;
|
|
7
|
+
phase: string;
|
|
8
|
+
active: boolean;
|
|
9
|
+
fresh: boolean;
|
|
10
|
+
fresh_until?: string;
|
|
11
|
+
next: string[];
|
|
12
|
+
receipt_status: string;
|
|
13
|
+
storage_path: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function compactProjectStateJson(skill: CanonicalGjcWorkflowSkill, stateJson: Record<string, unknown>, manifest: SkillManifest): Record<string, unknown>;
|
|
16
|
+
export declare function projectStateFields(skill: CanonicalGjcWorkflowSkill, stateJson: Record<string, unknown>, manifest: SkillManifest, fields: readonly StateProjectionField[]): Record<string, unknown>;
|
|
17
|
+
export declare function buildStateStatusSummary(skill: CanonicalGjcWorkflowSkill, stateJson: Record<string, unknown>, manifest: SkillManifest, storagePath: string): StateStatusSummary;
|
|
18
|
+
export declare function renderStateStatusLine(summary: StateStatusSummary): string;
|
|
19
|
+
export declare function renderContractMarkdown(skill: CanonicalGjcWorkflowSkill, contract: unknown): string;
|
|
20
|
+
export declare function renderHistoryMarkdown(history: {
|
|
21
|
+
entries: unknown[];
|
|
22
|
+
limit: number;
|
|
23
|
+
since?: string;
|
|
24
|
+
truncated: boolean;
|
|
25
|
+
}): string;
|
|
26
|
+
export declare function renderUltragoalStatusMarkdown(summary: {
|
|
27
|
+
exists: boolean;
|
|
28
|
+
status: string;
|
|
29
|
+
paths: {
|
|
30
|
+
goalsPath: string;
|
|
31
|
+
ledgerPath?: string;
|
|
32
|
+
};
|
|
33
|
+
gjcObjective?: string;
|
|
34
|
+
currentGoal?: {
|
|
35
|
+
id: string;
|
|
36
|
+
status: string;
|
|
37
|
+
title?: string;
|
|
38
|
+
objective?: string;
|
|
39
|
+
};
|
|
40
|
+
counts: Record<string, number>;
|
|
41
|
+
goals: unknown[];
|
|
42
|
+
}): string;
|
|
43
|
+
export declare function renderTeamStatusMarkdown(snapshot: {
|
|
44
|
+
team_name: string;
|
|
45
|
+
phase: string;
|
|
46
|
+
tmux_target?: string;
|
|
47
|
+
tmux_session?: string;
|
|
48
|
+
state_dir: string;
|
|
49
|
+
task_total: number;
|
|
50
|
+
task_counts: Record<string, number>;
|
|
51
|
+
workers: Array<{
|
|
52
|
+
id: string;
|
|
53
|
+
status: string;
|
|
54
|
+
}>;
|
|
55
|
+
notification_summary?: {
|
|
56
|
+
total: number;
|
|
57
|
+
replay_eligible: number;
|
|
58
|
+
by_state: Record<string, number>;
|
|
59
|
+
};
|
|
60
|
+
integration_by_worker?: Record<string, {
|
|
61
|
+
status?: string;
|
|
62
|
+
conflict_files?: string[];
|
|
63
|
+
}>;
|
|
64
|
+
}): string;
|
|
65
|
+
export declare function renderStateMarkdown(skill: CanonicalGjcWorkflowSkill, stateJson: Record<string, unknown>, manifest: SkillManifest): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
1
2
|
/**
|
|
2
3
|
* Native implementation of the `gjc state read|write|clear` command surface.
|
|
3
4
|
*
|
|
@@ -10,4 +11,5 @@ export interface StateCommandResult {
|
|
|
10
11
|
stdout?: string;
|
|
11
12
|
stderr?: string;
|
|
12
13
|
}
|
|
14
|
+
export declare function readWorkflowStateJson(cwd: string, skill: CanonicalGjcWorkflowSkill, sessionId?: string): Promise<Record<string, unknown>>;
|
|
13
15
|
export declare function runNativeStateCommand(args: string[], cwd?: string): Promise<StateCommandResult>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
2
|
+
export interface StateValidationResult {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
error?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function validateWorkflowStateEnvelope(skill: CanonicalGjcWorkflowSkill, state: unknown): StateValidationResult;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import type { SkillActiveEntry } from "../skill-state/active-state";
|
|
3
|
+
import { type AuditEntry, type CanonicalGjcWorkflowSkill, type WorkflowStateMutationOwner } from "../skill-state/workflow-state-contract";
|
|
4
|
+
/**
|
|
5
|
+
* Sole sanctioned project `.gjc/**` writer module (gate G1).
|
|
6
|
+
*
|
|
7
|
+
* All native `.gjc/**` filesystem mutations must route through these primitives.
|
|
8
|
+
* The primitives validate project `.gjc/**` ownership, create parent directories,
|
|
9
|
+
* and emit workflow receipts or audit entries where applicable by the caller's
|
|
10
|
+
* supplied mutation context. No lockfiles are used; isolation is by atomic rename,
|
|
11
|
+
* append, O_EXCL creates, conditional deletes, per-entry active-state files,
|
|
12
|
+
* and derived active-state snapshots.
|
|
13
|
+
* Transaction journals are per mutation id under `.gjc/state/transactions/`;
|
|
14
|
+
* they are recovery evidence only, never global locks or waiters, so stale
|
|
15
|
+
* journals do not block unrelated state reads or writes.
|
|
16
|
+
*/
|
|
17
|
+
export type WriterCategory = "state" | "artifact" | "ledger" | "log" | "report" | "agents" | "prune" | "force" | "transaction";
|
|
18
|
+
export interface StateWriterReceiptContext {
|
|
19
|
+
cwd?: string;
|
|
20
|
+
skill: CanonicalGjcWorkflowSkill;
|
|
21
|
+
owner: WorkflowStateMutationOwner;
|
|
22
|
+
command: string;
|
|
23
|
+
sessionId?: string;
|
|
24
|
+
mutationId?: string;
|
|
25
|
+
nowIso?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface StateWriterAuditContext {
|
|
28
|
+
cwd?: string;
|
|
29
|
+
category: WriterCategory;
|
|
30
|
+
verb: string;
|
|
31
|
+
owner: WorkflowStateMutationOwner;
|
|
32
|
+
skill?: CanonicalGjcWorkflowSkill | string;
|
|
33
|
+
mutationId?: string;
|
|
34
|
+
fromPhase?: string;
|
|
35
|
+
toPhase?: string;
|
|
36
|
+
forced?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface WorkflowEnvelopeIntegrityMismatch {
|
|
39
|
+
path: string;
|
|
40
|
+
expected: string;
|
|
41
|
+
actual: string;
|
|
42
|
+
}
|
|
43
|
+
export interface WorkflowTransactionJournal {
|
|
44
|
+
version: 1;
|
|
45
|
+
mutation_id: string;
|
|
46
|
+
status: "pending" | "committed";
|
|
47
|
+
created_at: string;
|
|
48
|
+
updated_at: string;
|
|
49
|
+
caller?: CanonicalGjcWorkflowSkill;
|
|
50
|
+
callee?: CanonicalGjcWorkflowSkill;
|
|
51
|
+
paths: string[];
|
|
52
|
+
steps: string[];
|
|
53
|
+
}
|
|
54
|
+
export interface StateWriterOptions {
|
|
55
|
+
cwd?: string;
|
|
56
|
+
receipt?: StateWriterReceiptContext;
|
|
57
|
+
audit?: StateWriterAuditContext;
|
|
58
|
+
}
|
|
59
|
+
export interface DeleteIfOwnedOptions extends StateWriterOptions {
|
|
60
|
+
predicate?: (current: unknown) => boolean | Promise<boolean>;
|
|
61
|
+
}
|
|
62
|
+
export interface DeleteResult {
|
|
63
|
+
path: string;
|
|
64
|
+
deleted: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface ActiveSessionScope {
|
|
67
|
+
sessionId?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface ActiveEntryWriteResult {
|
|
70
|
+
entryPath: string;
|
|
71
|
+
snapshotPath: string;
|
|
72
|
+
}
|
|
73
|
+
export interface HardPruneSelectorContext {
|
|
74
|
+
path: string;
|
|
75
|
+
value: unknown;
|
|
76
|
+
}
|
|
77
|
+
export interface GenericHardPruneTarget {
|
|
78
|
+
path: string;
|
|
79
|
+
category: WriterCategory | string;
|
|
80
|
+
}
|
|
81
|
+
export interface GenericHardPruneSelectorContext {
|
|
82
|
+
path: string;
|
|
83
|
+
category: WriterCategory | string;
|
|
84
|
+
stat: Awaited<ReturnType<typeof fs.stat>>;
|
|
85
|
+
readJson: () => Promise<unknown>;
|
|
86
|
+
}
|
|
87
|
+
export type GenericHardPruneSelector = (context: GenericHardPruneSelectorContext) => boolean | Promise<boolean>;
|
|
88
|
+
export interface ForceOverwriteOptions extends StateWriterOptions {
|
|
89
|
+
raw?: boolean;
|
|
90
|
+
}
|
|
91
|
+
export type HardPruneSelector = (context: HardPruneSelectorContext) => boolean | Promise<boolean>;
|
|
92
|
+
export declare class AlreadyExistsError extends Error {
|
|
93
|
+
readonly path: string;
|
|
94
|
+
constructor(path: string);
|
|
95
|
+
}
|
|
96
|
+
export declare function workflowEnvelopeContentSha256(value: unknown): string;
|
|
97
|
+
export declare function stampWorkflowEnvelopeChecksum<T>(value: T, filePath: string, computedAt?: string): T;
|
|
98
|
+
export declare function detectWorkflowEnvelopeIntegrityMismatch(filePath: string): Promise<WorkflowEnvelopeIntegrityMismatch | undefined>;
|
|
99
|
+
export declare function writeJsonAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
100
|
+
export declare function writeWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
101
|
+
export declare function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
|
|
102
|
+
export declare function updateJsonAtomic<T = unknown>(targetPath: string, mutator: (current: T | undefined) => T | Promise<T>, options?: StateWriterOptions): Promise<string>;
|
|
103
|
+
export declare function appendJsonl(targetPath: string, entry: unknown, options?: StateWriterOptions): Promise<string>;
|
|
104
|
+
export declare function appendText(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
|
|
105
|
+
export declare function createJsonNoClobber(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
106
|
+
export declare function deleteIfOwned(targetPath: string, predicateOrOptions?: ((current: unknown) => boolean | Promise<boolean>) | DeleteIfOwnedOptions): Promise<DeleteResult>;
|
|
107
|
+
export declare function removeFileAudited(targetPath: string, options?: StateWriterOptions): Promise<DeleteResult>;
|
|
108
|
+
/**
|
|
109
|
+
* Active entry files under `.gjc/state/active/<skill>.json` and
|
|
110
|
+
* `.gjc/state/sessions/<id>/active/<skill>.json` are authoritative. The
|
|
111
|
+
* adjacent `skill-active-state.json` file is only a derived cache rebuilt from
|
|
112
|
+
* those entries, so concurrent snapshot rebuilds can race without losing any
|
|
113
|
+
* writer's per-skill state.
|
|
114
|
+
*/
|
|
115
|
+
export declare function writeActiveEntry(cwd: string, sessionScope: string | ActiveSessionScope | undefined, skill: string, entry: SkillActiveEntry, options?: StateWriterOptions): Promise<string>;
|
|
116
|
+
export declare function removeActiveEntry(cwd: string, sessionScope: string | ActiveSessionScope | undefined, skill: string, options?: StateWriterOptions): Promise<DeleteResult>;
|
|
117
|
+
export declare function readActiveEntries(cwd: string, sessionScope?: string | ActiveSessionScope): Promise<SkillActiveEntry[]>;
|
|
118
|
+
export declare function rebuildActiveSnapshot(cwd: string, sessionScope?: string | ActiveSessionScope, options?: StateWriterOptions): Promise<string>;
|
|
119
|
+
export declare function mergeActiveState(cwd: string, sessionScope: string | ActiveSessionScope | undefined, skill: string, entry: SkillActiveEntry, options?: StateWriterOptions): Promise<ActiveEntryWriteResult>;
|
|
120
|
+
export declare function writeArtifact(targetPath: string, content: string, options?: StateWriterOptions): Promise<string>;
|
|
121
|
+
export declare function writeReport(targetPath: string, content: string, options?: StateWriterOptions): Promise<string>;
|
|
122
|
+
export declare function writeLogJsonl(targetPath: string, entry: unknown, options?: StateWriterOptions): Promise<string>;
|
|
123
|
+
export declare function softDelete(targetPath: string, meta: Record<string, unknown>, options?: StateWriterOptions): Promise<string>;
|
|
124
|
+
export declare function hardPruneJson(targetPaths: readonly string[], selector: HardPruneSelector, options?: StateWriterOptions): Promise<string[]>;
|
|
125
|
+
export declare function hardPrune(targets: readonly GenericHardPruneTarget[], selector: GenericHardPruneSelector, options?: StateWriterOptions): Promise<string[]>;
|
|
126
|
+
export declare function forceOverwrite(targetPath: string, rawValue: unknown, options?: ForceOverwriteOptions): Promise<string>;
|
|
127
|
+
export declare function appendAuditEntry(cwd: string, entry: AuditEntry): Promise<string>;
|
|
128
|
+
export declare function readWorkflowTransactionJournal(cwd: string, mutationId: string): Promise<WorkflowTransactionJournal | undefined>;
|
|
129
|
+
export declare function beginWorkflowTransactionJournal(input: {
|
|
130
|
+
cwd: string;
|
|
131
|
+
mutationId: string;
|
|
132
|
+
caller?: CanonicalGjcWorkflowSkill;
|
|
133
|
+
callee?: CanonicalGjcWorkflowSkill;
|
|
134
|
+
paths: string[];
|
|
135
|
+
}): Promise<string>;
|
|
136
|
+
export declare function updateWorkflowTransactionJournal(cwd: string, mutationId: string, patch: Partial<WorkflowTransactionJournal>): Promise<string>;
|
|
137
|
+
export declare function completeWorkflowTransactionJournal(cwd: string, mutationId: string): Promise<void>;
|