@gajae-code/coding-agent 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +26 -0
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/list-models.d.ts +6 -0
- package/dist/types/cli/setup-cli.d.ts +8 -1
- package/dist/types/commands/gc.d.ts +26 -0
- package/dist/types/commands/setup.d.ts +7 -0
- package/dist/types/config/file-lock-gc.d.ts +5 -0
- package/dist/types/config/file-lock.d.ts +29 -0
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +62 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/defaults/gjc/extensions/grok-build/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/index.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.d.ts +25 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.d.ts +27 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.d.ts +8 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.d.ts +5 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +10 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.d.ts +38 -0
- package/dist/types/defaults/gjc-grok-cli.d.ts +5 -0
- package/dist/types/extensibility/extensions/index.d.ts +1 -0
- package/dist/types/extensibility/extensions/prefix-command-bridge.d.ts +35 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +103 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +112 -0
- package/dist/types/gjc-runtime/gc-render.d.ts +6 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +134 -0
- package/dist/types/gjc-runtime/ledger-event-renderer.d.ts +68 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +64 -2
- package/dist/types/gjc-runtime/team-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +11 -0
- package/dist/types/gjc-runtime/tmux-gc.d.ts +7 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +10 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +29 -0
- package/dist/types/harness-control-plane/gc-adapter.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +7 -0
- package/dist/types/harness-control-plane/storage.d.ts +20 -0
- package/dist/types/modes/components/hook-selector.d.ts +7 -1
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +72 -2
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +13 -0
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +25 -0
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +10 -0
- package/dist/types/modes/theme/defaults/index.d.ts +302 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +39 -3
- package/dist/types/session/history-storage.d.ts +2 -2
- package/dist/types/session/session-manager.d.ts +10 -1
- package/dist/types/setup/credential-import.d.ts +79 -0
- package/dist/types/skill-state/workflow-hud.d.ts +14 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/render.d.ts +1 -1
- package/dist/types/tools/ask.d.ts +15 -1
- package/dist/types/tools/subagent-render.d.ts +7 -1
- package/dist/types/tools/subagent.d.ts +27 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +5 -0
- package/dist/types/web/search/index.d.ts +4 -4
- package/dist/types/web/search/provider.d.ts +16 -20
- package/dist/types/web/search/providers/base.d.ts +2 -1
- package/dist/types/web/search/providers/openai-compatible.d.ts +9 -0
- package/dist/types/web/search/types.d.ts +14 -2
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +52 -0
- package/src/cli/args.ts +5 -0
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/fast-help.ts +2 -0
- package/src/cli/list-models.ts +13 -1
- package/src/cli/setup-cli.ts +138 -3
- package/src/cli.ts +1 -0
- package/src/commands/gc.ts +22 -0
- package/src/commands/harness.ts +7 -3
- package/src/commands/setup.ts +5 -1
- package/src/commands/ultragoal.ts +3 -1
- package/src/config/file-lock-gc.ts +193 -0
- package/src/config/file-lock.ts +66 -10
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +39 -30
- package/src/config/model-registry.ts +21 -1
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +62 -0
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/server.ts +459 -3
- package/src/defaults/gjc/agent.models.grok-cli.yml +36 -0
- package/src/defaults/gjc/extensions/grok-build/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-build/package.json +7 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +39 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/package.json +8 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/index.ts +1 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +155 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/payload/sanitize.ts +361 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/billing.ts +57 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +99 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +50 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/usage.ts +56 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +36 -0
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/errors.ts +44 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +131 -113
- package/src/defaults/gjc/skills/deep-interview/lateral-review-panel.md +49 -0
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +30 -8
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/defaults/gjc-grok-cli.ts +22 -0
- package/src/extensibility/extensions/index.ts +1 -0
- package/src/extensibility/extensions/prefix-command-bridge.ts +128 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +457 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +18 -26
- package/src/gjc-runtime/deep-interview-state.ts +324 -0
- package/src/gjc-runtime/gc-render.ts +70 -0
- package/src/gjc-runtime/gc-runtime.ts +403 -0
- package/src/gjc-runtime/launch-tmux.ts +3 -4
- package/src/gjc-runtime/ledger-event-renderer.ts +164 -0
- package/src/gjc-runtime/ralplan-runtime.ts +232 -19
- package/src/gjc-runtime/state-renderer.ts +12 -3
- package/src/gjc-runtime/state-runtime.ts +48 -30
- package/src/gjc-runtime/state-writer.ts +254 -7
- package/src/gjc-runtime/team-gc.ts +49 -0
- package/src/gjc-runtime/team-runtime.ts +179 -2
- package/src/gjc-runtime/tmux-common.ts +14 -0
- package/src/gjc-runtime/tmux-gc.ts +177 -0
- package/src/gjc-runtime/tmux-sessions.ts +49 -1
- package/src/gjc-runtime/ultragoal-guard.ts +155 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +1239 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +44 -0
- package/src/gjc-runtime/workflow-manifest.ts +12 -0
- package/src/harness-control-plane/gc-adapter.ts +184 -0
- package/src/harness-control-plane/owner.ts +14 -2
- package/src/harness-control-plane/rpc-adapter.ts +1 -1
- package/src/harness-control-plane/storage.ts +70 -0
- package/src/hooks/skill-state.ts +121 -2
- package/src/internal-urls/docs-index.generated.ts +22 -12
- package/src/lsp/defaults.json +1 -0
- package/src/main.ts +18 -3
- package/src/modes/acp/acp-agent.ts +4 -2
- package/src/modes/bridge/bridge-mode.ts +2 -1
- package/src/modes/components/history-search.ts +5 -2
- package/src/modes/components/hook-selector.ts +19 -0
- package/src/modes/components/model-selector.ts +51 -8
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/controllers/command-controller.ts +25 -6
- package/src/modes/controllers/extension-ui-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +81 -1
- package/src/modes/interactive-mode.ts +11 -1
- package/src/modes/rpc/rpc-mode.ts +266 -34
- package/src/modes/shared/agent-wire/command-dispatch.ts +281 -261
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +30 -1
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +3 -0
- package/src/modes/shared/agent-wire/session-registry.ts +109 -0
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +24 -0
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +23 -3
- package/src/modes/shared/agent-wire/unattended-session.ts +32 -2
- package/src/modes/theme/defaults/claude-code.json +100 -0
- package/src/modes/theme/defaults/codex.json +100 -0
- package/src/modes/theme/defaults/index.ts +6 -0
- package/src/modes/theme/defaults/opencode.json +102 -0
- package/src/modes/theme/theme.ts +2 -2
- package/src/modes/types.ts +1 -1
- package/src/prompts/agents/executor.md +5 -2
- package/src/sdk.ts +29 -4
- package/src/session/agent-session.ts +99 -19
- package/src/session/blob-store.ts +59 -3
- package/src/session/history-storage.ts +32 -11
- package/src/session/session-manager.ts +72 -20
- package/src/setup/credential-import.ts +429 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +7 -1
- package/src/skill-state/deep-interview-mutation-guard.ts +2 -1
- package/src/skill-state/workflow-hud.ts +106 -10
- package/src/slash-commands/builtin-registry.ts +3 -2
- package/src/task/executor.ts +16 -1
- package/src/task/render.ts +18 -7
- package/src/tools/ask.ts +59 -2
- package/src/tools/cron.ts +1 -1
- package/src/tools/job.ts +3 -2
- package/src/tools/monitor.ts +36 -1
- package/src/tools/subagent-render.ts +128 -29
- package/src/tools/subagent.ts +173 -9
- package/src/tools/ultragoal-ask-guard.ts +39 -0
- package/src/web/search/index.ts +25 -25
- package/src/web/search/provider.ts +178 -87
- package/src/web/search/providers/base.ts +2 -1
- package/src/web/search/providers/openai-compatible.ts +151 -0
- package/src/web/search/types.ts +47 -22
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { type DeepInterviewEstablishedFact, type DeepInterviewRoundRecord, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
|
|
2
|
+
export * from "./deep-interview-state";
|
|
3
|
+
/**
|
|
4
|
+
* Runtime-owned deep-interview round recorder (conflict-aware scoring support).
|
|
5
|
+
*
|
|
6
|
+
* Ownership boundary (per the approved consensus plan): this module owns durable
|
|
7
|
+
* round-record semantics — stable identity, append-or-merge, lifecycle, compact
|
|
8
|
+
* reads, replay detection, and the pure scored-transition validator. Callers such
|
|
9
|
+
* as the `ask` tool only resolve an answer and invoke these helpers; they never
|
|
10
|
+
* compute state paths, merge records, or write `.gjc` files directly. All writes
|
|
11
|
+
* go through the sanctioned state-writer (`writeWorkflowEnvelopeAtomic`).
|
|
12
|
+
*/
|
|
13
|
+
export interface DeepInterviewAnswerInput {
|
|
14
|
+
interviewId?: string;
|
|
15
|
+
round: number;
|
|
16
|
+
round_id?: string;
|
|
17
|
+
questionId?: string;
|
|
18
|
+
questionText: string;
|
|
19
|
+
component?: string;
|
|
20
|
+
dimension?: string;
|
|
21
|
+
ambiguity?: number;
|
|
22
|
+
selectedOptions?: string[];
|
|
23
|
+
customInput?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface DeepInterviewScoringInput {
|
|
26
|
+
interviewId?: string;
|
|
27
|
+
round: number;
|
|
28
|
+
round_id?: string;
|
|
29
|
+
questionId?: string;
|
|
30
|
+
scores: Record<string, number>;
|
|
31
|
+
ambiguity: number;
|
|
32
|
+
triggers?: DeepInterviewTriggerMetadata[];
|
|
33
|
+
}
|
|
34
|
+
export type AppendOrMergeAction = "created" | "noop" | "replaced";
|
|
35
|
+
export interface AppendOrMergeResult {
|
|
36
|
+
rounds: DeepInterviewRoundRecord[];
|
|
37
|
+
action: AppendOrMergeAction;
|
|
38
|
+
record: DeepInterviewRoundRecord;
|
|
39
|
+
}
|
|
40
|
+
export interface DeepInterviewCompactState {
|
|
41
|
+
threshold?: number;
|
|
42
|
+
threshold_source?: string;
|
|
43
|
+
current_ambiguity?: number;
|
|
44
|
+
topology_summary?: {
|
|
45
|
+
active: number;
|
|
46
|
+
deferred: number;
|
|
47
|
+
components: string[];
|
|
48
|
+
};
|
|
49
|
+
established_facts: DeepInterviewEstablishedFact[];
|
|
50
|
+
unresolved_triggers: DeepInterviewTriggerMetadata[];
|
|
51
|
+
recent_scored_rounds: DeepInterviewRoundRecord[];
|
|
52
|
+
pending_shells: DeepInterviewRoundRecord[];
|
|
53
|
+
}
|
|
54
|
+
export interface TransitionValidationResult {
|
|
55
|
+
ok: boolean;
|
|
56
|
+
violations: string[];
|
|
57
|
+
}
|
|
58
|
+
export declare function buildAnswerShell(input: DeepInterviewAnswerInput, now?: string): DeepInterviewRoundRecord;
|
|
59
|
+
/**
|
|
60
|
+
* Append-or-merge by `round_key`. Exactly one record per key:
|
|
61
|
+
* - no existing record -> append (`created`);
|
|
62
|
+
* - identical question_hash + answer_hash -> deterministic no-op (`noop`);
|
|
63
|
+
* - same key, different hashes -> deterministic replacement of the prior shell
|
|
64
|
+
* (`replaced`); the prior answer for that key is superseded and lifecycle resets.
|
|
65
|
+
*/
|
|
66
|
+
export declare function appendOrMergeRound(rounds: readonly DeepInterviewRoundRecord[], shell: DeepInterviewRoundRecord): AppendOrMergeResult;
|
|
67
|
+
/**
|
|
68
|
+
* Merge scoring output into the existing record for the derived key, transitioning
|
|
69
|
+
* it to `scored`. Never appends a second record for the same key; if no shell exists
|
|
70
|
+
* yet (scoring without a prior ask), a scored record is created so data is not lost.
|
|
71
|
+
*/
|
|
72
|
+
export declare function enrichRoundWithScoring(rounds: readonly DeepInterviewRoundRecord[], input: DeepInterviewScoringInput, now?: string): {
|
|
73
|
+
rounds: DeepInterviewRoundRecord[];
|
|
74
|
+
record: DeepInterviewRoundRecord;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Bidirectional invariant: if `next` carries an `active` trigger, the affected
|
|
78
|
+
* dimension must not improve and overall ambiguity must rise vs the prior scored
|
|
79
|
+
* round. `disputed`/`unresolved` triggers are exempt but must carry a rationale.
|
|
80
|
+
*/
|
|
81
|
+
export declare function validateDeepInterviewScoredTransition(prior: DeepInterviewRoundRecord | undefined, next: DeepInterviewRoundRecord): TransitionValidationResult;
|
|
82
|
+
/** Back-compat wrapper: normalize a deep-interview envelope to its canonical nested shape. */
|
|
83
|
+
export declare function ensureDeepInterviewStateShape(value: unknown): DeepInterviewStateEnvelope;
|
|
84
|
+
export declare function projectCompactState(value: unknown, options?: {
|
|
85
|
+
lastN?: number;
|
|
86
|
+
}): DeepInterviewCompactState;
|
|
87
|
+
/** Record an `answered` shell for one round (append-or-merge by durable key). */
|
|
88
|
+
export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: {
|
|
89
|
+
sessionId?: string;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
action: AppendOrMergeAction;
|
|
92
|
+
record: DeepInterviewRoundRecord;
|
|
93
|
+
}>;
|
|
94
|
+
/** Merge scoring output into the same round record, transitioning to `scored`. */
|
|
95
|
+
export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: {
|
|
96
|
+
sessionId?: string;
|
|
97
|
+
}): Promise<{
|
|
98
|
+
record: DeepInterviewRoundRecord;
|
|
99
|
+
}>;
|
|
100
|
+
/** Compact projection so callers read a slice instead of the full transcript. */
|
|
101
|
+
export declare function readDeepInterviewStateCompact(statePath: string, options?: {
|
|
102
|
+
lastN?: number;
|
|
103
|
+
}): Promise<DeepInterviewCompactState>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from "./deep-interview-recorder";
|
|
1
2
|
/**
|
|
2
3
|
* Native implementation of `gjc deep-interview`.
|
|
3
4
|
*
|
|
@@ -12,6 +13,7 @@ export interface DeepInterviewCommandResult {
|
|
|
12
13
|
stdout?: string;
|
|
13
14
|
stderr?: string;
|
|
14
15
|
}
|
|
16
|
+
export declare function deepInterviewStatePath(cwd: string, sessionId: string | undefined): string;
|
|
15
17
|
export interface ResolvedDeepInterviewSpecWriteArgs {
|
|
16
18
|
stage: "final";
|
|
17
19
|
slug: string;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, dependency-free foundation for deep-interview state shape.
|
|
3
|
+
*
|
|
4
|
+
* Ownership boundary (per the approved consensus plan): this leaf module owns the
|
|
5
|
+
* canonical persisted shape (interview data nested under `state`), durable round
|
|
6
|
+
* identity/hashing, lossless legacy normalization, and the deep-interview-specific
|
|
7
|
+
* envelope/round merge used by every writer (`deep-interview-recorder`,
|
|
8
|
+
* `state-runtime` write/reconcile, seed, and handoff). It MUST NOT import the
|
|
9
|
+
* active-state, state-writer, CLI runtime, or filesystem so it stays cycle-free and
|
|
10
|
+
* trivially testable.
|
|
11
|
+
*/
|
|
12
|
+
export type DeepInterviewRoundLifecycle = "answered" | "pending_scoring" | "scored";
|
|
13
|
+
export type DeepInterviewTriggerKind = "A" | "B" | "C" | "D";
|
|
14
|
+
/** `active` triggers must satisfy the bidirectional invariant; disputed/unresolved are exempt with rationale. */
|
|
15
|
+
export type DeepInterviewTriggerStatus = "active" | "disputed" | "unresolved";
|
|
16
|
+
export interface DeepInterviewEstablishedFact {
|
|
17
|
+
id: string;
|
|
18
|
+
statement: string;
|
|
19
|
+
round: number;
|
|
20
|
+
component?: string;
|
|
21
|
+
dimension?: string;
|
|
22
|
+
evidence?: string;
|
|
23
|
+
disputed: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface DeepInterviewTriggerMetadata {
|
|
26
|
+
kind: DeepInterviewTriggerKind;
|
|
27
|
+
name: string;
|
|
28
|
+
status: DeepInterviewTriggerStatus;
|
|
29
|
+
component: string;
|
|
30
|
+
dimension: string;
|
|
31
|
+
priorDimensionScore?: number;
|
|
32
|
+
newDimensionScore?: number;
|
|
33
|
+
priorAmbiguity?: number;
|
|
34
|
+
newAmbiguity?: number;
|
|
35
|
+
evidence?: string;
|
|
36
|
+
contradictedFactId?: string;
|
|
37
|
+
/** Required when status is `disputed` or `unresolved` to exempt the invariant. */
|
|
38
|
+
rationale?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface DeepInterviewRoundRecord {
|
|
41
|
+
round_key: string;
|
|
42
|
+
round_id?: string;
|
|
43
|
+
round: number;
|
|
44
|
+
question_id?: string;
|
|
45
|
+
question_text?: string;
|
|
46
|
+
question_hash: string;
|
|
47
|
+
answer_hash: string;
|
|
48
|
+
selected_options?: string[];
|
|
49
|
+
custom_input?: string;
|
|
50
|
+
component?: string;
|
|
51
|
+
dimension?: string;
|
|
52
|
+
ambiguity_at_ask?: number;
|
|
53
|
+
lifecycle: DeepInterviewRoundLifecycle;
|
|
54
|
+
answered_at: string;
|
|
55
|
+
scored_at?: string;
|
|
56
|
+
scores?: Record<string, number>;
|
|
57
|
+
ambiguity?: number;
|
|
58
|
+
triggers?: DeepInterviewTriggerMetadata[];
|
|
59
|
+
}
|
|
60
|
+
export interface DeepInterviewStateEnvelope {
|
|
61
|
+
threshold?: number;
|
|
62
|
+
threshold_source?: string;
|
|
63
|
+
state?: Record<string, unknown>;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
export declare function hashContent(value: string): string;
|
|
67
|
+
export declare function questionHash(questionText: string): string;
|
|
68
|
+
export declare function answerHash(selectedOptions: string[] | undefined, customInput: string | undefined): string;
|
|
69
|
+
/**
|
|
70
|
+
* Durable round identity. Prefer `interview_id + round_id`; fall back to
|
|
71
|
+
* `interview_id + round + question.id` when no caller-supplied `round_id` exists.
|
|
72
|
+
*/
|
|
73
|
+
export declare function deriveRoundKey(interviewId: string | undefined, input: {
|
|
74
|
+
round_id?: string;
|
|
75
|
+
round: number;
|
|
76
|
+
questionId?: string;
|
|
77
|
+
}): string;
|
|
78
|
+
/**
|
|
79
|
+
* Canonicalize a deep-interview envelope: interview data nested under `state`,
|
|
80
|
+
* legacy flattened fields hoisted in losslessly, transcript duplicates removed
|
|
81
|
+
* from the top level, and `rounds`/`established_facts` guaranteed to be arrays.
|
|
82
|
+
*
|
|
83
|
+
* Idempotent: a canonical envelope is returned unchanged in shape. Never deletes
|
|
84
|
+
* unknown envelope or nested fields, and never mutates the input.
|
|
85
|
+
*/
|
|
86
|
+
export declare function normalizeDeepInterviewEnvelope(value: unknown): DeepInterviewStateEnvelope;
|
|
87
|
+
/**
|
|
88
|
+
* Lossless, idempotent merge of two round arrays.
|
|
89
|
+
*
|
|
90
|
+
* - Records sharing a durable key (`round_key`, or synthesized from
|
|
91
|
+
* `round_id`/`question_id`) merge into one, preferring scored over answered.
|
|
92
|
+
* - Records without any durable identity are preserved verbatim; an exact
|
|
93
|
+
* duplicate is skipped so repeated writes stay idempotent, but distinct records
|
|
94
|
+
* are never collapsed.
|
|
95
|
+
*
|
|
96
|
+
* Deliberate refinement of the approved plan: rather than mutating opaque legacy
|
|
97
|
+
* records with synthetic `legacy:<index>` keys, they are preserved verbatim with
|
|
98
|
+
* exact-duplicate dedupe. This satisfies the plan's intent (lossless, idempotent,
|
|
99
|
+
* never collapse distinct rounds) without rewriting user-supplied round objects,
|
|
100
|
+
* and keeps free-form extension preservation intact. Recorder-produced records
|
|
101
|
+
* always carry a `round_key`, so the synthetic path is unnecessary in practice.
|
|
102
|
+
*/
|
|
103
|
+
export declare function mergeDeepInterviewRounds(existing: readonly Record<string, unknown>[], incoming: readonly Record<string, unknown>[]): Record<string, unknown>[];
|
|
104
|
+
/**
|
|
105
|
+
* Deep-interview-specific envelope merge. Unlike the generic shallow null-delete
|
|
106
|
+
* merge, this keeps interview data nested under `state`, never deletes `state`,
|
|
107
|
+
* and merges `rounds` losslessly by durable key so a partial write (e.g. a
|
|
108
|
+
* scoring update) cannot drop recorder-written transcript history.
|
|
109
|
+
*/
|
|
110
|
+
export declare function mergeDeepInterviewEnvelope(existing: unknown, incoming: unknown, options?: {
|
|
111
|
+
replace?: boolean;
|
|
112
|
+
}): DeepInterviewStateEnvelope;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text rendering for `gjc gc` reports. JSON output is produced directly in
|
|
3
|
+
* `gc-runtime.ts`; this module owns the human-readable grouped report.
|
|
4
|
+
*/
|
|
5
|
+
import type { GcReport } from "./gc-runtime";
|
|
6
|
+
export declare function buildGcReportText(report: GcReport): string;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `gjc gc` runtime — a global, liveness-only, dry-run-by-default garbage
|
|
3
|
+
* collector for stale GJC session/PID records.
|
|
4
|
+
*
|
|
5
|
+
* Design (see .gjc/plans/ralplan/2026-06-13-1347-954f/pending-approval.md):
|
|
6
|
+
* - This module is an ORCHESTRATOR only. It owns the shared PID probe, the
|
|
7
|
+
* report/exit-code policy, and text/JSON rendering. It must NOT parse private
|
|
8
|
+
* store layouts directly; every store is reached through an injectable
|
|
9
|
+
* `GcStoreAdapter` that lives next to its store owner.
|
|
10
|
+
* - Liveness-only and fail-closed: only `ESRCH` (no such process) is `dead`
|
|
11
|
+
* (removable). `process.kill(pid, 0)` success, `EPERM`, and any unknown probe
|
|
12
|
+
* error all mean KEEP — a live process is never signalled or killed.
|
|
13
|
+
* - Dry-run by default: nothing is deleted unless `--prune`/`--force`.
|
|
14
|
+
*/
|
|
15
|
+
export type GcStore = "harness_leases" | "team_workers" | "file_locks" | "tmux_sessions" | "registry_entries";
|
|
16
|
+
export declare const GC_STORES: readonly GcStore[];
|
|
17
|
+
/** Why a probed pid is kept instead of treated as dead. */
|
|
18
|
+
export type GcPidKeepReason = "alive" | "eperm" | "unknown";
|
|
19
|
+
export interface GcPidProbeResult {
|
|
20
|
+
/** `dead` only on ESRCH; `keep` for alive/eperm/unknown (fail-closed). */
|
|
21
|
+
status: "dead" | "keep";
|
|
22
|
+
reason?: GcPidKeepReason;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Single shared liveness contract threaded through every classifier + prune path. */
|
|
26
|
+
export type GcPidProbe = (pid: number) => GcPidProbeResult;
|
|
27
|
+
export type GcPidStatus = "dead" | "alive" | "eperm" | "unknown" | "none";
|
|
28
|
+
export type GcAction = "none" | "would_remove" | "removed" | "remove_failed" | "skipped";
|
|
29
|
+
export interface GcRecord {
|
|
30
|
+
store: GcStore;
|
|
31
|
+
/** Stable identifier: session id, lock dir path, worker id, tmux name, registry session id. */
|
|
32
|
+
id: string;
|
|
33
|
+
path?: string;
|
|
34
|
+
root?: string;
|
|
35
|
+
pid?: number;
|
|
36
|
+
pid_status?: GcPidStatus;
|
|
37
|
+
/** Store-specific classification label (e.g. "dead", "live", "unclassified", "terminal_lifecycle"). */
|
|
38
|
+
status: string;
|
|
39
|
+
stale: boolean;
|
|
40
|
+
removable: boolean;
|
|
41
|
+
action: GcAction;
|
|
42
|
+
reason: string;
|
|
43
|
+
detail?: string;
|
|
44
|
+
error?: string;
|
|
45
|
+
removed?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface GcError {
|
|
48
|
+
store: GcStore;
|
|
49
|
+
scope: string;
|
|
50
|
+
message: string;
|
|
51
|
+
}
|
|
52
|
+
export interface GcCollectResult {
|
|
53
|
+
records: GcRecord[];
|
|
54
|
+
errors: GcError[];
|
|
55
|
+
}
|
|
56
|
+
export interface GcPruneOutcome {
|
|
57
|
+
removed: boolean;
|
|
58
|
+
error?: string;
|
|
59
|
+
/** Set when a removable record was skipped at prune time (e.g. TOCTOU became live). */
|
|
60
|
+
skipped?: string;
|
|
61
|
+
}
|
|
62
|
+
export interface GcContext {
|
|
63
|
+
probe: GcPidProbe;
|
|
64
|
+
force: boolean;
|
|
65
|
+
env: NodeJS.ProcessEnv;
|
|
66
|
+
cwd: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A store-owned GC adapter. `collect` discovers + classifies (using the shared
|
|
70
|
+
* probe) without mutating anything. `prune` removes a single record, and MUST
|
|
71
|
+
* re-validate / re-probe immediately before any destructive action.
|
|
72
|
+
*/
|
|
73
|
+
export interface GcStoreAdapter {
|
|
74
|
+
store: GcStore;
|
|
75
|
+
collect(ctx: GcContext): Promise<GcCollectResult>;
|
|
76
|
+
prune(record: GcRecord, ctx: GcContext): Promise<GcPruneOutcome>;
|
|
77
|
+
}
|
|
78
|
+
export interface GcCounts {
|
|
79
|
+
discovered: number;
|
|
80
|
+
stale: number;
|
|
81
|
+
alive: number;
|
|
82
|
+
eperm: number;
|
|
83
|
+
unknown: number;
|
|
84
|
+
terminal_lifecycle: number;
|
|
85
|
+
unclassified: number;
|
|
86
|
+
would_remove: number;
|
|
87
|
+
removed: number;
|
|
88
|
+
failed: number;
|
|
89
|
+
errors: number;
|
|
90
|
+
by_store: Record<GcStore, {
|
|
91
|
+
discovered: number;
|
|
92
|
+
stale: number;
|
|
93
|
+
would_remove: number;
|
|
94
|
+
removed: number;
|
|
95
|
+
failed: number;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
export interface GcReport {
|
|
99
|
+
dry_run: boolean;
|
|
100
|
+
stores: Record<GcStore, GcRecord[]>;
|
|
101
|
+
counts: GcCounts;
|
|
102
|
+
errors: GcError[];
|
|
103
|
+
}
|
|
104
|
+
export interface GcRunResult {
|
|
105
|
+
stdout: string;
|
|
106
|
+
stderr: string;
|
|
107
|
+
status: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The shared, fail-closed PID probe. ESRCH => dead/removable; success => alive;
|
|
111
|
+
* EPERM => kept (owned by another user); any other error => kept as unknown.
|
|
112
|
+
*/
|
|
113
|
+
export declare const gcPidProbe: GcPidProbe;
|
|
114
|
+
/** Map a `GcPidProbe` onto the harness lease probe shape (`"alive"|"dead"|"eperm"`). */
|
|
115
|
+
export declare function gcProbeToLeasePidStatus(probe: GcPidProbe): (pid: number) => "alive" | "dead" | "eperm";
|
|
116
|
+
/** Translate a probe result into a record-friendly pid status label. */
|
|
117
|
+
export declare function gcPidStatusLabel(result: GcPidProbeResult): Exclude<GcPidStatus, "none">;
|
|
118
|
+
/**
|
|
119
|
+
* Collect every store's records (catching hard discovery errors per adapter),
|
|
120
|
+
* then optionally prune removable records with per-record revalidation.
|
|
121
|
+
*/
|
|
122
|
+
export declare function collectGcReport(adapters: GcStoreAdapter[], ctx: GcContext, prune: boolean): Promise<GcReport>;
|
|
123
|
+
/**
|
|
124
|
+
* Exit-code policy:
|
|
125
|
+
* - usage/parse error => 2
|
|
126
|
+
* - hard discovery errors => 1 (both modes)
|
|
127
|
+
* - prune mode with a failed intended removal => 1
|
|
128
|
+
* - otherwise => 0
|
|
129
|
+
*/
|
|
130
|
+
export declare function computeExitCode(report: GcReport): number;
|
|
131
|
+
export declare function runGjcGcCommand(argv: string[], cwd?: string, env?: NodeJS.ProcessEnv, adapters?: GcStoreAdapter[]): Promise<GcRunResult>;
|
|
132
|
+
export declare function gcHelpText(): string;
|
|
133
|
+
/** Lazily assemble the real store adapters (kept lazy to avoid import cycles). */
|
|
134
|
+
export declare function defaultGcAdapters(): Promise<GcStoreAdapter[]>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure parse + summarize for ledger-backed skill observability.
|
|
3
|
+
*
|
|
4
|
+
* Workflow progress for ultragoal/ralplan cannot be observed via subagent tool
|
|
5
|
+
* events (those skills persist through `bash`-backed `gjc` CLI calls whose tool
|
|
6
|
+
* `details` carry no structured payload). The durable source of truth is the
|
|
7
|
+
* append-only ledgers:
|
|
8
|
+
* - ultragoal: `.gjc/ultragoal/ledger.jsonl`
|
|
9
|
+
* - ralplan: `.gjc/plans/ralplan/<run-id>/index.jsonl`
|
|
10
|
+
*
|
|
11
|
+
* This module is I/O-free: callers read the files and pass lines or already-parsed
|
|
12
|
+
* rows. It feeds the compact HUD chip builders in `skill-state/workflow-hud.ts`
|
|
13
|
+
* via the runtime sync paths. Display-string helpers stay theme-free.
|
|
14
|
+
*/
|
|
15
|
+
/** Minimal projection of an ultragoal ledger row used for the HUD chip. */
|
|
16
|
+
export interface UltragoalLedgerEventLite {
|
|
17
|
+
/** Normalized from the row's `event` field, or `type` for reconcile rows. */
|
|
18
|
+
event: string;
|
|
19
|
+
goalId?: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
timestamp?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Coerce an already-parsed ledger row into the lite shape. Accepts both the
|
|
25
|
+
* `event`-keyed vocabulary (plan_created, goal_started, goal_checkpointed,
|
|
26
|
+
* steering_accepted/rejected, review_blockers_recorded) and the `type`-keyed
|
|
27
|
+
* reconcile-failure row (`type: "reconcile_failed"`). Returns undefined when no
|
|
28
|
+
* event/type discriminator is present.
|
|
29
|
+
*/
|
|
30
|
+
export declare function coerceUltragoalLedgerEvent(row: Record<string, unknown>): UltragoalLedgerEventLite | undefined;
|
|
31
|
+
/** Parse a single ultragoal ledger JSONL line; undefined for blank/malformed lines. */
|
|
32
|
+
export declare function parseUltragoalLedgerLine(line: string): UltragoalLedgerEventLite | undefined;
|
|
33
|
+
/** The most recent event, or undefined when the ledger is empty. */
|
|
34
|
+
export declare function latestUltragoalLedgerEvent(events: readonly UltragoalLedgerEventLite[]): UltragoalLedgerEventLite | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Best-effort latest event from raw ledger text: parses line-by-line and skips
|
|
37
|
+
* blank/malformed rows so a torn or hand-edited ledger never throws on the HUD
|
|
38
|
+
* path. Strict receipt consumers should keep using the validating reader.
|
|
39
|
+
*/
|
|
40
|
+
export declare function latestUltragoalLedgerEventFromText(text: string): UltragoalLedgerEventLite | undefined;
|
|
41
|
+
/** Minimal projection of a ralplan `index.jsonl` row. */
|
|
42
|
+
export interface RalplanIndexRow {
|
|
43
|
+
stage: string;
|
|
44
|
+
stageN?: number;
|
|
45
|
+
}
|
|
46
|
+
/** Parse a single ralplan index JSONL line; undefined for blank/malformed lines. */
|
|
47
|
+
export declare function parseRalplanIndexLine(line: string): RalplanIndexRow | undefined;
|
|
48
|
+
export interface RalplanIndexSummary {
|
|
49
|
+
/** Number of consensus iterations (planner/revision boundaries), >= 0. */
|
|
50
|
+
iteration: number;
|
|
51
|
+
/** Stage names present in the current (latest) iteration, in append order. */
|
|
52
|
+
currentStages: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Derive iteration count and current-iteration stage presence from index rows.
|
|
56
|
+
*
|
|
57
|
+
* `stage_n` is NOT used as the iteration key: it is stored verbatim per row and a
|
|
58
|
+
* single planner/architect/critic pass can span multiple stage_n values. Instead,
|
|
59
|
+
* a `planner` or `revision` row opens a new iteration and subsequent rows attach
|
|
60
|
+
* to it. No verdict is derived here (index rows carry none).
|
|
61
|
+
*/
|
|
62
|
+
export declare function summarizeRalplanIndex(rows: readonly RalplanIndexRow[]): RalplanIndexSummary;
|
|
63
|
+
/**
|
|
64
|
+
* Compact, theme-free presence string for the ralplan `stages` chip, e.g.
|
|
65
|
+
* `P·A·C`. Collapses past `cap` with a "… N more" suffix. Returns undefined when
|
|
66
|
+
* there are no stages.
|
|
67
|
+
*/
|
|
68
|
+
export declare function formatRalplanStagePresence(stages: readonly string[], cap?: number): string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Stats } from "node:fs";
|
|
2
|
+
import { type FileLockOptions } from "../config/file-lock";
|
|
2
3
|
import type { SkillActiveEntry } from "../skill-state/active-state";
|
|
3
4
|
import { type AuditEntry, type CanonicalGjcWorkflowSkill, type WorkflowStateMutationOwner } from "../skill-state/workflow-state-contract";
|
|
4
5
|
/**
|
|
@@ -55,6 +56,12 @@ export interface StateWriterOptions {
|
|
|
55
56
|
cwd?: string;
|
|
56
57
|
receipt?: StateWriterReceiptContext;
|
|
57
58
|
audit?: StateWriterAuditContext;
|
|
59
|
+
/**
|
|
60
|
+
* Cross-process lock tuning for read-modify-write paths that route through
|
|
61
|
+
* `withWorkflowStateLock` / `updateJsonAtomic`. Omit for the hardened
|
|
62
|
+
* `withFileLock` defaults.
|
|
63
|
+
*/
|
|
64
|
+
lock?: FileLockOptions;
|
|
58
65
|
}
|
|
59
66
|
export interface DeleteIfOwnedOptions extends StateWriterOptions {
|
|
60
67
|
predicate?: (current: unknown) => boolean | Promise<boolean>;
|
|
@@ -81,7 +88,7 @@ export interface GenericHardPruneTarget {
|
|
|
81
88
|
export interface GenericHardPruneSelectorContext {
|
|
82
89
|
path: string;
|
|
83
90
|
category: WriterCategory | string;
|
|
84
|
-
stat:
|
|
91
|
+
stat: Stats;
|
|
85
92
|
readJson: () => Promise<unknown>;
|
|
86
93
|
}
|
|
87
94
|
export type GenericHardPruneSelector = (context: GenericHardPruneSelectorContext) => boolean | Promise<boolean>;
|
|
@@ -109,8 +116,63 @@ export declare function detectWorkflowEnvelopeIntegrityMismatch(filePath: string
|
|
|
109
116
|
export declare function writeJsonAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
110
117
|
export declare function writeWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
111
118
|
export declare function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
|
|
119
|
+
/**
|
|
120
|
+
* Serialize a read-modify-write (or any multi-step mutation) against concurrent
|
|
121
|
+
* writers of the same `.gjc/**` target. Uses the cross-process directory lock
|
|
122
|
+
* from `withFileLock`, keyed on the resolved file path, so separate CLI/agent
|
|
123
|
+
* processes (e.g. team-mode workers) cannot interleave one writer's read with
|
|
124
|
+
* another writer's write and silently drop the first mutation (issue #646).
|
|
125
|
+
*
|
|
126
|
+
* The lock is advisory: it only protects callers that route through it, so every
|
|
127
|
+
* read-modify-write of a given file MUST acquire this lock for the same resolved
|
|
128
|
+
* path. `atomicWrite`'s temp-file + rename crash-atomicity is preserved; this
|
|
129
|
+
* layers concurrency-atomicity on top without weakening it.
|
|
130
|
+
*/
|
|
131
|
+
export declare function withWorkflowStateLock<T>(targetPath: string, fn: () => Promise<T>, options?: StateWriterOptions): Promise<T>;
|
|
112
132
|
export declare function updateJsonAtomic<T = unknown>(targetPath: string, mutator: (current: T | undefined) => T | Promise<T>, options?: StateWriterOptions): Promise<string>;
|
|
113
133
|
export declare function appendJsonl(targetPath: string, entry: unknown, options?: StateWriterOptions): Promise<string>;
|
|
134
|
+
export interface AppendJsonlIdempotentOptions extends StateWriterOptions {
|
|
135
|
+
/**
|
|
136
|
+
* Identity key for an entry. Two entries that produce the same non-`undefined`
|
|
137
|
+
* key are duplicates, so only the first is appended. Return `undefined` to opt a
|
|
138
|
+
* candidate out of dedup (it is always appended). Use `key` for the common case
|
|
139
|
+
* where identity reduces to a single string.
|
|
140
|
+
*/
|
|
141
|
+
key?: (entry: unknown) => string | undefined;
|
|
142
|
+
/**
|
|
143
|
+
* Equivalence predicate: return `true` when `existing` already represents
|
|
144
|
+
* `candidate`, suppressing the append. Use when identity cannot be reduced to a
|
|
145
|
+
* single string key. When both `key` and `equals` are supplied, `equals` wins.
|
|
146
|
+
*/
|
|
147
|
+
equals?: (candidate: unknown, existing: unknown) => boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface AppendJsonlIdempotentResult {
|
|
150
|
+
path: string;
|
|
151
|
+
/** `true` when the entry was written; `false` when an equivalent entry already existed. */
|
|
152
|
+
appended: boolean;
|
|
153
|
+
/** The pre-existing entry that suppressed the append, when `appended` is `false`. */
|
|
154
|
+
duplicate?: unknown;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Append `entry` to a JSONL file only when no equivalent entry already exists —
|
|
158
|
+
* the shared idempotent append primitive (issue #660).
|
|
159
|
+
*
|
|
160
|
+
* `appendJsonl` is a pure append with no dedup, so every recurring "duplicate
|
|
161
|
+
* ledger row" bug (#638, #643, #645) had to be patched with bespoke per-call-site
|
|
162
|
+
* guards. This primitive centralizes the read-check-append cycle: a caller
|
|
163
|
+
* declares identity once via `key` or `equals` instead of re-deriving the lookup
|
|
164
|
+
* at each site.
|
|
165
|
+
*
|
|
166
|
+
* The read-then-append is serialized through the same cross-process workflow lock
|
|
167
|
+
* as `updateJsonAtomic`, so two concurrent idempotent appends cannot both observe
|
|
168
|
+
* "no duplicate" and both write (the #646 TOCTOU that a plain `appendJsonl`
|
|
169
|
+
* preceded by a manual existence check is still exposed to).
|
|
170
|
+
*
|
|
171
|
+
* Scope note: this dedups the *append* only. Call sites whose idempotency must
|
|
172
|
+
* also skip a coupled mutation — e.g. the plan/state rewrite in #643/#645 — still
|
|
173
|
+
* need a whole-operation guard; this primitive is the ledger-level half of that.
|
|
174
|
+
*/
|
|
175
|
+
export declare function appendJsonlIdempotent(targetPath: string, entry: unknown, options: AppendJsonlIdempotentOptions): Promise<AppendJsonlIdempotentResult>;
|
|
114
176
|
export declare function appendText(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
|
|
115
177
|
export declare function createJsonNoClobber(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
|
|
116
178
|
export declare function deleteIfOwned(targetPath: string, predicateOrOptions?: ((current: unknown) => boolean | Promise<boolean>) | DeleteIfOwnedOptions): Promise<DeleteResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GC adapter for team workers (`.gjc/state/team/<name>/workers/<id>/` heartbeat
|
|
3
|
+
* + lifecycle). Liveness-only: numeric PID status dominates lifecycle/heartbeat
|
|
4
|
+
* signals.
|
|
5
|
+
*/
|
|
6
|
+
import type { GcStoreAdapter } from "./gc-runtime";
|
|
7
|
+
export declare const teamWorkersGcAdapter: GcStoreAdapter;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WorkflowHudSummary } from "../skill-state/active-state";
|
|
2
|
+
import type { GcPidProbe, GcRecord } from "./gc-runtime";
|
|
2
3
|
export type GjcTeamPhase = "starting" | "running" | "awaiting_integration" | "complete" | "failed" | "cancelled";
|
|
3
4
|
export type GjcTeamTaskStatus = "pending" | "blocked" | "in_progress" | "completed" | "failed";
|
|
4
5
|
export type GjcWorkerStatusState = "idle" | "working" | "blocked" | "done" | "failed" | "draining" | "unknown";
|
|
@@ -272,6 +273,10 @@ export interface GjcWorkerIntegrationAttemptRequestResult {
|
|
|
272
273
|
}
|
|
273
274
|
export declare const GJC_TEAM_API_OPERATIONS: readonly ["send-message", "broadcast", "mailbox-list", "mailbox-mark-delivered", "mailbox-mark-notified", "notification-list", "notification-read", "notification-replay", "notification-mark-pane-attempt", "worker-startup-ack", "create-task", "read-task", "list-tasks", "update-task", "claim-task", "transition-task-status", "transition-task", "release-task-claim", "read-config", "read-manifest", "read-worker-status", "update-worker-status", "read-worker-heartbeat", "recover-stale-claims", "update-worker-heartbeat", "write-worker-inbox", "write-worker-identity", "append-event", "read-events", "read-traces", "await-event", "write-shutdown-request", "read-shutdown-ack", "read-monitor-snapshot", "write-monitor-snapshot", "read-task-approval", "write-task-approval"];
|
|
274
275
|
export declare function resolveGjcTeamStateRoot(cwd?: string, env?: NodeJS.ProcessEnv): string;
|
|
276
|
+
/** @internal */
|
|
277
|
+
export declare function listTeamWorkerGcRecords(teamRoot: string, probe: GcPidProbe): Promise<GcRecord[]>;
|
|
278
|
+
/** @internal */
|
|
279
|
+
export declare function pruneTeamWorkerGcRecord(record: GcRecord, probe: GcPidProbe): Promise<boolean>;
|
|
275
280
|
export declare function persistGjcTeamModeStateSummary(snapshot: GjcTeamSnapshot, cwd?: string): Promise<void>;
|
|
276
281
|
export declare function recoverGjcTeamStaleClaims(teamName: string, cwd?: string, env?: NodeJS.ProcessEnv): Promise<GjcTeamLivenessRecoveryResult>;
|
|
277
282
|
type GjcTeamTaskMetadataInput = Partial<Pick<GjcTeamTask, "owner" | "lane" | "required_role" | "allowed_roles" | "depends_on" | "blocked_by">>;
|
|
@@ -21,6 +21,17 @@ export interface TmuxCommandResult {
|
|
|
21
21
|
export type TmuxCommandRunner = (args: string[]) => TmuxCommandResult;
|
|
22
22
|
export declare function envDisabled(value: string | undefined): boolean;
|
|
23
23
|
export declare function resolveGjcTmuxCommand(env?: NodeJS.ProcessEnv): string;
|
|
24
|
+
/**
|
|
25
|
+
* Build the exact-session target for tmux *option* commands
|
|
26
|
+
* (`show-options` / `set-option`) and `display-message -t`.
|
|
27
|
+
*
|
|
28
|
+
* Session-scoped commands such as `kill-session` / `attach-session` resolve a
|
|
29
|
+
* bare exact target (`=NAME`), but tmux 3.6a refuses to resolve a bare `=NAME`
|
|
30
|
+
* for option/display commands. Appending the empty window separator (`=NAME:`)
|
|
31
|
+
* keeps the exact-session match while giving tmux the window-qualified target
|
|
32
|
+
* those commands require. See gajae-code#580.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildGjcTmuxExactOptionTarget(sessionName: string): string;
|
|
24
35
|
export declare const GJC_TMUX_UNTAGGED_REASON = "gjc_tmux_session_untagged";
|
|
25
36
|
export declare function buildGjcTmuxUntaggedSessionHint(tmuxCommand: string): string;
|
|
26
37
|
export declare function buildGjcTmuxUntaggedSessionError(sessionName: string, tmuxCommand: string): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GC adapter for gjc-tagged tmux sessions. Stale iff `@gjc-project` path is gone
|
|
3
|
+
* OR `@gjc-branch` has no live git worktree. Removal is a spec-authorized
|
|
4
|
+
* destructive `kill-session`, gated by exact-target re-read + revalidation.
|
|
5
|
+
*/
|
|
6
|
+
import type { GcStoreAdapter } from "./gc-runtime";
|
|
7
|
+
export declare const tmuxSessionsGcAdapter: GcStoreAdapter;
|
|
@@ -9,9 +9,22 @@ export interface GjcTmuxSessionStatus {
|
|
|
9
9
|
branchSlug?: string;
|
|
10
10
|
project?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface GjcTmuxSessionTagsForGc {
|
|
13
|
+
profile?: string;
|
|
14
|
+
project?: string;
|
|
15
|
+
branch?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface GjcTmuxSessionsForGc {
|
|
18
|
+
tagged: GjcTmuxSessionStatus[];
|
|
19
|
+
untagged: string[];
|
|
20
|
+
}
|
|
12
21
|
export declare function listGjcTmuxSessions(env?: NodeJS.ProcessEnv): GjcTmuxSessionStatus[];
|
|
22
|
+
/** @internal */
|
|
23
|
+
export declare function listTmuxSessionsForGc(env?: NodeJS.ProcessEnv): GjcTmuxSessionsForGc;
|
|
13
24
|
export declare function findGjcTmuxSessionByBranch(branch: string, env?: NodeJS.ProcessEnv, project?: string | null): GjcTmuxSessionStatus | undefined;
|
|
14
25
|
export declare function statusGjcTmuxSession(sessionName: string, env?: NodeJS.ProcessEnv): GjcTmuxSessionStatus;
|
|
15
26
|
export declare function createGjcTmuxSession(env?: NodeJS.ProcessEnv): GjcTmuxSessionStatus;
|
|
27
|
+
/** @internal */
|
|
28
|
+
export declare function readTmuxSessionTagsForGc(sessionName: string, env?: NodeJS.ProcessEnv): GjcTmuxSessionTagsForGc;
|
|
16
29
|
export declare function removeGjcTmuxSession(sessionName: string, env?: NodeJS.ProcessEnv): GjcTmuxSessionStatus;
|
|
17
30
|
export declare function attachGjcTmuxSession(sessionName: string, env?: NodeJS.ProcessEnv): never;
|
|
@@ -5,6 +5,15 @@ export interface UltragoalGuardDiagnostic {
|
|
|
5
5
|
message: string;
|
|
6
6
|
goalId?: string;
|
|
7
7
|
}
|
|
8
|
+
export interface UltragoalAskBlockDiagnostic {
|
|
9
|
+
active: boolean;
|
|
10
|
+
reason: string;
|
|
11
|
+
source: "absent" | "durable_state" | "durable_state_unreadable" | "ledger" | "goals_json";
|
|
12
|
+
goalsPath?: string;
|
|
13
|
+
ledgerPath?: string;
|
|
14
|
+
goalIds?: string[];
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
8
17
|
export interface CurrentGoalLike {
|
|
9
18
|
objective: string;
|
|
10
19
|
status?: string;
|
|
@@ -19,6 +28,7 @@ export declare function readUltragoalVerificationState(input: {
|
|
|
19
28
|
cwd: string;
|
|
20
29
|
currentGoal?: CurrentGoalLike | null;
|
|
21
30
|
}): Promise<UltragoalGuardDiagnostic>;
|
|
31
|
+
export declare function isUltragoalAskBlocked(cwd: string): Promise<UltragoalAskBlockDiagnostic>;
|
|
22
32
|
export declare function assertCanCompleteCurrentGoal(input: {
|
|
23
33
|
cwd: string;
|
|
24
34
|
currentGoal?: CurrentGoalLike | null;
|