@quantiya/codevibe-core 2.0.1 → 2.0.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/dist/__tests__/prompt-parser.test.d.ts +1 -0
- package/dist/adapter/registry.d.ts +69 -2
- package/dist/appsync/__tests__/appsync-client-event-source-filter.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client-task-group.test.d.ts +1 -0
- package/dist/appsync/__tests__/cleanup-subscription.test.d.ts +1 -0
- package/dist/appsync/__tests__/coerce-awsjson-and-review-summary.test.d.ts +1 -0
- package/dist/appsync/__tests__/cp1f-quorum-sdk.test.d.ts +1 -0
- package/dist/appsync/__tests__/event-throttle.test.d.ts +1 -0
- package/dist/appsync/appsync-client.d.ts +621 -10
- package/dist/appsync/event-throttle.d.ts +28 -0
- package/dist/appsync/index.d.ts +3 -0
- package/dist/appsync/queries.d.ts +19 -0
- package/dist/audit-keys/index.d.ts +32 -0
- package/dist/auth/auth-service.d.ts +32 -2
- package/dist/auth/auth-telemetry.d.ts +19 -1
- package/dist/auth/index.d.ts +1 -0
- package/dist/companion-mode/persist-preference.d.ts +1 -1
- package/dist/config/config.d.ts +8 -1
- package/dist/continuation/__tests__/dirty-state-collector.test.d.ts +1 -0
- package/dist/continuation/__tests__/integration.test.d.ts +1 -0
- package/dist/continuation/__tests__/packet-reader.test.d.ts +1 -0
- package/dist/continuation/__tests__/packet-writer.test.d.ts +1 -0
- package/dist/continuation/__tests__/parity.test.d.ts +1 -0
- package/dist/continuation/__tests__/status-cli.test.d.ts +1 -0
- package/dist/continuation/dirty-state-collector.d.ts +46 -0
- package/dist/continuation/index.d.ts +8 -0
- package/dist/continuation/packet-reader.d.ts +33 -0
- package/dist/continuation/packet-writer.d.ts +86 -0
- package/dist/continuation/types.d.ts +239 -0
- package/dist/credential-broker/__tests__/broker.test.d.ts +1 -0
- package/dist/credential-broker/__tests__/canonical.test.d.ts +1 -0
- package/dist/credential-broker/__tests__/scrubber.test.d.ts +1 -0
- package/dist/credential-broker/__tests__/upstream-client.test.d.ts +1 -0
- package/dist/credential-broker/__tests__/vendor-key-store.test.d.ts +1 -0
- package/dist/credential-broker/audit-sink.d.ts +69 -0
- package/dist/credential-broker/broker-config.d.ts +39 -0
- package/dist/credential-broker/broker-token.d.ts +123 -0
- package/dist/credential-broker/broker.d.ts +165 -0
- package/dist/credential-broker/canonical.d.ts +119 -0
- package/dist/credential-broker/index.d.ts +15 -0
- package/dist/credential-broker/scrubber.d.ts +45 -0
- package/dist/credential-broker/types.d.ts +141 -0
- package/dist/credential-broker/upstream-client.d.ts +20 -0
- package/dist/credential-broker/vendor-key-store.d.ts +54 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +427 -124
- package/dist/keychain/__tests__/keychain-backend.test.d.ts +1 -0
- package/dist/keychain/keychain-backend.d.ts +82 -0
- package/dist/local-executor/__tests__/agentic-disposable-repo.test.d.ts +1 -0
- package/dist/local-executor/__tests__/agentic-resolve.test.d.ts +1 -0
- package/dist/local-executor/__tests__/agentic-resolver-flag.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-a-sign.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class1-reconcilers.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class2-resolver.test.d.ts +1 -0
- package/dist/local-executor/__tests__/confined-model-caller.test.d.ts +1 -0
- package/dist/local-executor/__tests__/conflict-classifier.test.d.ts +1 -0
- package/dist/local-executor/__tests__/conflict-resolution-durable-store.test.d.ts +1 -0
- package/dist/local-executor/__tests__/conflict-resolution-store.test.d.ts +1 -0
- package/dist/local-executor/__tests__/cp1f-quorum-consumer.test.d.ts +1 -0
- package/dist/local-executor/__tests__/cp7-audit-writer.test.d.ts +1 -0
- package/dist/local-executor/__tests__/durable-store.test.d.ts +1 -0
- package/dist/local-executor/__tests__/git-lock-retry.test.d.ts +1 -0
- package/dist/local-executor/__tests__/implementor-argv.test.d.ts +1 -0
- package/dist/local-executor/__tests__/local-executor-teams.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-conflict-extract.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-conflict-git.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-conflict-resolve-agentic.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-conflict-resolve.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-journal-store.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-train-agentic-recovery.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-train-w3.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-train-waveb.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/merge-train.test.d.ts +1 -0
- package/dist/local-executor/__tests__/promote-wal-store.test.d.ts +1 -0
- package/dist/local-executor/__tests__/revert-reconcile.test.d.ts +1 -0
- package/dist/local-executor/__tests__/revert-runner.test.d.ts +1 -0
- package/dist/local-executor/__tests__/shared-contract-detector.test.d.ts +1 -0
- package/dist/local-executor/__tests__/substrate-engage.test.d.ts +1 -0
- package/dist/local-executor/__tests__/team-execution-flag.test.d.ts +1 -0
- package/dist/local-executor/__tests__/track-registry.test.d.ts +1 -0
- package/dist/local-executor/__tests__/wb2-review-bundle.test.d.ts +1 -0
- package/dist/local-executor/__tests__/wb2-substrate-spawn.live.test.d.ts +1 -0
- package/dist/local-executor/__tests__/workspace-shadow.test.d.ts +1 -0
- package/dist/local-executor/__tests__/worktree-merge.test.d.ts +1 -0
- package/dist/local-executor/agentic-disposable-repo.d.ts +52 -0
- package/dist/local-executor/agentic-resolve.d.ts +54 -0
- package/dist/local-executor/agentic-resolver-flag.d.ts +9 -0
- package/dist/local-executor/authority.d.ts +33 -1
- package/dist/local-executor/class-a-emit.d.ts +3 -1
- package/dist/local-executor/class-a-sign.d.ts +57 -0
- package/dist/local-executor/class-b-consumer.d.ts +159 -4
- package/dist/local-executor/class-b-verify.d.ts +30 -0
- package/dist/local-executor/class1-reconcilers.d.ts +58 -0
- package/dist/local-executor/class2-resolver.d.ts +74 -0
- package/dist/local-executor/confined-model-caller.d.ts +39 -0
- package/dist/local-executor/conflict-classifier.d.ts +21 -0
- package/dist/local-executor/conflict-resolution-durable-store.d.ts +61 -0
- package/dist/local-executor/conflict-resolution-store.d.ts +210 -0
- package/dist/local-executor/conflict-types.d.ts +86 -0
- package/dist/local-executor/cp7-audit-writer.d.ts +152 -0
- package/dist/local-executor/durable-store.d.ts +334 -0
- package/dist/local-executor/git-lock-retry.d.ts +40 -0
- package/dist/local-executor/hook-bridge.d.ts +1 -1
- package/dist/local-executor/implementor-argv.d.ts +183 -0
- package/dist/local-executor/index.d.ts +44 -3
- package/dist/local-executor/local-executor-impl.d.ts +645 -4
- package/dist/local-executor/merge-conflict-extract.d.ts +34 -0
- package/dist/local-executor/merge-conflict-resolve.d.ts +101 -0
- package/dist/local-executor/merge-journal-store.d.ts +311 -0
- package/dist/local-executor/merge-train.d.ts +713 -0
- package/dist/local-executor/promote-wal-store.d.ts +301 -0
- package/dist/local-executor/resolution-set-index.d.ts +51 -0
- package/dist/local-executor/revert-reconcile.d.ts +89 -0
- package/dist/local-executor/revert-runner.d.ts +17 -0
- package/dist/local-executor/shared-contract-detector.d.ts +57 -0
- package/dist/local-executor/spawn.d.ts +29 -1
- package/dist/local-executor/task-group-types.d.ts +346 -0
- package/dist/local-executor/team-execution-flag.d.ts +21 -0
- package/dist/local-executor/track-registry.d.ts +50 -0
- package/dist/local-executor/types.d.ts +238 -4
- package/dist/local-executor/wb2-review-bundle.d.ts +59 -0
- package/dist/local-executor/workspace-shadow.d.ts +290 -0
- package/dist/local-executor/worktree-merge.d.ts +601 -0
- package/dist/local-model/__tests__/installer.test.d.ts +1 -0
- package/dist/local-model/__tests__/manager.test.d.ts +1 -0
- package/dist/local-model/__tests__/ollama.test.d.ts +1 -0
- package/dist/local-model/__tests__/runtime.test.d.ts +1 -0
- package/dist/local-model/__tests__/state.test.d.ts +1 -0
- package/dist/local-model/manager.d.ts +119 -0
- package/dist/local-model/ollama.d.ts +27 -0
- package/dist/local-model/runtime.d.ts +27 -0
- package/dist/local-model/state.d.ts +32 -0
- package/dist/orchestration/detect-agents.d.ts +15 -2
- package/dist/orchestration/setup-types.d.ts +2 -1
- package/dist/orchestration-shell/__tests__/attachments.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/audit-browser.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/audited-path-fixes.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/bracketed-paste.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-group-halt-wiring.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-orchestration-session-bootstrap.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-probe-group-status.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-quorum-loop-tier.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-verdict-classifier-wiring.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/context-store.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp10-585-accept-echo-target.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp10-585-loop.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp10-585-prompts.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp12-w2b-team-loop.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp12-w4-team-recovery.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp1f-quorum-loop.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp606-team-track-user-resolved.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cp7-reviewer-substrate.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/declared-test-runner.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/familiarize-routing.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/gate-decision-submit.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/gate-details-panel.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/gate-verdict-details-dispatch.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/group-decision-submit.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/image-attach-e2e.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/input-bar-autocomplete.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/live-region-cap.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/live-static-order.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/model-cli.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/non-gate-prompt-routing.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/orchestration-app-group-decision-transport.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/orchestration-app-layout.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/reissue-team-retained-spec.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/review-summary-render.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/reviewer-wizard.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/reviewers-format.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/root-discovery.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/serialize-submissions.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/slash-suggest.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/status-format.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/task-progress.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/team-decompose-routing.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/team-decompose-types.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/team-decompose.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/team-e2e-smoke.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/tier2-reviewer-selection.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/web-browsing.test.d.ts +1 -0
- package/dist/orchestration-shell/attachments.d.ts +152 -0
- package/dist/orchestration-shell/audit-browser.d.ts +115 -0
- package/dist/orchestration-shell/audit-runner.d.ts +59 -0
- package/dist/orchestration-shell/bracketed-paste.d.ts +26 -0
- package/dist/orchestration-shell/cli.d.ts +336 -1
- package/dist/orchestration-shell/cli.js +39318 -3436
- package/dist/orchestration-shell/components/AuditLogPanel.d.ts +11 -0
- package/dist/orchestration-shell/components/ConversationPane.d.ts +7 -1
- package/dist/orchestration-shell/components/GateDetailsPanel.d.ts +57 -0
- package/dist/orchestration-shell/components/GatePanelEntry.d.ts +9 -0
- package/dist/orchestration-shell/components/GatePromptEntry.d.ts +7 -0
- package/dist/orchestration-shell/components/InputBar.d.ts +17 -3
- package/dist/orchestration-shell/components/LiveProgressLine.d.ts +8 -0
- package/dist/orchestration-shell/components/MultiTrackStatusNode.d.ts +8 -0
- package/dist/orchestration-shell/components/OrchestrationApp.d.ts +81 -15
- package/dist/orchestration-shell/components/ReviewerSetupWizard.d.ts +24 -0
- package/dist/orchestration-shell/components/StatusBar.d.ts +15 -2
- package/dist/orchestration-shell/context-store.d.ts +389 -0
- package/dist/orchestration-shell/declared-test-runner.d.ts +84 -0
- package/dist/orchestration-shell/emit-shell-event.d.ts +1 -1
- package/dist/orchestration-shell/gate-decision-submit.d.ts +245 -0
- package/dist/orchestration-shell/gate-prompts.d.ts +361 -3
- package/dist/orchestration-shell/index.d.ts +613 -1
- package/dist/orchestration-shell/ink-runtime.d.ts +21 -1
- package/dist/orchestration-shell/live-region-cap.d.ts +70 -0
- package/dist/orchestration-shell/live-static-order.d.ts +22 -0
- package/dist/orchestration-shell/non-tty-fallback.d.ts +21 -0
- package/dist/orchestration-shell/quorum-loop.d.ts +1900 -0
- package/dist/orchestration-shell/root-discovery.d.ts +25 -0
- package/dist/orchestration-shell/route-browse.d.ts +20 -0
- package/dist/orchestration-shell/slash-router.d.ts +20 -1
- package/dist/orchestration-shell/slash-routes/continuation.d.ts +71 -0
- package/dist/orchestration-shell/slash-routes/reviewers.d.ts +41 -0
- package/dist/orchestration-shell/slash-suggest.d.ts +29 -0
- package/dist/orchestration-shell/status-format.d.ts +59 -0
- package/dist/orchestration-shell/task-progress.d.ts +122 -0
- package/dist/orchestration-shell/team-decompose.d.ts +196 -0
- package/dist/orchestration-shell/types.d.ts +363 -3
- package/dist/orchestration-shell/vendor/ink-parse-keypress.d.ts +42 -0
- package/dist/orchestration-shell/web/extract.d.ts +11 -0
- package/dist/orchestration-shell/web/fetch.d.ts +15 -0
- package/dist/orchestration-shell/web/ip.d.ts +26 -0
- package/dist/orchestration-shell/web/sanitize.d.ts +14 -0
- package/dist/orchestration-shell/web/search.d.ts +16 -0
- package/dist/planner/__tests__/local-gemma.test.d.ts +1 -0
- package/dist/planner/index.d.ts +2 -0
- package/dist/planner/local-advisory.d.ts +84 -0
- package/dist/planner/local-gemma.d.ts +23 -0
- package/dist/planner/types.d.ts +16 -6
- package/dist/reviewer/__tests__/antigravity-provider.test.d.ts +1 -0
- package/dist/reviewer/__tests__/claude-provider-json.test.d.ts +1 -0
- package/dist/reviewer/__tests__/cp7-reviewer-sandbox.test.d.ts +1 -0
- package/dist/reviewer/__tests__/output-parser-classifier-helpers.test.d.ts +1 -0
- package/dist/reviewer/__tests__/verdict-classifier.test.d.ts +1 -0
- package/dist/reviewer/index.d.ts +2 -0
- package/dist/reviewer/output-parser.d.ts +48 -12
- package/dist/reviewer/provider.d.ts +107 -3
- package/dist/reviewer/providers/__tests__/failure-classifier.test.d.ts +1 -0
- package/dist/reviewer/providers/antigravity.d.ts +49 -0
- package/dist/reviewer/providers/claude.d.ts +19 -4
- package/dist/reviewer/providers/codex.d.ts +47 -5
- package/dist/reviewer/providers/failure-classifier.d.ts +26 -0
- package/dist/reviewer/providers/gemini.d.ts +5 -4
- package/dist/reviewer/registry.d.ts +5 -5
- package/dist/reviewer/subprocess.d.ts +37 -0
- package/dist/reviewer/token-usage.d.ts +32 -0
- package/dist/reviewer/types.d.ts +5 -5
- package/dist/reviewer/verdict-classifier.d.ts +62 -0
- package/dist/session/__tests__/prepare-event-timestamp.test.d.ts +1 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/prepare-event-timestamp.d.ts +30 -0
- package/dist/substrate/__tests__/docker.test.d.ts +1 -0
- package/dist/substrate/__tests__/forwarder.test.d.ts +1 -0
- package/dist/substrate/__tests__/git-proxy.test.d.ts +1 -0
- package/dist/substrate/__tests__/sandbox-exec.test.d.ts +1 -0
- package/dist/substrate/__tests__/substrate-e2e.integration.test.d.ts +1 -0
- package/dist/substrate/command-runner.d.ts +19 -0
- package/dist/substrate/docker.d.ts +134 -0
- package/dist/substrate/errors.d.ts +33 -0
- package/dist/substrate/forwarder.d.ts +67 -0
- package/dist/substrate/git-proxy.d.ts +35 -0
- package/dist/substrate/index.d.ts +12 -0
- package/dist/substrate/relay-script.d.ts +27 -0
- package/dist/substrate/sandbox-exec.d.ts +116 -0
- package/dist/substrate/types.d.ts +218 -0
- package/dist/substrate-launch/__tests__/apikey-bootstrap.test.d.ts +1 -0
- package/dist/substrate-launch/__tests__/creditless-loop.integration.test.d.ts +1 -0
- package/dist/substrate-launch/__tests__/engage-substrate.test.d.ts +1 -0
- package/dist/substrate-launch/__tests__/fallback-ladder.test.d.ts +1 -0
- package/dist/substrate-launch/__tests__/le-env-scrub.test.d.ts +1 -0
- package/dist/substrate-launch/__tests__/sanitized-env.test.d.ts +1 -0
- package/dist/substrate-launch/apikey-bootstrap.d.ts +84 -0
- package/dist/substrate-launch/engage-substrate.d.ts +102 -0
- package/dist/substrate-launch/fallback-ladder.d.ts +49 -0
- package/dist/substrate-launch/index.d.ts +12 -0
- package/dist/substrate-launch/le-env-scrub.d.ts +77 -0
- package/dist/substrate-launch/sanitized-env.d.ts +73 -0
- package/dist/types/auth.d.ts +6 -1
- package/dist/types/events.d.ts +3 -1
- package/dist/types/reviewer.d.ts +6 -6
- package/package.json +7 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type ReviewerProvider, type ReviewerSpec } from '../provider.js';
|
|
1
|
+
import { type ReviewerEvaluateOptions, type ReviewerProvider, type ReviewerSpec } from '../provider.js';
|
|
2
2
|
import { type SubprocessOutcome } from '../subprocess.js';
|
|
3
3
|
import type { ReviewerVerdict } from '../types.js';
|
|
4
|
+
import { type VerdictClassifier } from '../verdict-classifier.js';
|
|
4
5
|
import type { BuiltCommand } from './claude.js';
|
|
5
6
|
/** Construction options. */
|
|
6
7
|
export interface GeminiReviewerProviderOptions {
|
|
@@ -42,7 +43,7 @@ export interface GeminiModelStats {
|
|
|
42
43
|
export declare class GeminiReviewerProvider implements ReviewerProvider {
|
|
43
44
|
private readonly executable;
|
|
44
45
|
constructor(opts?: GeminiReviewerProviderOptions);
|
|
45
|
-
evaluate(spec: ReviewerSpec, gateId: string): Promise<ReviewerVerdict>;
|
|
46
|
+
evaluate(spec: ReviewerSpec, gateId: string, opts?: ReviewerEvaluateOptions): Promise<ReviewerVerdict>;
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Construct the Gemini CLI invocation. Split out from `evaluate` so unit
|
|
@@ -71,13 +72,13 @@ export declare class GeminiReviewerProvider implements ReviewerProvider {
|
|
|
71
72
|
* session INACTIVE (empirically observed 2026-04-21 during Phase 2c.2
|
|
72
73
|
* local testing).
|
|
73
74
|
*/
|
|
74
|
-
export declare function buildCommand(executable: string, spec: ReviewerSpec): BuiltCommand;
|
|
75
|
+
export declare function buildCommand(executable: string, spec: ReviewerSpec, sandboxed?: boolean): BuiltCommand;
|
|
75
76
|
/**
|
|
76
77
|
* Map the raw subprocess outcome into a `ReviewerVerdict` or throw a
|
|
77
78
|
* structured `ReviewerErrorClass`. See `claude.ts::buildVerdict` for the
|
|
78
79
|
* shared safety rule (non-zero exit overrides any parseable stdout).
|
|
79
80
|
*/
|
|
80
|
-
export declare function buildVerdict(spec: ReviewerSpec, gateId: string, outcome: SubprocessOutcome): ReviewerVerdict
|
|
81
|
+
export declare function buildVerdict(spec: ReviewerSpec, gateId: string, outcome: SubprocessOutcome, classifyVerdict?: VerdictClassifier): Promise<ReviewerVerdict>;
|
|
81
82
|
/**
|
|
82
83
|
* Parse the FIRST complete JSON object in `stdout`, discarding any trailing
|
|
83
84
|
* bytes. User-level hooks (e.g., CodeVibe's own Gemini plugin hooks
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReviewerProvider, type ReviewerSpec } from './provider.js';
|
|
1
|
+
import { type ReviewerEvaluateOptions, type ReviewerProvider, type ReviewerSpec } from './provider.js';
|
|
2
2
|
import type { AgentKind, ReviewerVerdict } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Per-agent reviewer dispatch.
|
|
@@ -62,12 +62,12 @@ export declare class ReviewerRegistry implements ReviewerProvider {
|
|
|
62
62
|
* existing escalation path handles it. The `reason` field includes
|
|
63
63
|
* the agent name so audit can identify the misconfiguration.
|
|
64
64
|
*/
|
|
65
|
-
evaluate(spec: ReviewerSpec, gateId: string): Promise<ReviewerVerdict>;
|
|
65
|
+
evaluate(spec: ReviewerSpec, gateId: string, opts?: ReviewerEvaluateOptions): Promise<ReviewerVerdict>;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Production factory: build a registry pre-populated with all
|
|
69
|
-
* subprocess providers (Claude, Gemini, Codex) using the
|
|
70
|
-
* binaries from PATH. Equivalent of Rust's
|
|
68
|
+
* Production factory: build a registry pre-populated with all four
|
|
69
|
+
* subprocess providers (Claude, Gemini, Codex, Antigravity) using the
|
|
70
|
+
* standard binaries from PATH. Equivalent of Rust's
|
|
71
71
|
* `withSubprocessProviders()` napi factory.
|
|
72
72
|
*
|
|
73
73
|
* Plugins call this once at startup and hand the registry to the
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SubstrateHandle } from '../substrate/types.js';
|
|
1
2
|
/**
|
|
2
3
|
* Successful subprocess run. Exit status may still be failure (non-zero
|
|
3
4
|
* code); the caller decides whether to treat that as a reviewer spawn error
|
|
@@ -72,8 +73,44 @@ export interface RunReviewerOptions {
|
|
|
72
73
|
* primary plugin session. Each provider is responsible for setting it;
|
|
73
74
|
* this module does NOT inject it automatically because providers may
|
|
74
75
|
* also need to forward `process.env` selectively.
|
|
76
|
+
*
|
|
77
|
+
* # CP-7 §8 (Stage-1-resolved) — IGNORED on the substrate path
|
|
78
|
+
*
|
|
79
|
+
* `env` applies ONLY to the LEGACY (no-`substrate`) path, where it is
|
|
80
|
+
* passed verbatim to `child_process.spawn`. When `substrate` is supplied
|
|
81
|
+
* the child is obtained via `SubstrateHandle.exec(argv, …)`, whose env is
|
|
82
|
+
* PRE-BAKED at `substrate.launch()` time (the I1 allow-list `sanitizedEnv`
|
|
83
|
+
* with the broker base-URL redirect, NO vendor key) — `exec()` takes no
|
|
84
|
+
* env parameter by contract (`substrate/types.ts:138`). So this field is
|
|
85
|
+
* deliberately UNUSED on the substrate path: that is the moat invariant —
|
|
86
|
+
* a sandboxed reviewer MUST NOT inherit ANY ambient credential, and the
|
|
87
|
+
* provider's `{...process.env}` spread (the historic moat hole) never
|
|
88
|
+
* reaches the child because we do not honor `env` here. See the per-agent
|
|
89
|
+
* providers' `buildCommand` which drops the `process.env` spread for the
|
|
90
|
+
* substrate path. The `QUORUM_REVIEWER_SUBPROCESS` marker is folded into
|
|
91
|
+
* the substrate's sanitizedEnv at launch (the same way the implementor's
|
|
92
|
+
* §3.6 markers are), not via this field.
|
|
75
93
|
*/
|
|
76
94
|
env: NodeJS.ProcessEnv;
|
|
95
|
+
/**
|
|
96
|
+
* CP-7 §8 (Stage-1-resolved) — OPTIONAL substrate handle. When supplied,
|
|
97
|
+
* the reviewer runs INSIDE the CP-7 trusted-execution sandbox + broker
|
|
98
|
+
* (exactly like a substrate-confined implementor): the child is obtained
|
|
99
|
+
* via `substrate.exec(argv, { stdinTty: true, … })` instead of
|
|
100
|
+
* `child_process.spawn`, so it sees ONLY the pre-baked I1 allow-list env
|
|
101
|
+
* (broker base-URL + bootstrap config dir; NO ambient vendor creds), and
|
|
102
|
+
* its model API call routes through the loopback broker (which injects the
|
|
103
|
+
* vendor key host-side). ABSENT → the LEGACY path (`child_process.spawn`
|
|
104
|
+
* with `env`) runs byte-identical to pre-CP-7-reviewer-sandbox behavior.
|
|
105
|
+
*
|
|
106
|
+
* The §3.1 lifecycle (prompt-write-to-stdin, stdout/stderr capture, the
|
|
107
|
+
* timeout race, abort/signal handling, teardown/kill, the SubprocessOutcome
|
|
108
|
+
* shape) is PRESERVED EXACTLY on both paths — `SubstrateProc` exposes the
|
|
109
|
+
* same `stdin`/`stdout`/`stderr`/`kill`/`on('close'|'error')` surface, so
|
|
110
|
+
* the lifecycle code below is shared; only the child-acquisition step
|
|
111
|
+
* differs.
|
|
112
|
+
*/
|
|
113
|
+
substrate?: SubstrateHandle;
|
|
77
114
|
/** Working directory; falls back to `process.cwd()`. */
|
|
78
115
|
cwd?: string;
|
|
79
116
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [P2-0] Clamp an UNTYPED token field (from agent CLI JSON) to a finite,
|
|
3
|
+
* non-negative INTEGER. Token fields come from untyped agent JSON — a string /
|
|
4
|
+
* object / `NaN` / negative / fractional value would poison the per-task
|
|
5
|
+
* accumulator (→ `NaN` render, or a reopened window showing a LOWER total),
|
|
6
|
+
* violating the "token count is a number" invariant. Every numeric ingress
|
|
7
|
+
* (`unwrapClaudeJson` usage reads, Codex `sumCodexTokens` per-event sum, the
|
|
8
|
+
* QuorumLoop `addTaskTokens`) gates on this, so a malformed field contributes 0,
|
|
9
|
+
* never corrupts the accumulator.
|
|
10
|
+
*/
|
|
11
|
+
export declare function finiteToken(n: unknown): number;
|
|
12
|
+
/**
|
|
13
|
+
* [P2-6] Unwrap a Claude Code `--output-format json` NON-interactive envelope into
|
|
14
|
+
* `{ text, tokens }`. The ENTIRE body is `try/catch`-guarded — ANY throw (parse
|
|
15
|
+
* error, unexpected shape, field-access `TypeError`) degrades to the backward-compat
|
|
16
|
+
* raw-stdout fallback `{ text: stdout, tokens: undefined }`, so adding this unwrap
|
|
17
|
+
* can NEVER break a caller (it reduces to today's raw-stdout behavior).
|
|
18
|
+
*
|
|
19
|
+
* • No `type:'result'` object located / non-JSON → raw fallback (byte-identical
|
|
20
|
+
* to today — the downstream parser sees the raw stdout).
|
|
21
|
+
* • `is_error === true` OR `result` not a non-empty string → `{ text:'', tokens:
|
|
22
|
+
* undefined }`. The CALLER treats an empty/failed result as an agent FAILURE
|
|
23
|
+
* (reviewer ESCALATE / resolver human-gate — same as today), NOT a silent pass.
|
|
24
|
+
* • else → `{ text: result, tokens: (finiteToken(usage.input_tokens) +
|
|
25
|
+
* finiteToken(usage.output_tokens)) || undefined }`. `finiteToken` clamps
|
|
26
|
+
* absent/malformed usage to 0 (no `TypeError`, no `NaN`); cache tokens are
|
|
27
|
+
* excluded in v1 (input+output only — see design "Known v1 limitation").
|
|
28
|
+
*/
|
|
29
|
+
export declare function unwrapClaudeJson(stdout: string): {
|
|
30
|
+
text: string;
|
|
31
|
+
tokens?: number;
|
|
32
|
+
};
|
package/dist/reviewer/types.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Agent kinds the reviewer subprocess layer can spawn.
|
|
3
3
|
*
|
|
4
4
|
* Lowercase wire format matches `codevibe_policy::AgentKind`'s
|
|
5
5
|
* `#[serde(rename_all = "lowercase")]` attribute. **Append-only after launch**
|
|
6
|
-
* —
|
|
7
|
-
* `claude` → `Claude` would break every audit chain entry that has
|
|
8
|
-
* it.
|
|
6
|
+
* — `antigravity` appended per AGY-2.0-SUPPORT-DESIGN.md (Phase A, 2026-07-03);
|
|
7
|
+
* renaming `claude` → `Claude` would break every audit chain entry that has
|
|
8
|
+
* serialised it.
|
|
9
9
|
*/
|
|
10
|
-
export type AgentKind = 'claude' | 'gemini' | 'codex';
|
|
10
|
+
export type AgentKind = 'claude' | 'gemini' | 'codex' | 'antigravity';
|
|
11
11
|
/**
|
|
12
12
|
* Review lens a reviewer seat evaluates through.
|
|
13
13
|
*
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { LocalGemmaPlannerRunner } from '../planner/local-gemma';
|
|
2
|
+
import type { AgentKind, ReviewerRole, VerdictKind } from './types';
|
|
3
|
+
/** Per-verdict context (seat/role/agent) — carried for observability; the Gemma
|
|
4
|
+
* classification itself is context-free (deterministic on `rawText`). */
|
|
5
|
+
export interface VerdictClassifierContext {
|
|
6
|
+
seatId: number;
|
|
7
|
+
role: ReviewerRole;
|
|
8
|
+
agent: AgentKind;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A classifier's resolved decision. `reason` is set ONLY on a fail-closed ESCALATE
|
|
12
|
+
* (a SAFE closed label — never raw model/reviewer text); a genuine reviewer verdict
|
|
13
|
+
* (incl. a genuine ESCALATE the reviewer actually chose) leaves `reason` undefined
|
|
14
|
+
* so the provider keeps the reviewer's own reasoning (D5/MED-C).
|
|
15
|
+
*/
|
|
16
|
+
export interface VerdictClassification {
|
|
17
|
+
verdict: VerdictKind;
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
export type VerdictClassifier = (rawText: string, ctx: VerdictClassifierContext) => Promise<VerdictClassification>;
|
|
21
|
+
/** SAFE closed labels for a fail-closed ESCALATE (D3/D5/MED-C). Never raw text. */
|
|
22
|
+
export declare const VERDICT_CLASSIFIER_UNCERTAIN = "verdict_classifier_uncertain";
|
|
23
|
+
export declare const VERDICT_CLASSIFIER_CONFLICT = "verdict_classifier_conflict";
|
|
24
|
+
export declare const VERDICT_CLASSIFIER_UNAVAILABLE = "verdict_classifier_unavailable";
|
|
25
|
+
/**
|
|
26
|
+
* Build a fail-closed Gemma verdict classifier. Order:
|
|
27
|
+
* (1) empty `rawText.trim()===''` → ESCALATE (no `classify` call);
|
|
28
|
+
* (2) [D2a] conflicting standalone verdicts → ESCALATE (before Gemma);
|
|
29
|
+
* (3) classify (8s race) → validate JSON/enum/`confidence:'high'` per D3;
|
|
30
|
+
* (4) REVISE → require `extractSuggestedChanges(postVerdictReasoning(rawText))`
|
|
31
|
+
* yields ≥1 change (D5), else ESCALATE.
|
|
32
|
+
* Whole body try/catch-wrapped; any throw / timeout → ESCALATE (unavailable).
|
|
33
|
+
* A genuine non-ESCALATE verdict (and a genuine reviewer ESCALATE) returns NO
|
|
34
|
+
* `reason` so the provider keeps the reviewer's own reasoning.
|
|
35
|
+
*/
|
|
36
|
+
export declare function makeGemmaVerdictClassifier(runner: LocalGemmaPlannerRunner, opts?: {
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
}): VerdictClassifier;
|
|
39
|
+
/**
|
|
40
|
+
* A trivial classifier that returns ESCALATE (with a closed `reason` label) for
|
|
41
|
+
* every input, with no runner. Installed by the wiring when flag=`gemma` but the
|
|
42
|
+
* Gemma runner is null at boot (Ollama unreachable) — so `gemma` mode NEVER
|
|
43
|
+
* silently degrades to the regex parser (agy-MED-1).
|
|
44
|
+
*/
|
|
45
|
+
export declare function alwaysEscalateClassifier(reason: string): VerdictClassifier;
|
|
46
|
+
/**
|
|
47
|
+
* [D5] Resolve the `ReviewerVerdict`'s `reasoning` + `suggested_changes` from a
|
|
48
|
+
* classification, shared by all three providers' `buildVerdict` so the safety-
|
|
49
|
+
* critical mapping lives in ONE audited place:
|
|
50
|
+
* - `reasoning`: a fail-closed ESCALATE (has a closed `reason` label) → that
|
|
51
|
+
* label (never raw text, parity with the old `parse_failure`→template); every
|
|
52
|
+
* other verdict (incl. a genuine reviewer ESCALATE, `reason` undefined) → the
|
|
53
|
+
* reviewer's raw text verbatim.
|
|
54
|
+
* - `suggested_changes`: REVISE → `extractSuggestedChanges(postVerdictReasoning(
|
|
55
|
+
* rawText))` (non-empty by construction — the classifier already gated it);
|
|
56
|
+
* every other verdict → `[]`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveClassifiedVerdictFields(classification: VerdictClassification, rawText: string): {
|
|
59
|
+
verdict: VerdictKind;
|
|
60
|
+
reasoning: string;
|
|
61
|
+
suggested_changes: string[];
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/session/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export type { ResumeOrCreateSessionInput, ResumeOrCreateSessionResult } from './
|
|
|
3
3
|
export { rekeySessionForNewDevices } from './session-rekey';
|
|
4
4
|
export { startDeviceKeyWatcher } from './device-key-watcher';
|
|
5
5
|
export { registerDeviceEncryptionKey } from './register-device-key';
|
|
6
|
+
export { prepareEventTimestamp, _resetPrepareEventTimestampForTesting, } from './prepare-event-timestamp';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns an ISO-8601 timestamp with millisecond precision that is
|
|
3
|
+
* STRICTLY GREATER than any previous timestamp returned for the same
|
|
4
|
+
* `orderingKey` within this process.
|
|
5
|
+
*
|
|
6
|
+
* Formula: `Math.max(baseMs, lastMs + 1, floorMs)` where `floorMs` is
|
|
7
|
+
* `notBeforeMs + 1` when a finite `notBeforeMs` is supplied (else 0), and:
|
|
8
|
+
* - baseMs = parsed agentClock if provided (and valid), else Date.now()
|
|
9
|
+
* - lastMs = previously-emitted ms for this orderingKey (or 0 if first)
|
|
10
|
+
*
|
|
11
|
+
* `agentClock` ANCHORS the timestamp when provided. This is the load-bearing
|
|
12
|
+
* behavior for agy's transcript replay: agy emits events with their original
|
|
13
|
+
* `created_at` even during a backfill (so subscription clients see them in
|
|
14
|
+
* logical order, not in replay-arrival order). For hook-driven plugins
|
|
15
|
+
* (claude/codex/gemini), `agentClock` is left undefined and baseMs = wallMs.
|
|
16
|
+
*
|
|
17
|
+
* Memory: bounded LRU with cap=MAX_LRU_KEYS. Eviction order is least-
|
|
18
|
+
* recently-touched, so active orderingKeys are never evicted. Resets on
|
|
19
|
+
* process restart (correct: restart is a new lifecycle).
|
|
20
|
+
*/
|
|
21
|
+
export declare function prepareEventTimestamp(opts: {
|
|
22
|
+
orderingKey: string;
|
|
23
|
+
agentClock?: string;
|
|
24
|
+
notBeforeMs?: number;
|
|
25
|
+
}): string;
|
|
26
|
+
/**
|
|
27
|
+
* Test-only: clear the per-key map. Used by jest/vitest to reset state
|
|
28
|
+
* between tests. Not exported from the package root.
|
|
29
|
+
*/
|
|
30
|
+
export declare function _resetPrepareEventTimestampForTesting(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CommandResult, CommandRunner, RunnerProc } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The production `CommandRunner` — runs `docker` / `sandbox-exec` via
|
|
4
|
+
* `node:child_process`. No shell is used (argv is passed directly to
|
|
5
|
+
* `spawn`), so there is no shell-injection surface from the constructed
|
|
6
|
+
* arguments.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ChildProcessCommandRunner implements CommandRunner {
|
|
9
|
+
run(argv: string[], opts?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
input?: string;
|
|
12
|
+
}): Promise<CommandResult>;
|
|
13
|
+
spawnLong(argv: string[], opts: {
|
|
14
|
+
stdinTty: boolean;
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
env?: Readonly<Record<string, string>>;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}): RunnerProc;
|
|
19
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { type ForwarderFactory } from './forwarder';
|
|
2
|
+
import type { CommandRunner, EgressObservationHook, Substrate, SubstrateHandle, SubstrateSpec } from './types';
|
|
3
|
+
/** Where, inside the container, the worktree is mounted (the agent's cwd/home). */
|
|
4
|
+
export declare const CONTAINER_WORKDIR = "/workspace";
|
|
5
|
+
/** Injectable deps — default-wired to the real runtime; stubbed in unit tests. */
|
|
6
|
+
export interface DockerSubstrateDeps {
|
|
7
|
+
/** Process layer (default: `node:child_process`). Stub in unit tests. */
|
|
8
|
+
runner?: CommandRunner;
|
|
9
|
+
/** Host-side UDS relay factory (default: real `node:net`). */
|
|
10
|
+
forwarderFactory?: ForwarderFactory;
|
|
11
|
+
/** §3.5 observation seam. **W3 wires the emit**; default no-op. */
|
|
12
|
+
onEgressDenied?: EgressObservationHook;
|
|
13
|
+
/** Override the container image (default {@link DEFAULT_IMAGE}). */
|
|
14
|
+
image?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Override the host root for the per-session scratch dir (default:
|
|
17
|
+
* os.tmpdir()). The per-session dir holds ONLY the broker socket (in `uds/`),
|
|
18
|
+
* the relay script, and the scrubbed git-proxy (in `gitproxy/`) — no secrets.
|
|
19
|
+
* The git-proxy now lives UNDER this dir (MED fix), so the one
|
|
20
|
+
* teardown/rollback rm removes it.
|
|
21
|
+
*/
|
|
22
|
+
sessionRoot?: string;
|
|
23
|
+
}
|
|
24
|
+
/** The deterministic per-session container name. */
|
|
25
|
+
export declare function containerName(id: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* The shell-wrapped container entrypoint: start the in-container relay in the
|
|
28
|
+
* background, then hold the container alive for `docker exec`. We MUST wrap in
|
|
29
|
+
* `sh -c` because the relay has to run CONCURRENTLY with the hold (the relay is
|
|
30
|
+
* the broker channel; `exec sleep infinity` keeps the container up for exec).
|
|
31
|
+
* `exec` replaces the shell with sleep so signals (docker kill) propagate.
|
|
32
|
+
*
|
|
33
|
+
* MED fix (Stage-2): the whole `sh -c` runs under `env -i <sanitizedEnv>` so
|
|
34
|
+
* PID1 (and thus everything inheriting from it, including `docker exec`) has
|
|
35
|
+
* EXACTLY `sanitizedEnv` — the image's baked env is wiped. The relay needs
|
|
36
|
+
* Node on PATH; `sanitizedEnv` carries PATH (the allow-list includes it).
|
|
37
|
+
*
|
|
38
|
+
* Exposed for the conformance test (pins the `env -i … sh -c 'node relay.js
|
|
39
|
+
* <port> <sock> & exec sleep infinity'` shape).
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildContainerEntrypoint(sanitizedEnv: Readonly<Record<string, string>>): string[];
|
|
42
|
+
/**
|
|
43
|
+
* `docker run --network none -d` argv. Builds the FULL Option-A isolation
|
|
44
|
+
* surface the conformance test pins:
|
|
45
|
+
* - `--network none` → STRUCTURAL default-deny (only `lo`, no egress).
|
|
46
|
+
* - `-v <workdir>:/workspace` → ONLY the worktree mounted (rw).
|
|
47
|
+
* - `-v <gitProxy>:/workspace/.git:ro` → scrubbed `.git`, read-only (if any).
|
|
48
|
+
* - `-v <relayScript>:/codevibe/relay.js:ro` → the in-container relay (ro).
|
|
49
|
+
* - `-v <udsDir>:/codevibe/broker:rw` → the bind-mounted broker UDS dir (rw,
|
|
50
|
+
* so the container's `connect()` works; the dir holds only the socket).
|
|
51
|
+
* - env via repeated `-e K=V` built EXACTLY from `spec.sanitizedEnv` (no host
|
|
52
|
+
* env passthrough; `docker run` does NOT inherit the host env). MED fix:
|
|
53
|
+
* the `-e` flags ADD to the image's baked env, so the AUTHORITATIVE wipe is
|
|
54
|
+
* the `env -i <sanitizedEnv>` prefix on the entrypoint (PID1) + every exec.
|
|
55
|
+
* - entrypoint: `env -i <sanitizedEnv> sh -c 'node relay.js <port> <sock> &
|
|
56
|
+
* exec sleep infinity'` — PID1's env is EXACTLY sanitizedEnv (MED fix).
|
|
57
|
+
* NO `--add-host`, NO `--network <name>`, NO `--internal`, and NO `-v` for host
|
|
58
|
+
* keychain/home/dotfiles is ever added.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildRunArgv(args: {
|
|
61
|
+
id: string;
|
|
62
|
+
image: string;
|
|
63
|
+
workdir: string;
|
|
64
|
+
gitProxyPath: string | null;
|
|
65
|
+
relayScriptPath: string;
|
|
66
|
+
udsDir: string;
|
|
67
|
+
sanitizedEnv: Readonly<Record<string, string>>;
|
|
68
|
+
/** CP-7 PART D — apiKeyHelper bootstrap mount (`hostDir`→`sandboxDir:ro`). */
|
|
69
|
+
agentBootstrap?: {
|
|
70
|
+
hostDir: string;
|
|
71
|
+
sandboxDir: string;
|
|
72
|
+
};
|
|
73
|
+
}): string[];
|
|
74
|
+
/**
|
|
75
|
+
* `docker exec [-i] <name> env -i <sanitizedEnv> <argv...>` — run the agent
|
|
76
|
+
* inside the live sandbox. MED fix (Stage-2): the `env -i <sanitizedEnv>`
|
|
77
|
+
* prefix clears whatever env `docker exec` would inherit from PID1 / the image
|
|
78
|
+
* and sets EXACTLY `sanitizedEnv`, so the agent env is the SAME set as the A5
|
|
79
|
+
* path (no image `PATH`/baked-env leak). `--env-file`/`-e` on `docker exec`
|
|
80
|
+
* only ADD; `env -i` in the command position is the authoritative wipe.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildExecArgv(id: string, argv: string[], stdinTty: boolean, sanitizedEnv: Readonly<Record<string, string>>): string[];
|
|
83
|
+
/** `docker kill <name>` — teardown step 1. */
|
|
84
|
+
export declare function buildKillArgv(id: string): string[];
|
|
85
|
+
/** `docker rm -f <name>` — teardown step 2 (idempotent via -f). */
|
|
86
|
+
export declare function buildRmArgv(id: string): string[];
|
|
87
|
+
/**
|
|
88
|
+
* A1 Docker substrate (`egressFidelity: 'strict'`, Option A). See file header
|
|
89
|
+
* for the full egress + fs + env contract.
|
|
90
|
+
*/
|
|
91
|
+
export declare class DockerSubstrate implements Substrate {
|
|
92
|
+
private readonly runner;
|
|
93
|
+
private readonly forwarderFactory;
|
|
94
|
+
private readonly onEgressDenied;
|
|
95
|
+
private readonly image;
|
|
96
|
+
private readonly sessionRoot;
|
|
97
|
+
constructor(deps?: DockerSubstrateDeps);
|
|
98
|
+
launch(spec: SubstrateSpec): Promise<SubstrateHandle>;
|
|
99
|
+
private rollback;
|
|
100
|
+
/**
|
|
101
|
+
* r5 HIGH-2 (Codex — NULL-vs-THROW gap). The proxy build produced no usable
|
|
102
|
+
* proxy (it returned `null` OR threw). Decide the safe outcome by whether the
|
|
103
|
+
* workdir actually HAS a `.git`:
|
|
104
|
+
*
|
|
105
|
+
* - NO `<workdir>/.git` → return `null` (a non-git workdir; the
|
|
106
|
+
* `docker run` mounts only the worktree,
|
|
107
|
+
* git reports "not a repository" — no
|
|
108
|
+
* credential surface either way).
|
|
109
|
+
* - `<workdir>/.git` EXISTS → write an EMPTY SCRUBBED `.git` overlay
|
|
110
|
+
* (a dir with ONLY a stripped synthetic
|
|
111
|
+
* `config` — NO remotes/creds/hooks) and
|
|
112
|
+
* return its path, so the `:ro` bind mount
|
|
113
|
+
* SHADOWS the real `.git`. Degraded git
|
|
114
|
+
* reads, but the credential surface is
|
|
115
|
+
* fail-closed.
|
|
116
|
+
* - overlay write ALSO fails → roll back + throw (NEVER mount the
|
|
117
|
+
* worktree with a live `.git`).
|
|
118
|
+
*
|
|
119
|
+
* Used for BOTH the null-return and the throw path so a workdir with a real
|
|
120
|
+
* but unresolvable `.git` can never reach the agent un-shadowed. `fsp.stat`
|
|
121
|
+
* (NOT `lstat`) follows a `.git` that is a symlink/dir/file alike — any of
|
|
122
|
+
* those "exists" cases must be shadowed.
|
|
123
|
+
*/
|
|
124
|
+
private ensureGitOverlayOrFailClosed;
|
|
125
|
+
private assertDockerAvailable;
|
|
126
|
+
}
|
|
127
|
+
export declare const __testing: {
|
|
128
|
+
DEFAULT_IMAGE: string;
|
|
129
|
+
CONTAINER_WORKDIR: string;
|
|
130
|
+
CONTAINER_GIT: string;
|
|
131
|
+
CONTAINER_RELAY_PATH: string;
|
|
132
|
+
CONTAINER_BROKER_DIR: string;
|
|
133
|
+
RELAY_PORT: number;
|
|
134
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by {@link import('./docker').DockerSubstrate.launch} when the Docker
|
|
3
|
+
* CLI/daemon is absent or unusable, and by
|
|
4
|
+
* {@link import('./sandbox-exec').SandboxExecSubstrate.launch} when
|
|
5
|
+
* `sandbox-exec` is unavailable (non-macOS / missing binary).
|
|
6
|
+
*
|
|
7
|
+
* The LE catches this to drive the §6 Q2 fallback ladder. The carried
|
|
8
|
+
* `isolationTech` + `reason` let the LE log/branch precisely; the substrate
|
|
9
|
+
* itself NEVER falls back silently — refusing to run is the safe state.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SubstrateUnavailableError extends Error {
|
|
12
|
+
/** Which backend was unavailable (`docker` / `sandbox_exec`). */
|
|
13
|
+
readonly isolationTech: string;
|
|
14
|
+
/** Human-readable cause (CLI missing, daemon down, non-macOS, …). */
|
|
15
|
+
readonly reason: string;
|
|
16
|
+
constructor(
|
|
17
|
+
/** Which backend was unavailable (`docker` / `sandbox_exec`). */
|
|
18
|
+
isolationTech: string,
|
|
19
|
+
/** Human-readable cause (CLI missing, daemon down, non-macOS, …). */
|
|
20
|
+
reason: string, cause?: unknown);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when a substrate lifecycle step (network create, container run,
|
|
24
|
+
* `docker exec`, profile write) fails for a reason OTHER than the backend
|
|
25
|
+
* being absent — i.e. the backend is present but a command errored. Distinct
|
|
26
|
+
* from {@link SubstrateUnavailableError} so the LE does NOT mistake a transient
|
|
27
|
+
* command failure for "no runtime, fall back to A5."
|
|
28
|
+
*/
|
|
29
|
+
export declare class SubstrateLaunchError extends Error {
|
|
30
|
+
readonly isolationTech: string;
|
|
31
|
+
readonly reason: string;
|
|
32
|
+
constructor(isolationTech: string, reason: string, cause?: unknown);
|
|
33
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { EgressObservationHook } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Construction spec for the host-side UDS relay. The substrate owns one per
|
|
4
|
+
* session.
|
|
5
|
+
*/
|
|
6
|
+
export interface ForwarderSpec {
|
|
7
|
+
/** Orchestration task_id — stamped on every `egress_denied` observation. */
|
|
8
|
+
taskId: string;
|
|
9
|
+
/**
|
|
10
|
+
* The FIXED upstream the relay ALWAYS dials (`spec.hostBrokerAddr`).
|
|
11
|
+
* Agent-supplied targets are ignored — this is the only destination.
|
|
12
|
+
*/
|
|
13
|
+
hostBrokerAddr: string;
|
|
14
|
+
/**
|
|
15
|
+
* The host UDS path the relay LISTENS on (the container bind-mounts this rw
|
|
16
|
+
* and its in-relay dials it). Required for Option A — there is no TCP bind.
|
|
17
|
+
*/
|
|
18
|
+
udsPath: string;
|
|
19
|
+
/** §3.5 observation seam. **W3 wires the emit**; default no-op. */
|
|
20
|
+
onEgressDenied?: EgressObservationHook;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The host-side UDS relay (§3.1, `strict` tier, Option A). Listens on a
|
|
24
|
+
* per-session host Unix-domain socket; every inbound connection is relayed to
|
|
25
|
+
* the single fixed `hostBrokerAddr`. It never reads an agent-supplied
|
|
26
|
+
* destination. A broker-upstream connect failure fires
|
|
27
|
+
* {@link EgressObservationHook} (W3 → `egress_denied`).
|
|
28
|
+
*/
|
|
29
|
+
export declare class HostEgressForwarder {
|
|
30
|
+
private readonly server;
|
|
31
|
+
private readonly upstream;
|
|
32
|
+
private readonly onEgressDenied;
|
|
33
|
+
private readonly taskId;
|
|
34
|
+
private readonly udsPath;
|
|
35
|
+
private listening;
|
|
36
|
+
constructor(spec: ForwarderSpec);
|
|
37
|
+
/**
|
|
38
|
+
* Start listening on the host UDS. Removes any stale socket file at the path
|
|
39
|
+
* first (a crashed prior run can leave one — listen() would EADDRINUSE).
|
|
40
|
+
* Resolves with the UDS path the container dials.
|
|
41
|
+
*/
|
|
42
|
+
start(): Promise<{
|
|
43
|
+
udsPath: string;
|
|
44
|
+
}>;
|
|
45
|
+
/** The host UDS path the container dials (valid after {@link start}). */
|
|
46
|
+
boundAddr(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Idempotent teardown — closes the listener (relayed sockets drop with it)
|
|
49
|
+
* and unlinks the host UDS file so the per-session dir can be removed.
|
|
50
|
+
*/
|
|
51
|
+
stop(): Promise<void>;
|
|
52
|
+
private onConnection;
|
|
53
|
+
private observeDenial;
|
|
54
|
+
/**
|
|
55
|
+
* Directly record a blocked outbound attempt. Under Option A there is no
|
|
56
|
+
* network-observable denied attempt for A1 (the container has no NIC — see
|
|
57
|
+
* the docker.ts §3.5 footnote), so this is STRUCTURALLY UNFIRED for A1. It
|
|
58
|
+
* stays exposed so a future iptables/A5 tier that CAN observe a sandbox→
|
|
59
|
+
* non-broker attempt routes it through the same seam + id minting.
|
|
60
|
+
*/
|
|
61
|
+
recordBlockedDestination(destination: string, denialReason: string): void;
|
|
62
|
+
private safeDestroy;
|
|
63
|
+
}
|
|
64
|
+
/** Factory the substrate uses (injectable so unit tests can stub the relay). */
|
|
65
|
+
export type ForwarderFactory = (spec: ForwarderSpec) => HostEgressForwarder;
|
|
66
|
+
/** Default factory — the real `node:net` UDS relay. */
|
|
67
|
+
export declare const defaultForwarderFactory: ForwarderFactory;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal synthetic `config` written into the proxy. Repository-format
|
|
3
|
+
* version + bare=false ONLY — explicitly NO `[remote ...]`, NO `[credential]`,
|
|
4
|
+
* NO `core.hooksPath`, NO `[user]` (which could carry a signing key path). This
|
|
5
|
+
* is the credential-scrub: the real repo's config never enters the sandbox.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SCRUBBED_CONFIG: string;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the real parent `.git` directory for a worktree. In a worktree the
|
|
10
|
+
* `<workdir>/.git` is a FILE: `gitdir: /abs/path/to/parent/.git/worktrees/<n>`.
|
|
11
|
+
* The commit objects live in the parent repo's top-level `.git` (i.e. two
|
|
12
|
+
* levels up from `worktrees/<n>`). For a NON-worktree checkout `<workdir>/.git`
|
|
13
|
+
* is already the real dir. Returns the directory that holds `objects/` +
|
|
14
|
+
* `refs/`.
|
|
15
|
+
*
|
|
16
|
+
* @returns the resolved real git-common-dir, or `null` if `<workdir>/.git` is
|
|
17
|
+
* absent/unreadable (the caller skips proxying — a non-git workdir is fine).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveGitCommonDir(workdir: string): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Build a read-only, credential-scrubbed `.git` proxy at `destDir` from the
|
|
22
|
+
* resolved git-common-dir. **[W2-min]** — copies only {@link COPIED_GIT_ENTRIES}
|
|
23
|
+
* + a synthetic stripped {@link SCRUBBED_CONFIG}; NO remotes/creds/hooks/reflog.
|
|
24
|
+
*
|
|
25
|
+
* The substrate bind-mounts `destDir` READ-ONLY into the sandbox at
|
|
26
|
+
* `<workdir>/.git`. Returns the proxy path on success, or `null` if `workdir`
|
|
27
|
+
* is not a resolvable git checkout (the substrate then mounts only the worktree
|
|
28
|
+
* with no `.git`, and git read commands simply report "not a repository" — no
|
|
29
|
+
* ambient exposure either way).
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildScrubbedGitProxy(workdir: string, destDir: string): Promise<string | null>;
|
|
32
|
+
export declare const __testing: {
|
|
33
|
+
COPIED_GIT_ENTRIES: readonly ["HEAD", "refs", "packed-refs", "objects"];
|
|
34
|
+
SCRUBBED_CONFIG: string;
|
|
35
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { IsolationTech, EgressFidelity, SubstrateSpec, SubstrateProc, SubstrateHandle, Substrate, EgressDenialDetail, EgressObservationHook, CommandResult, CommandRunner, RunnerProc, } from "./types";
|
|
2
|
+
export { NOOP_EGRESS_HOOK } from "./types";
|
|
3
|
+
export { DockerSubstrate } from "./docker";
|
|
4
|
+
export type { DockerSubstrateDeps } from "./docker";
|
|
5
|
+
export { SandboxExecSubstrate, buildSeatbeltProfile } from "./sandbox-exec";
|
|
6
|
+
export type { SandboxExecDeps } from "./sandbox-exec";
|
|
7
|
+
export { SubstrateUnavailableError, SubstrateLaunchError } from "./errors";
|
|
8
|
+
export { ChildProcessCommandRunner } from "./command-runner";
|
|
9
|
+
export { HostEgressForwarder, defaultForwarderFactory } from "./forwarder";
|
|
10
|
+
export type { ForwarderSpec, ForwarderFactory } from "./forwarder";
|
|
11
|
+
export { buildScrubbedGitProxy, resolveGitCommonDir } from "./git-proxy";
|
|
12
|
+
export { IN_CONTAINER_RELAY_SOURCE, CONTAINER_RELAY_PATH, CONTAINER_BROKER_DIR, CONTAINER_BROKER_SOCK, BROKER_SOCK_NAME, RELAY_PORT, } from "./relay-script";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The in-container relay source. argv: `node relay.js <port> <udsPath>`.
|
|
3
|
+
* - `<port>` : the loopback TCP port the agent dials (container namespace).
|
|
4
|
+
* - `<udsPath>`: the bind-mounted host UDS the bytes are forwarded to.
|
|
5
|
+
*
|
|
6
|
+
* `net.createServer` on `127.0.0.1:<port>` → `net.connect(<udsPath>)` → pipe
|
|
7
|
+
* both ways. A per-connection UDS-connect failure drops only that connection
|
|
8
|
+
* (the agent retries); a listen failure exits non-zero so the wrapper's hold
|
|
9
|
+
* surfaces it. Bound to `127.0.0.1` explicitly so it never binds a routable
|
|
10
|
+
* interface (there is none under `--network none`, but this is belt-and-braces).
|
|
11
|
+
*/
|
|
12
|
+
export declare const IN_CONTAINER_RELAY_SOURCE = "'use strict';\n// CP-7 A1 in-container relay (loopback TCP -> bind-mounted host UDS).\nconst net = require('net');\nconst port = Number(process.argv[2]);\nconst udsPath = process.argv[3];\nif (!Number.isInteger(port) || port <= 0 || port > 65535 || !udsPath) {\n console.error('relay: usage: node relay.js <port> <udsPath>');\n process.exit(2);\n}\nconst server = net.createServer((client) => {\n // Single hard-wired upstream: the bind-mounted host UDS. No agent-supplied\n // destination is ever read \u2014 this relay forwards loopback bytes to the UDS only.\n const up = net.connect(udsPath);\n const drop = () => { try { client.destroy(); } catch (e) {} try { up.destroy(); } catch (e) {} };\n up.on('connect', () => { client.pipe(up); up.pipe(client); });\n up.on('error', drop);\n client.on('error', drop);\n});\nserver.on('error', (err) => {\n console.error('relay: listen failed: ' + (err && err.message));\n process.exit(1);\n});\nserver.listen(port, '127.0.0.1', () => {\n console.error('relay: listening on 127.0.0.1:' + port + ' -> ' + udsPath);\n});\n";
|
|
13
|
+
/** The in-container path the relay script is bind-mounted (read-only) to. */
|
|
14
|
+
export declare const CONTAINER_RELAY_PATH = "/codevibe/relay.js";
|
|
15
|
+
/** The in-container directory the host UDS dir is bind-mounted (rw) to. */
|
|
16
|
+
export declare const CONTAINER_BROKER_DIR = "/codevibe/broker";
|
|
17
|
+
/** The UDS filename inside the broker dir (host + container agree on this). */
|
|
18
|
+
export declare const BROKER_SOCK_NAME = "broker.sock";
|
|
19
|
+
/** The in-container UDS path the relay forwards to. */
|
|
20
|
+
export declare const CONTAINER_BROKER_SOCK = "/codevibe/broker/broker.sock";
|
|
21
|
+
/**
|
|
22
|
+
* The FIXED loopback port the in-container relay listens on, and the port the
|
|
23
|
+
* agent dials via `sandboxBrokerUrl = http://127.0.0.1:<port>`. The container
|
|
24
|
+
* has its OWN net namespace under `--network none`, so a fixed port never
|
|
25
|
+
* collides with anything on the host. 8787 is arbitrary-but-stable.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RELAY_PORT = 8787;
|