@gajae-code/coding-agent 0.3.2 → 0.4.1
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 +39 -0
- package/dist/types/config/model-registry.d.ts +17 -10
- package/dist/types/config/models-config-schema.d.ts +37 -0
- package/dist/types/config/settings-schema.d.ts +5 -0
- package/dist/types/edit/diff.d.ts +16 -0
- package/dist/types/edit/modes/replace.d.ts +7 -0
- package/dist/types/extensibility/gjc-plugins/activation.d.ts +14 -0
- package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/injection.d.ts +31 -0
- package/dist/types/extensibility/gjc-plugins/loader.d.ts +3 -0
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +8 -0
- package/dist/types/extensibility/gjc-plugins/schema.d.ts +3 -0
- package/dist/types/extensibility/gjc-plugins/state.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/tools.d.ts +8 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +64 -0
- package/dist/types/extensibility/gjc-plugins/validation.d.ts +4 -0
- package/dist/types/extensibility/skills.d.ts +9 -1
- package/dist/types/gjc-runtime/state-runtime.d.ts +22 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -2
- package/dist/types/harness-control-plane/storage.d.ts +7 -0
- package/dist/types/lsp/client.d.ts +1 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +2 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-client.d.ts +19 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +179 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +57 -0
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +16 -1
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +47 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +7 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +3 -1
- package/dist/types/modes/shared/agent-wire/responses.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +27 -0
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +68 -0
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +161 -0
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +61 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +114 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +39 -0
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
- package/dist/types/sdk.d.ts +7 -0
- package/dist/types/session/agent-session.d.ts +10 -0
- package/dist/types/session/blob-store.d.ts +17 -0
- package/dist/types/session/messages.d.ts +3 -0
- package/dist/types/session/session-storage.d.ts +6 -0
- package/dist/types/skill-state/active-state.d.ts +13 -0
- package/dist/types/thinking.d.ts +3 -2
- package/dist/types/tools/index.d.ts +3 -0
- package/package.json +9 -7
- package/src/cli.ts +14 -0
- package/src/commands/harness.ts +192 -7
- package/src/commands/ultragoal.ts +1 -21
- package/src/config/model-equivalence.ts +1 -1
- package/src/config/model-registry.ts +32 -5
- package/src/config/models-config-schema.ts +7 -2
- package/src/config/settings-schema.ts +4 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +19 -23
- package/src/defaults/gjc/skills/ralplan/SKILL.md +7 -7
- package/src/discovery/claude-plugins.ts +25 -5
- package/src/edit/diff.ts +64 -1
- package/src/edit/modes/replace.ts +60 -2
- package/src/extensibility/gjc-plugins/activation.ts +87 -0
- package/src/extensibility/gjc-plugins/index.ts +9 -0
- package/src/extensibility/gjc-plugins/injection.ts +114 -0
- package/src/extensibility/gjc-plugins/loader.ts +131 -0
- package/src/extensibility/gjc-plugins/paths.ts +66 -0
- package/src/extensibility/gjc-plugins/schema.ts +79 -0
- package/src/extensibility/gjc-plugins/state.ts +29 -0
- package/src/extensibility/gjc-plugins/tools.ts +47 -0
- package/src/extensibility/gjc-plugins/types.ts +97 -0
- package/src/extensibility/gjc-plugins/validation.ts +76 -0
- package/src/extensibility/skills.ts +39 -7
- package/src/gjc-runtime/state-runtime.ts +93 -2
- package/src/gjc-runtime/state-writer.ts +17 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +76 -121
- package/src/gjc-runtime/workflow-manifest.generated.json +5 -0
- package/src/gjc-runtime/workflow-manifest.ts +2 -2
- package/src/harness-control-plane/storage.ts +144 -2
- package/src/hashline/hash.ts +23 -0
- package/src/hooks/skill-state.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +5 -5
- package/src/lsp/client.ts +7 -0
- package/src/modes/acp/acp-agent.ts +25 -2
- package/src/modes/bridge/bridge-mode.ts +124 -2
- package/src/modes/controllers/input-controller.ts +14 -2
- package/src/modes/prompt-action-autocomplete.ts +49 -10
- package/src/modes/rpc/rpc-client.ts +79 -3
- package/src/modes/rpc/rpc-mode.ts +67 -0
- package/src/modes/rpc/rpc-types.ts +224 -2
- package/src/modes/shared/agent-wire/approval-gate.ts +151 -0
- package/src/modes/shared/agent-wire/command-dispatch.ts +97 -4
- package/src/modes/shared/agent-wire/command-validation.ts +25 -1
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +222 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +13 -0
- package/src/modes/shared/agent-wire/handshake.ts +43 -3
- package/src/modes/shared/agent-wire/protocol.ts +7 -0
- package/src/modes/shared/agent-wire/responses.ts +2 -2
- package/src/modes/shared/agent-wire/scopes.ts +2 -0
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +341 -0
- package/src/modes/shared/agent-wire/unattended-audit.ts +175 -0
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +406 -0
- package/src/modes/shared/agent-wire/unattended-session.ts +180 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +324 -0
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +331 -0
- package/src/modes/theme/theme.ts +6 -0
- package/src/prompts/system/system-prompt.md +9 -0
- package/src/runtime-mcp/client.ts +7 -4
- package/src/runtime-mcp/manager.ts +45 -13
- package/src/runtime-mcp/transports/http.ts +40 -14
- package/src/runtime-mcp/transports/stdio.ts +11 -10
- package/src/sdk.ts +47 -0
- package/src/session/agent-session.ts +211 -2
- package/src/session/blob-store.ts +84 -0
- package/src/session/messages.ts +3 -0
- package/src/session/session-manager.ts +390 -33
- package/src/session/session-storage.ts +26 -0
- package/src/setup/provider-onboarding.ts +2 -2
- package/src/skill-state/active-state.ts +89 -1
- package/src/task/discovery.ts +7 -1
- package/src/task/executor.ts +16 -2
- package/src/thinking.ts +8 -2
- package/src/tools/ask.ts +39 -9
- package/src/tools/index.ts +3 -0
- package/src/tools/skill.ts +15 -3
- package/src/utils/edit-mode.ts +1 -1
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { EventEnvelope, ReceiptFamily, SessionState } from "./types";
|
|
2
|
+
interface ResolveHarnessSessionRootOptions {
|
|
3
|
+
expectedWorkspace?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function canonicalWorkspacePath(workspace: string): string;
|
|
2
6
|
export declare const MAX_UNIX_SOCKET_PATH_BYTES = 100;
|
|
3
7
|
export declare function controlSocketPath(root: string, sessionId: string, env?: NodeJS.ProcessEnv): string;
|
|
4
8
|
export declare class StorageError extends Error {
|
|
@@ -27,6 +31,8 @@ export interface SessionPaths {
|
|
|
27
31
|
}
|
|
28
32
|
export declare function sessionPaths(root: string, sessionId: string): SessionPaths;
|
|
29
33
|
export declare function readSessionState(root: string, sessionId: string): Promise<SessionState | null>;
|
|
34
|
+
export declare function rememberHarnessSessionRoot(root: string, sessionId: string, env?: NodeJS.ProcessEnv): Promise<void>;
|
|
35
|
+
export declare function resolveHarnessSessionRoot(root: string, sessionId: string, env?: NodeJS.ProcessEnv, options?: ResolveHarnessSessionRootOptions): Promise<string>;
|
|
30
36
|
export declare function writeSessionState(root: string, state: SessionState): Promise<void>;
|
|
31
37
|
export declare function sessionExists(root: string, sessionId: string): Promise<boolean>;
|
|
32
38
|
/** Append a single severity envelope to events.jsonl. Single-writer discipline is the owner's job (M3). */
|
|
@@ -51,3 +57,4 @@ export declare function writeReceiptImmutable(root: string, sessionId: string, f
|
|
|
51
57
|
createdAt: string;
|
|
52
58
|
}): Promise<ReceiptIndexEntry>;
|
|
53
59
|
export declare function readReceiptIndex(root: string, sessionId: string, family?: ReceiptFamily): Promise<ReceiptIndexEntry[]>;
|
|
60
|
+
export {};
|
|
@@ -4,6 +4,7 @@ import type { LspClient, ServerConfig } from "./types";
|
|
|
4
4
|
* @param ms - Timeout in milliseconds, or null/undefined to disable
|
|
5
5
|
*/
|
|
6
6
|
export declare function setIdleTimeout(ms: number | null | undefined): void;
|
|
7
|
+
export declare function isIdleCheckerActiveForTests(): boolean;
|
|
7
8
|
/** Timeout for warmup initialize requests (5 seconds) */
|
|
8
9
|
export declare const WARMUP_TIMEOUT_MS = 5000;
|
|
9
10
|
/**
|
|
@@ -7,6 +7,7 @@ import { RpcHostUriBridge } from "../shared/agent-wire/host-uri-bridge";
|
|
|
7
7
|
import { type BridgeCommandScope } from "../shared/agent-wire/scopes";
|
|
8
8
|
import { UiRequestBroker } from "../shared/agent-wire/ui-request-broker";
|
|
9
9
|
import type { BridgeUiResult } from "../shared/agent-wire/ui-result";
|
|
10
|
+
import { UnattendedSessionControlPlane } from "../shared/agent-wire/unattended-session";
|
|
10
11
|
import { type BridgePermissionRequestPayload } from "./bridge-client-bridge";
|
|
11
12
|
import { type BridgeUiRequestPayload } from "./bridge-ui-context";
|
|
12
13
|
import { BridgeEventStream } from "./event-stream";
|
|
@@ -30,6 +31,7 @@ interface BridgeFetchHandlerOptions {
|
|
|
30
31
|
hostToolBridge?: RpcHostToolBridge;
|
|
31
32
|
hostUriBridge?: RpcHostUriBridge;
|
|
32
33
|
endpointMatrix?: Partial<BridgeEndpointMatrix>;
|
|
34
|
+
unattendedControlPlane?: UnattendedSessionControlPlane;
|
|
33
35
|
}
|
|
34
36
|
interface BridgeIdempotencyRecord {
|
|
35
37
|
route: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { AutocompleteItem, AutocompleteProvider, SlashCommand } from "@gajae-code/tui";
|
|
2
|
+
import type { KeybindingsManager } from "../config/keybindings";
|
|
3
3
|
interface PromptActionDefinition {
|
|
4
4
|
id: string;
|
|
5
5
|
label: string;
|
|
@@ -8,7 +8,7 @@ import type { CompactionResult } from "@gajae-code/agent-core/compaction";
|
|
|
8
8
|
import type { ImageContent, Model } from "@gajae-code/ai";
|
|
9
9
|
import type { BashResult } from "../../exec/bash-executor";
|
|
10
10
|
import type { SessionStats } from "../../session/agent-session";
|
|
11
|
-
import type { RpcHandoffResult, RpcHostToolDefinition, RpcSessionState } from "./rpc-types";
|
|
11
|
+
import type { RpcExtensionUIRequest, RpcHandoffResult, RpcHostToolDefinition, RpcSessionState, RpcUnattendedAccepted, RpcUnattendedDeclaration, RpcWorkflowGate, RpcWorkflowGateResolution } from "./rpc-types";
|
|
12
12
|
export interface RpcClientOptions {
|
|
13
13
|
/** Path to the CLI entry point (default: searches for dist/cli.js) */
|
|
14
14
|
cliPath?: string;
|
|
@@ -60,6 +60,24 @@ export declare class RpcClient {
|
|
|
60
60
|
* Subscribe to agent events.
|
|
61
61
|
*/
|
|
62
62
|
onEvent(listener: RpcEventListener): () => void;
|
|
63
|
+
/**
|
|
64
|
+
* Subscribe to workflow lifecycle gates emitted by RPC mode.
|
|
65
|
+
*/
|
|
66
|
+
onWorkflowGate(listener: (gate: RpcWorkflowGate) => void): () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Answer a workflow lifecycle gate and wait for the server resolution envelope.
|
|
69
|
+
*/
|
|
70
|
+
respondGate(gateId: string, answer: unknown, idempotencyKey?: string): Promise<RpcWorkflowGateResolution>;
|
|
71
|
+
/**
|
|
72
|
+
* Subscribe to extension UI requests emitted by the server (e.g. select /
|
|
73
|
+
* input / editor / confirm). Returns an unsubscribe function.
|
|
74
|
+
*/
|
|
75
|
+
onExtensionUiRequest(listener: (req: RpcExtensionUIRequest) => void): () => void;
|
|
76
|
+
/**
|
|
77
|
+
* Enter unattended mode by declaring budget + scopes + action allowlist.
|
|
78
|
+
* Returns the accepted declaration, or rejects (fail-closed) on refusal.
|
|
79
|
+
*/
|
|
80
|
+
negotiateUnattended(declaration: RpcUnattendedDeclaration): Promise<RpcUnattendedAccepted>;
|
|
63
81
|
/**
|
|
64
82
|
* Get collected stderr output (useful for debugging).
|
|
65
83
|
*/
|
|
@@ -145,7 +145,14 @@ export type RpcCommand = {
|
|
|
145
145
|
id?: string;
|
|
146
146
|
type: "login";
|
|
147
147
|
providerId: string;
|
|
148
|
-
}
|
|
148
|
+
} | {
|
|
149
|
+
id?: string;
|
|
150
|
+
type: "negotiate_unattended";
|
|
151
|
+
declaration: RpcUnattendedDeclaration;
|
|
152
|
+
} | ({
|
|
153
|
+
id?: string;
|
|
154
|
+
type: "workflow_gate_response";
|
|
155
|
+
} & RpcWorkflowGateResponse);
|
|
149
156
|
export interface RpcSessionState {
|
|
150
157
|
model?: Model;
|
|
151
158
|
thinkingLevel: ThinkingLevel | undefined;
|
|
@@ -411,12 +418,24 @@ export type RpcResponse = {
|
|
|
411
418
|
data: {
|
|
412
419
|
providerId: string;
|
|
413
420
|
};
|
|
421
|
+
} | {
|
|
422
|
+
id?: string;
|
|
423
|
+
type: "response";
|
|
424
|
+
command: "negotiate_unattended";
|
|
425
|
+
success: true;
|
|
426
|
+
data: RpcUnattendedAccepted;
|
|
427
|
+
} | {
|
|
428
|
+
id?: string;
|
|
429
|
+
type: "response";
|
|
430
|
+
command: "workflow_gate_response";
|
|
431
|
+
success: true;
|
|
432
|
+
data: RpcWorkflowGateResolution;
|
|
414
433
|
} | {
|
|
415
434
|
id?: string;
|
|
416
435
|
type: "response";
|
|
417
436
|
command: string;
|
|
418
437
|
success: false;
|
|
419
|
-
error: string;
|
|
438
|
+
error: string | object;
|
|
420
439
|
};
|
|
421
440
|
/** Emitted when an extension needs user input */
|
|
422
441
|
export type RpcExtensionUIRequest = {
|
|
@@ -584,3 +603,161 @@ export type RpcExtensionUIResponse = {
|
|
|
584
603
|
timedOut?: boolean;
|
|
585
604
|
};
|
|
586
605
|
export type RpcCommandType = RpcCommand["type"];
|
|
606
|
+
/**
|
|
607
|
+
* Lifecycle stages that emit machine-addressable gates. v1 is single-agent;
|
|
608
|
+
* `team` parallel execution over RPC is deferred, so it is intentionally absent
|
|
609
|
+
* from this union. Gate construction rejects any other stage value.
|
|
610
|
+
*/
|
|
611
|
+
export type RpcWorkflowStage = "deep-interview" | "ralplan" | "ultragoal";
|
|
612
|
+
/** Reserved stage names that are explicitly not part of the v1 contract. */
|
|
613
|
+
export declare const RESERVED_WORKFLOW_STAGES: readonly string[];
|
|
614
|
+
export type RpcWorkflowGateKind = "question" | "approval" | "execution";
|
|
615
|
+
/**
|
|
616
|
+
* The documented JSON Schema 2020-12 subset supported by the gate validator.
|
|
617
|
+
* Schemas containing any keyword outside this shape are rejected at gate
|
|
618
|
+
* construction time so the server never advertises a schema it cannot validate.
|
|
619
|
+
*/
|
|
620
|
+
export interface RpcJsonSchema {
|
|
621
|
+
type?: "string" | "number" | "integer" | "boolean" | "object" | "array" | "null";
|
|
622
|
+
enum?: unknown[];
|
|
623
|
+
const?: unknown;
|
|
624
|
+
properties?: Record<string, RpcJsonSchema>;
|
|
625
|
+
required?: string[];
|
|
626
|
+
additionalProperties?: boolean | RpcJsonSchema;
|
|
627
|
+
items?: RpcJsonSchema;
|
|
628
|
+
minLength?: number;
|
|
629
|
+
maxLength?: number;
|
|
630
|
+
minItems?: number;
|
|
631
|
+
maxItems?: number;
|
|
632
|
+
uniqueItems?: boolean;
|
|
633
|
+
minimum?: number;
|
|
634
|
+
maximum?: number;
|
|
635
|
+
title?: string;
|
|
636
|
+
description?: string;
|
|
637
|
+
oneOf?: RpcJsonSchema[];
|
|
638
|
+
anyOf?: RpcJsonSchema[];
|
|
639
|
+
}
|
|
640
|
+
export interface RpcWorkflowGateOption {
|
|
641
|
+
value: unknown;
|
|
642
|
+
label: string;
|
|
643
|
+
description?: string;
|
|
644
|
+
}
|
|
645
|
+
export interface RpcWorkflowGateContext {
|
|
646
|
+
title?: string;
|
|
647
|
+
prompt?: string;
|
|
648
|
+
summary?: string;
|
|
649
|
+
stage_state?: Record<string, unknown>;
|
|
650
|
+
artifact_refs?: Array<{
|
|
651
|
+
kind: string;
|
|
652
|
+
path?: string;
|
|
653
|
+
sha256?: string;
|
|
654
|
+
}>;
|
|
655
|
+
language?: string;
|
|
656
|
+
}
|
|
657
|
+
/** Outbound event: a machine-addressable workflow gate awaiting an answer. */
|
|
658
|
+
export interface RpcWorkflowGate {
|
|
659
|
+
type: "workflow_gate";
|
|
660
|
+
/** Run-scoped, monotonic, stable id (e.g. `wg_<run>_<stage>_000001`). */
|
|
661
|
+
gate_id: string;
|
|
662
|
+
stage: RpcWorkflowStage;
|
|
663
|
+
kind: RpcWorkflowGateKind;
|
|
664
|
+
schema: RpcJsonSchema;
|
|
665
|
+
/** Canonical hash of `schema`; advertised hash must equal server validation hash. */
|
|
666
|
+
schema_hash: string;
|
|
667
|
+
options?: RpcWorkflowGateOption[];
|
|
668
|
+
context: RpcWorkflowGateContext;
|
|
669
|
+
created_at: string;
|
|
670
|
+
required: true;
|
|
671
|
+
}
|
|
672
|
+
/** Inbound: the agent's answer to a workflow gate. */
|
|
673
|
+
export interface RpcWorkflowGateResponse {
|
|
674
|
+
gate_id: string;
|
|
675
|
+
answer: unknown;
|
|
676
|
+
/** Optional idempotency key; same key + body returns the cached resolution. */
|
|
677
|
+
idempotency_key?: string;
|
|
678
|
+
}
|
|
679
|
+
/** Outcome of resolving a gate, surfaced back to the answering client. */
|
|
680
|
+
export interface RpcWorkflowGateResolution {
|
|
681
|
+
gate_id: string;
|
|
682
|
+
status: "accepted" | "rejected";
|
|
683
|
+
answer_hash: string;
|
|
684
|
+
resolved_at: string;
|
|
685
|
+
/** Present only when `status === "rejected"`. */
|
|
686
|
+
error?: RpcWorkflowGateValidationError;
|
|
687
|
+
}
|
|
688
|
+
/** Typed error shape for schema validation failures (#315 acceptance). */
|
|
689
|
+
export interface RpcWorkflowGateValidationError {
|
|
690
|
+
code: "invalid_workflow_gate_answer";
|
|
691
|
+
gate_id: string;
|
|
692
|
+
schema_hash: string;
|
|
693
|
+
errors: Array<{
|
|
694
|
+
path: string;
|
|
695
|
+
keyword: string;
|
|
696
|
+
message: string;
|
|
697
|
+
expected?: unknown;
|
|
698
|
+
}>;
|
|
699
|
+
}
|
|
700
|
+
export interface RpcUnattendedBudget {
|
|
701
|
+
max_tokens: number;
|
|
702
|
+
max_tool_calls: number;
|
|
703
|
+
max_wall_time_ms: number;
|
|
704
|
+
max_cost_usd: number;
|
|
705
|
+
}
|
|
706
|
+
export interface RpcUnattendedDeclaration {
|
|
707
|
+
/** Identity of the operating external agent, recorded in the audit trail. */
|
|
708
|
+
actor: string;
|
|
709
|
+
budget: RpcUnattendedBudget;
|
|
710
|
+
/** Coarse command scopes the agent may use (maps to BridgeCommandScope). */
|
|
711
|
+
scopes: string[];
|
|
712
|
+
/** Action classes the agent is allowed to perform (default-deny otherwise). */
|
|
713
|
+
action_allowlist: string[];
|
|
714
|
+
}
|
|
715
|
+
export interface RpcUnattendedAccepted {
|
|
716
|
+
run_id: string;
|
|
717
|
+
actor: string;
|
|
718
|
+
budget: RpcUnattendedBudget;
|
|
719
|
+
scopes: string[];
|
|
720
|
+
action_allowlist: string[];
|
|
721
|
+
accepted_at: string;
|
|
722
|
+
}
|
|
723
|
+
export type RpcBudgetMetric = "tokens" | "tool_calls" | "wall_time" | "cost";
|
|
724
|
+
/** Typed payload emitted when a declared budget cap is breached (#318). */
|
|
725
|
+
export interface RpcBudgetExceeded {
|
|
726
|
+
code: "budget_exceeded";
|
|
727
|
+
metric: RpcBudgetMetric;
|
|
728
|
+
limit: number;
|
|
729
|
+
observed: number;
|
|
730
|
+
/** The accounting phase that detected the breach. */
|
|
731
|
+
phase: string;
|
|
732
|
+
run_id: string;
|
|
733
|
+
session_id?: string;
|
|
734
|
+
/** `aborting` = breach detected, async abort initiated; settled status follows in audit. */
|
|
735
|
+
abort_status: "aborting" | "aborted" | "abort_failed";
|
|
736
|
+
}
|
|
737
|
+
export type RpcUnattendedRefusalCode = "unattended_not_negotiated" | "incomplete_budget" | "unsupported_budget_metric" | "invalid_unattended_declaration" | "unattended_aborted";
|
|
738
|
+
/** Typed refusal emitted when unattended mode cannot start or continue (fail-closed). */
|
|
739
|
+
export interface RpcUnattendedRefused {
|
|
740
|
+
code: RpcUnattendedRefusalCode;
|
|
741
|
+
message: string;
|
|
742
|
+
}
|
|
743
|
+
/** v1 action taxonomy: every authorized operation maps to one of these classes. */
|
|
744
|
+
export type RpcUnattendedActionClass = "command.prompt" | "command.control" | "command.bash" | "command.export" | "command.session" | "command.model" | "command.message_read" | "command.host_tools" | "command.host_uri" | "command.admin" | "bash.readonly" | "bash.mutating" | "bash.destructive" | "git.force_push" | "file.delete" | "file.write" | "host_tool.invoke" | "host_uri.read" | "host_uri.write" | "auth.login";
|
|
745
|
+
/** Typed error when a command's coarse scope is not in the declared allowlist. */
|
|
746
|
+
export interface RpcScopeDenied {
|
|
747
|
+
code: "scope_denied";
|
|
748
|
+
scope: string;
|
|
749
|
+
command?: string;
|
|
750
|
+
run_id: string;
|
|
751
|
+
session_id?: string;
|
|
752
|
+
/** Always true: enforcement happens before the side effect runs. */
|
|
753
|
+
pre_side_effect: true;
|
|
754
|
+
}
|
|
755
|
+
/** Typed error when an action class is not in the declared allowlist (default-deny). */
|
|
756
|
+
export interface RpcActionDenied {
|
|
757
|
+
code: "action_denied";
|
|
758
|
+
action: string;
|
|
759
|
+
command?: string;
|
|
760
|
+
run_id: string;
|
|
761
|
+
session_id?: string;
|
|
762
|
+
pre_side_effect: true;
|
|
763
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ralplan approval + ultragoal execution gate mapping (#317).
|
|
3
|
+
*
|
|
4
|
+
* Maps the two human-gated lifecycle decisions onto `workflow_gate` events:
|
|
5
|
+
* - ralplan `pending approval` -> `workflow_gate` { kind: "approval" } whose
|
|
6
|
+
* answer is one of approve / request-changes / reject (+ optional comments);
|
|
7
|
+
* - ultragoal execution sign-off -> `workflow_gate` { kind: "execution" } whose
|
|
8
|
+
* answer is approve / decline (+ optional reason).
|
|
9
|
+
*
|
|
10
|
+
* Gates remain mandatory; the external agent substitutes for the human at the
|
|
11
|
+
* answer boundary only. Declining / requesting changes is honored and is NEVER
|
|
12
|
+
* silently treated as approval.
|
|
13
|
+
*
|
|
14
|
+
* This is the pure mapping primitive; routing ralplan/ultragoal through it when
|
|
15
|
+
* an unattended controller + gate broker are attached is wired with the transport
|
|
16
|
+
* in #321 and exercised end-to-end by #323.
|
|
17
|
+
*/
|
|
18
|
+
import type { RpcWorkflowGateContext } from "../../rpc/rpc-types";
|
|
19
|
+
import type { OpenGateInput } from "./workflow-gate-broker";
|
|
20
|
+
export type ApprovalDecision = "approve" | "request-changes" | "reject";
|
|
21
|
+
export type ExecutionDecision = "approve" | "decline";
|
|
22
|
+
export interface ApprovalGateAnswer {
|
|
23
|
+
decision: ApprovalDecision;
|
|
24
|
+
comments?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ExecutionGateAnswer {
|
|
27
|
+
decision: ExecutionDecision;
|
|
28
|
+
reason?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ApprovalGateResult {
|
|
31
|
+
approved: boolean;
|
|
32
|
+
decision: ApprovalDecision;
|
|
33
|
+
comments?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ExecutionGateResult {
|
|
36
|
+
approved: boolean;
|
|
37
|
+
decision: ExecutionDecision;
|
|
38
|
+
reason?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare class ApprovalGateError extends Error {
|
|
41
|
+
readonly code: "invalid_answer_shape" | "unknown_decision" | "missing_comments";
|
|
42
|
+
constructor(code: "invalid_answer_shape" | "unknown_decision" | "missing_comments", message: string);
|
|
43
|
+
}
|
|
44
|
+
/** Build the ralplan `pending approval` -> `workflow_gate { kind: "approval" }` open-input. */
|
|
45
|
+
export declare function approvalGate(context?: RpcWorkflowGateContext): OpenGateInput;
|
|
46
|
+
/** Build the ultragoal execution sign-off -> `workflow_gate { kind: "execution" }` open-input. */
|
|
47
|
+
export declare function executionGate(context?: RpcWorkflowGateContext): OpenGateInput;
|
|
48
|
+
/**
|
|
49
|
+
* Decode a ralplan approval answer. `request-changes` requires comments and is
|
|
50
|
+
* NEVER treated as approval; only an explicit `approve` advances.
|
|
51
|
+
*/
|
|
52
|
+
export declare function decodeApproval(answer: unknown): ApprovalGateResult;
|
|
53
|
+
/**
|
|
54
|
+
* Decode an ultragoal execution answer. Only an explicit `approve` advances;
|
|
55
|
+
* `decline` is honored and never silently approved.
|
|
56
|
+
*/
|
|
57
|
+
export declare function decodeExecution(answer: unknown): ExecutionGateResult;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentTool } from "@gajae-code/agent-core";
|
|
2
2
|
import type { ExtensionUIContext } from "../../../extensibility/extensions";
|
|
3
3
|
import type { AgentSession } from "../../../session/agent-session";
|
|
4
|
-
import type { RpcCommand, RpcExtensionUIRequest, RpcHostToolDefinition, RpcHostUriSchemeDefinition, RpcResponse } from "../../rpc/rpc-types";
|
|
4
|
+
import type { RpcCommand, RpcExtensionUIRequest, RpcHostToolDefinition, RpcHostUriSchemeDefinition, RpcResponse, RpcUnattendedAccepted, RpcUnattendedDeclaration, RpcWorkflowGateResolution, RpcWorkflowGateResponse } from "../../rpc/rpc-types";
|
|
5
5
|
export type RpcCommandDispatchOutput = (obj: RpcResponse | RpcExtensionUIRequest | object) => void;
|
|
6
6
|
export interface RpcHostToolRegistry {
|
|
7
7
|
setTools(tools: RpcHostToolDefinition[]): AgentTool[];
|
|
@@ -9,12 +9,27 @@ export interface RpcHostToolRegistry {
|
|
|
9
9
|
export interface RpcHostUriRegistry {
|
|
10
10
|
setSchemes(schemes: RpcHostUriSchemeDefinition[]): string[];
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Optional unattended control plane wired into RPC dispatch (#318/#319/#323).
|
|
14
|
+
* When present, `negotiate_unattended` and `workflow_gate_response` route here
|
|
15
|
+
* instead of falling through to the unknown-command path.
|
|
16
|
+
*/
|
|
17
|
+
export interface RpcUnattendedControlPlane {
|
|
18
|
+
/** Enter unattended mode (fail-closed); throws an Error on refusal. */
|
|
19
|
+
negotiate(declaration: RpcUnattendedDeclaration): RpcUnattendedAccepted;
|
|
20
|
+
/** Resolve a pending workflow gate with the agent's answer. */
|
|
21
|
+
resolveGate(response: RpcWorkflowGateResponse): Promise<RpcWorkflowGateResolution>;
|
|
22
|
+
isUnattended?(): boolean;
|
|
23
|
+
preflightCommand?(command: RpcCommand): void;
|
|
24
|
+
reconcileUsage?(phase?: string): void;
|
|
25
|
+
}
|
|
12
26
|
export interface RpcCommandDispatchContext {
|
|
13
27
|
session: AgentSession;
|
|
14
28
|
output: RpcCommandDispatchOutput;
|
|
15
29
|
hostToolRegistry: RpcHostToolRegistry;
|
|
16
30
|
hostUriRegistry: RpcHostUriRegistry;
|
|
17
31
|
createUiContext: () => Pick<ExtensionUIContext, "notify">;
|
|
32
|
+
unattendedControlPlane?: RpcUnattendedControlPlane;
|
|
18
33
|
}
|
|
19
34
|
export declare function normalizeHostToolDefinitions(tools: RpcHostToolDefinition[]): RpcHostToolDefinition[];
|
|
20
35
|
export declare function dispatchRpcCommand(command: RpcCommand, context: RpcCommandDispatchContext): Promise<RpcResponse>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { OpenGateInput } from "./workflow-gate-broker";
|
|
2
|
+
/** "Other (type your own)" sentinel, mirroring the interactive ask tool. */
|
|
3
|
+
export declare const GATE_OTHER_OPTION = "Other (type your own)";
|
|
4
|
+
export interface AskGateQuestion {
|
|
5
|
+
id: string;
|
|
6
|
+
question: string;
|
|
7
|
+
options: Array<{
|
|
8
|
+
label: string;
|
|
9
|
+
}>;
|
|
10
|
+
multi?: boolean;
|
|
11
|
+
recommended?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface AskGateResult {
|
|
14
|
+
id: string;
|
|
15
|
+
question: string;
|
|
16
|
+
options: string[];
|
|
17
|
+
multi: boolean;
|
|
18
|
+
selectedOptions: string[];
|
|
19
|
+
customInput?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The answer shape an agent returns for a deep-interview question gate.
|
|
23
|
+
*
|
|
24
|
+
* `selected` are picked option labels; free text is conveyed by `other: true`
|
|
25
|
+
* plus `custom`, encoded separately from `selected` so a real option whose label
|
|
26
|
+
* happens to equal the display sentinel can never collide with the free-text path.
|
|
27
|
+
*/
|
|
28
|
+
export interface DeepInterviewGateAnswer {
|
|
29
|
+
selected: string[];
|
|
30
|
+
other?: boolean;
|
|
31
|
+
custom?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class DeepInterviewGateError extends Error {
|
|
34
|
+
readonly code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection";
|
|
35
|
+
constructor(code: "invalid_answer_shape" | "unknown_option" | "multi_not_allowed" | "missing_custom" | "empty_selection" | "duplicate_selection", message: string);
|
|
36
|
+
}
|
|
37
|
+
/** Build the `workflow_gate` open-input for one deep-interview question. */
|
|
38
|
+
export declare function questionToGate(question: AskGateQuestion): OpenGateInput;
|
|
39
|
+
/**
|
|
40
|
+
* Decode a gate answer into the QuestionResult the interactive path produces.
|
|
41
|
+
* Selections are de-duplicated (the interactive UI stores them in a Set), and
|
|
42
|
+
* free text is taken from `other`/`custom`. Throws DeepInterviewGateError on a
|
|
43
|
+
* semantically invalid answer.
|
|
44
|
+
*/
|
|
45
|
+
export declare function gateAnswerToResult(question: AskGateQuestion, answer: unknown): AskGateResult;
|
|
46
|
+
/** Convenience: map a batch of ask questions to gate open-inputs. */
|
|
47
|
+
export declare function questionsToGates(questions: AskGateQuestion[]): OpenGateInput[];
|
|
@@ -22,3 +22,10 @@ export declare class BridgeFrameSequencer {
|
|
|
22
22
|
}
|
|
23
23
|
/** Serialize a single `AgentSessionEvent` into an `event` wire frame. */
|
|
24
24
|
export declare function toBridgeEventFrame(event: AgentSessionEvent, sequencer: BridgeFrameSequencer): BridgeEventFrame;
|
|
25
|
+
/**
|
|
26
|
+
* Serialize a `workflow_gate` event into a sequenced wire frame (#321). The
|
|
27
|
+
* gate_id is stamped as the correlation id so the answer (posted to the
|
|
28
|
+
* ui-responses endpoint) can be matched, and the monotonic `seq` gives replay
|
|
29
|
+
* while `frame_id` + gate_id give idempotency.
|
|
30
|
+
*/
|
|
31
|
+
export declare function toBridgeWorkflowGateFrame(gate: import("../../rpc/rpc-types").RpcWorkflowGate, sequencer: BridgeFrameSequencer): import("./protocol").BridgeWorkflowGateFrame;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { RpcUnattendedDeclaration } from "../../rpc/rpc-types";
|
|
1
2
|
import { BRIDGE_PROTOCOL_VERSION, type BridgeFrameType } from "./protocol";
|
|
2
3
|
import type { BridgeCommandScope } from "./scopes";
|
|
3
|
-
export type BridgeCapability = "events" | "prompt" | "permission" | "elicitation" | "ui.declarative" | "ui.editor" | "ui.terminal_input" | "host_tools" | "host_uri" | "client_bridge.read_text_file" | "client_bridge.write_text_file" | "client_bridge.create_terminal";
|
|
4
|
+
export type BridgeCapability = "events" | "prompt" | "permission" | "elicitation" | "ui.declarative" | "ui.editor" | "ui.terminal_input" | "host_tools" | "host_uri" | "client_bridge.read_text_file" | "client_bridge.write_text_file" | "client_bridge.create_terminal" | "workflow_gate";
|
|
4
5
|
export interface BridgeProtocolRange {
|
|
5
6
|
min: number;
|
|
6
7
|
max: number;
|
|
@@ -10,6 +11,8 @@ export interface BridgeHandshakeRequest {
|
|
|
10
11
|
capabilities: BridgeCapability[];
|
|
11
12
|
requested_scopes: BridgeCommandScope[];
|
|
12
13
|
last_seq?: number;
|
|
14
|
+
/** Optional unattended declaration (budget + scope + action allowlist) for #318/#319. */
|
|
15
|
+
unattended?: RpcUnattendedDeclaration;
|
|
13
16
|
}
|
|
14
17
|
export interface BridgeEndpointDescriptor {
|
|
15
18
|
events: string;
|
|
@@ -29,6 +32,10 @@ export interface BridgeHandshakeAccepted {
|
|
|
29
32
|
unsupported: BridgeCapability[];
|
|
30
33
|
endpoints: BridgeEndpointDescriptor;
|
|
31
34
|
frame_types: BridgeFrameType[];
|
|
35
|
+
/** Echoed unattended declaration when one was supplied and accepted (#321). */
|
|
36
|
+
accepted_unattended?: RpcUnattendedDeclaration;
|
|
37
|
+
/** Server-side accepted unattended mode after live negotiation, not just declaration echo. */
|
|
38
|
+
unattended_active?: boolean;
|
|
32
39
|
}
|
|
33
40
|
export interface BridgeHandshakeRejected {
|
|
34
41
|
status: "rejected";
|
|
@@ -36,6 +43,8 @@ export interface BridgeHandshakeRejected {
|
|
|
36
43
|
message: string;
|
|
37
44
|
}
|
|
38
45
|
export type BridgeHandshakeResponse = BridgeHandshakeAccepted | BridgeHandshakeRejected;
|
|
46
|
+
/** Shape-validate an optional unattended declaration carried on the handshake. */
|
|
47
|
+
export declare function isUnattendedDeclarationShape(value: unknown): value is RpcUnattendedDeclaration;
|
|
39
48
|
export declare function isBridgeHandshakeRequest(value: unknown): value is BridgeHandshakeRequest;
|
|
40
49
|
export declare function negotiateBridgeHandshake(request: BridgeHandshakeRequest, server: {
|
|
41
50
|
sessionId: string;
|
|
@@ -43,4 +52,5 @@ export declare function negotiateBridgeHandshake(request: BridgeHandshakeRequest
|
|
|
43
52
|
scopes: readonly BridgeCommandScope[];
|
|
44
53
|
endpoints: BridgeEndpointDescriptor;
|
|
45
54
|
frameTypes: readonly BridgeFrameType[];
|
|
55
|
+
acceptedUnattended?: RpcUnattendedDeclaration;
|
|
46
56
|
}): BridgeHandshakeResponse;
|
|
@@ -15,7 +15,7 @@ export type AgentSessionEventType = AgentSessionEvent["type"];
|
|
|
15
15
|
/** Every agent-session event type, derived from the exhaustive registry. */
|
|
16
16
|
export declare const AGENT_SESSION_EVENT_TYPES: readonly AgentSessionEventType[];
|
|
17
17
|
/** Top-level frame categories carried over any bridge transport. */
|
|
18
|
-
export type BridgeFrameType = "ready" | "event" | "response" | "ui_request" | "permission_request" | "host_tool_call" | "host_uri_request" | "reset" | "error";
|
|
18
|
+
export type BridgeFrameType = "ready" | "event" | "response" | "ui_request" | "permission_request" | "host_tool_call" | "host_uri_request" | "reset" | "workflow_gate" | "error";
|
|
19
19
|
/**
|
|
20
20
|
* Universal frame envelope. Every frame on every transport carries these
|
|
21
21
|
* fields so clients can order (`seq`), resume (`seq` cursor), and correlate
|
|
@@ -42,3 +42,5 @@ export interface BridgeEventPayload {
|
|
|
42
42
|
}
|
|
43
43
|
/** An `AgentSessionEvent` serialized into a versioned wire frame. */
|
|
44
44
|
export type BridgeEventFrame = BridgeFrameEnvelope<"event", BridgeEventPayload>;
|
|
45
|
+
/** A `workflow_gate` event serialized into a versioned wire frame (#321). */
|
|
46
|
+
export type BridgeWorkflowGateFrame = BridgeFrameEnvelope<"workflow_gate", import("../../rpc/rpc-types").RpcWorkflowGate>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Shared RPC-compatible response helpers for agent-wire consumers. */
|
|
2
2
|
import type { RpcCommand, RpcResponse } from "../../rpc/rpc-types";
|
|
3
3
|
export declare function rpcSuccess<T extends RpcCommand["type"]>(id: string | undefined, command: T, data?: object | null): RpcResponse;
|
|
4
|
-
export declare function rpcError(id: string | undefined, command: string,
|
|
4
|
+
export declare function rpcError(id: string | undefined, command: string, error: string | object): RpcResponse;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unattended action taxonomy + classifier (#319).
|
|
3
|
+
*
|
|
4
|
+
* Maps coarse command scopes and concrete bash commands onto the v1 action
|
|
5
|
+
* taxonomy so the controller can authorize (default-deny) BEFORE any side effect.
|
|
6
|
+
*
|
|
7
|
+
* The classifier is deliberately FAIL-CLOSED for shell evasion:
|
|
8
|
+
* - nested execution via `$(...)`, backticks, and `<(...)` / `>(...)` is
|
|
9
|
+
* extracted and classified recursively, so a destructive command hidden in a
|
|
10
|
+
* substitution cannot masquerade as the harmless outer command;
|
|
11
|
+
* - statements are split on newlines and `; && || | &`, so a second
|
|
12
|
+
* (destructive) command on another line is classified too;
|
|
13
|
+
* - leading environment assignments and wrappers (`sudo`, `env`, `command`,
|
|
14
|
+
* `xargs`, …) are stripped/followed to the effective command;
|
|
15
|
+
* - anything that is not provably read-only escalates to at least
|
|
16
|
+
* `bash.mutating`, and clearly destructive forms escalate further, so an
|
|
17
|
+
* undeclared destructive action is denied rather than silently allowed.
|
|
18
|
+
*/
|
|
19
|
+
import type { RpcUnattendedActionClass } from "../../rpc/rpc-types";
|
|
20
|
+
import type { BridgeCommandScope } from "./scopes";
|
|
21
|
+
/** Coarse command scope -> `command.<scope>` action class. */
|
|
22
|
+
export declare function actionClassForScope(scope: BridgeCommandScope): RpcUnattendedActionClass;
|
|
23
|
+
/**
|
|
24
|
+
* Classify a (possibly compound / nested) bash command into the most severe
|
|
25
|
+
* action class across all statements and nested substitutions. Fail-closed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function classifyBashAction(command: string): RpcUnattendedActionClass;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { RpcBudgetExceeded, RpcWorkflowGateKind, RpcWorkflowStage } from "../../rpc/rpc-types";
|
|
2
|
+
export declare const AUDIT_SCHEMA_VERSION = 1;
|
|
3
|
+
export declare const AUDIT_CATEGORY = "unattended_lifecycle";
|
|
4
|
+
export type AuditOutcome = "accepted" | "rejected" | "denied" | "exceeded" | "aborted" | "info";
|
|
5
|
+
export interface AuditRecord {
|
|
6
|
+
event_id: string;
|
|
7
|
+
schema_version: number;
|
|
8
|
+
category: typeof AUDIT_CATEGORY;
|
|
9
|
+
run_id: string;
|
|
10
|
+
session_id?: string;
|
|
11
|
+
actor?: string;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
event: string;
|
|
14
|
+
outcome: AuditOutcome;
|
|
15
|
+
dedupe_key: string;
|
|
16
|
+
gate_id?: string;
|
|
17
|
+
stage?: RpcWorkflowStage;
|
|
18
|
+
kind?: RpcWorkflowGateKind;
|
|
19
|
+
scope?: string;
|
|
20
|
+
action?: string;
|
|
21
|
+
budget?: RpcBudgetExceeded;
|
|
22
|
+
/** Full answer (omitted when redaction is enabled). */
|
|
23
|
+
answer?: unknown;
|
|
24
|
+
answer_hash?: string;
|
|
25
|
+
error?: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface AuditQuery {
|
|
28
|
+
run_id?: string;
|
|
29
|
+
session_id?: string;
|
|
30
|
+
actor?: string;
|
|
31
|
+
gate_id?: string;
|
|
32
|
+
outcome?: AuditOutcome;
|
|
33
|
+
event?: string;
|
|
34
|
+
since?: string;
|
|
35
|
+
until?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface AuditLogOptions {
|
|
38
|
+
/** When true, gate answers are stored as hash + summary only. */
|
|
39
|
+
redactAnswers?: boolean;
|
|
40
|
+
/** Injectable id/clock for deterministic tests. */
|
|
41
|
+
now?(): number;
|
|
42
|
+
nextId?(): string;
|
|
43
|
+
}
|
|
44
|
+
export declare function defaultAuditPath(runId: string, root?: string): string;
|
|
45
|
+
/** Append-only audit log writer + reader for one unattended run. */
|
|
46
|
+
export declare class UnattendedAuditLog {
|
|
47
|
+
private readonly filePath;
|
|
48
|
+
private readonly seen;
|
|
49
|
+
private readonly now;
|
|
50
|
+
private readonly nextId;
|
|
51
|
+
private readonly redactAnswers;
|
|
52
|
+
constructor(filePath: string, options?: AuditLogOptions);
|
|
53
|
+
/**
|
|
54
|
+
* Append a record. Returns the written record, or `null` if a record with the
|
|
55
|
+
* same dedupe_key was already written (exactly-once).
|
|
56
|
+
*/
|
|
57
|
+
record(input: Omit<AuditRecord, "event_id" | "schema_version" | "category" | "timestamp">): AuditRecord | null;
|
|
58
|
+
/** Append one line and fsync it for crash durability. */
|
|
59
|
+
private appendDurable;
|
|
60
|
+
/** Read every record (fail-closed: a corrupt line throws rather than silently dropping). */
|
|
61
|
+
readAll(): AuditRecord[];
|
|
62
|
+
/** Query records with filters (run/session/actor/gate/outcome/event + time window). */
|
|
63
|
+
query(filter?: AuditQuery): AuditRecord[];
|
|
64
|
+
/** Export the full trail as an array (for `get_unattended_audit`). */
|
|
65
|
+
export(filter?: AuditQuery): AuditRecord[];
|
|
66
|
+
}
|
|
67
|
+
/** SHA-256 of the canonical JSON of an answer (matches the gate broker's hash). */
|
|
68
|
+
export declare function answerHash(answer: unknown): string;
|