@quantiya/codevibe-core 2.0.0 → 2.0.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/dist/__tests__/cp-5-baseline-invariants.test.d.ts +1 -0
- package/dist/adapter/__tests__/capabilities.test.d.ts +1 -0
- package/dist/adapter/__tests__/contract-conformance.test.d.ts +1 -0
- package/dist/adapter/__tests__/packets.test.d.ts +1 -0
- package/dist/adapter/__tests__/progress.test.d.ts +1 -0
- package/dist/adapter/__tests__/registry.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/claude.smoke.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/codex.smoke.test.d.ts +1 -0
- package/dist/adapter/__tests__/smoke/gemini.smoke.test.d.ts +1 -0
- package/dist/adapter/capabilities.d.ts +68 -0
- package/dist/adapter/index.d.ts +7 -0
- package/dist/adapter/packets.d.ts +129 -0
- package/dist/adapter/progress.d.ts +93 -0
- package/dist/adapter/registry.d.ts +24 -0
- package/dist/adapter/types.d.ts +22 -0
- package/dist/appsync/__tests__/appsync-client-apply-user-decision.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client-classb.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client-planner.test.d.ts +1 -0
- package/dist/appsync/__tests__/appsync-client.test.d.ts +1 -0
- package/dist/appsync/appsync-client.d.ts +412 -0
- package/dist/appsync/index.d.ts +1 -1
- package/dist/appsync/queries.d.ts +15 -0
- package/dist/auth/__tests__/auth-telemetry.test.d.ts +1 -0
- package/dist/auth/auth-telemetry.d.ts +98 -5
- package/dist/companion-mode/__tests__/persist-preference.test.d.ts +1 -0
- package/dist/companion-mode/__tests__/resolve-agent.test.d.ts +1 -0
- package/dist/companion-mode/agent-picker.d.ts +9 -0
- package/dist/companion-mode/index.d.ts +55 -0
- package/dist/companion-mode/persist-preference.d.ts +24 -0
- package/dist/companion-mode/resolve-agent.d.ts +41 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.js +243 -42
- package/dist/keychain/keychain-manager.d.ts +16 -2
- package/dist/local-executor/__tests__/authority-symlink-fixture.d.ts +15 -0
- package/dist/local-executor/__tests__/authority.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-a-emit.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-b-consumer.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/class-b-consumer.test.d.ts +1 -0
- package/dist/local-executor/__tests__/hook-bridge.test.d.ts +1 -0
- package/dist/local-executor/__tests__/local-executor.integration.test.d.ts +1 -0
- package/dist/local-executor/__tests__/spawn.test.d.ts +1 -0
- package/dist/local-executor/__tests__/verification-runner.test.d.ts +1 -0
- package/dist/local-executor/authority.d.ts +29 -0
- package/dist/local-executor/class-a-emit.d.ts +138 -0
- package/dist/local-executor/class-b-consumer.d.ts +121 -0
- package/dist/local-executor/hook-bridge.d.ts +36 -0
- package/dist/local-executor/index.d.ts +8 -0
- package/dist/local-executor/local-executor-impl.d.ts +83 -0
- package/dist/local-executor/spawn.d.ts +6 -0
- package/dist/local-executor/types.d.ts +183 -0
- package/dist/local-executor/verification-gates/build.d.ts +6 -0
- package/dist/local-executor/verification-gates/deploy-preflight.d.ts +6 -0
- package/dist/local-executor/verification-gates/diff-sanity.d.ts +6 -0
- package/dist/local-executor/verification-gates/hostile-grep.d.ts +6 -0
- package/dist/local-executor/verification-gates/lint.d.ts +6 -0
- package/dist/local-executor/verification-gates/shell-runner.d.ts +40 -0
- package/dist/local-executor/verification-gates/source-traceability.d.ts +6 -0
- package/dist/local-executor/verification-gates/tests.d.ts +6 -0
- package/dist/local-executor/verification-gates/typecheck.d.ts +6 -0
- package/dist/local-executor/verification-runner.d.ts +28 -0
- package/dist/orchestration/__tests__/setup-bootstrap.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-failure-recourse.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-save.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-seat-picker.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-telemetry.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-test-agents.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-types.test.d.ts +1 -0
- package/dist/orchestration/__tests__/setup-wizard.test.d.ts +1 -0
- package/dist/orchestration/__tests__/v1-options.test.d.ts +1 -0
- package/dist/orchestration/detect-agents.d.ts +2 -1
- package/dist/orchestration/index.d.ts +1 -0
- package/dist/orchestration/orchestration-cli.d.ts +4 -1
- package/dist/orchestration/setup-bootstrap.d.ts +146 -0
- package/dist/orchestration/setup-failure-recourse.d.ts +23 -0
- package/dist/orchestration/setup-save.d.ts +47 -0
- package/dist/orchestration/setup-seat-picker.d.ts +72 -0
- package/dist/orchestration/setup-telemetry.d.ts +54 -0
- package/dist/orchestration/setup-test-agents.d.ts +108 -0
- package/dist/orchestration/setup-types.d.ts +140 -0
- package/dist/orchestration/setup-wizard.d.ts +57 -0
- package/dist/orchestration/v1-options.d.ts +97 -0
- package/dist/orchestration-shell/__tests__/cli-authority-bridge.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-planner-stack.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-singleton-enforcement.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/cli-stub-session-adapter.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/components.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/emit-shell-event.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/gate-prompts.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/hostile-grep.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/mode-selection.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/process-markers.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/reducer.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-classify-dispatch.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-planner-wiring.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell-signal.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/runOrchestrationShell.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/slash-router.test.d.ts +1 -0
- package/dist/orchestration-shell/__tests__/sticky-preference.test.d.ts +1 -0
- package/dist/orchestration-shell/cli.d.ts +96 -0
- package/dist/orchestration-shell/cli.js +8309 -0
- package/dist/orchestration-shell/cohort-flag.d.ts +16 -0
- package/dist/orchestration-shell/components/CodeVibeLogo.d.ts +2 -0
- package/dist/orchestration-shell/components/ConversationPane.d.ts +7 -0
- package/dist/orchestration-shell/components/GatePromptEntry.d.ts +9 -0
- package/dist/orchestration-shell/components/InputBar.d.ts +41 -0
- package/dist/orchestration-shell/components/OrchestrationApp.d.ts +63 -0
- package/dist/orchestration-shell/components/StatusBar.d.ts +7 -0
- package/dist/orchestration-shell/components/nodes/AdvisoryEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/GateStatusNode.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/PlannerDecisionEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/ReviewerQuorumStatusNode.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/SlashOutputEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/SubagentEventEntry.d.ts +8 -0
- package/dist/orchestration-shell/components/nodes/UserMessageEntry.d.ts +8 -0
- package/dist/orchestration-shell/emit-shell-event.d.ts +64 -0
- package/dist/orchestration-shell/gate-prompts.d.ts +123 -0
- package/dist/orchestration-shell/index.d.ts +100 -0
- package/dist/orchestration-shell/ink-runtime.d.ts +64 -0
- package/dist/orchestration-shell/mode-selection.d.ts +46 -0
- package/dist/orchestration-shell/non-tty-fallback.d.ts +46 -0
- package/dist/orchestration-shell/process-markers.d.ts +12 -0
- package/dist/orchestration-shell/reducer.d.ts +8 -0
- package/dist/orchestration-shell/slash-router.d.ts +45 -0
- package/dist/orchestration-shell/sticky-preference.d.ts +24 -0
- package/dist/orchestration-shell/store.d.ts +17 -0
- package/dist/orchestration-shell/types.d.ts +417 -0
- package/dist/planner/__tests__/cache-clarification-bypass.test.d.ts +1 -0
- package/dist/planner/__tests__/cache.test.d.ts +1 -0
- package/dist/planner/__tests__/client.test.d.ts +1 -0
- package/dist/planner/__tests__/health-machine-transitions.test.d.ts +1 -0
- package/dist/planner/__tests__/types-zod.test.d.ts +1 -0
- package/dist/planner/adapter.d.ts +16 -0
- package/dist/planner/cache.d.ts +35 -0
- package/dist/planner/client.d.ts +103 -0
- package/dist/planner/health-state.d.ts +24 -0
- package/dist/planner/index.d.ts +5 -0
- package/dist/planner/types.d.ts +113 -0
- package/dist/session/__tests__/session-resume-service-keys.test.d.ts +1 -0
- package/dist/session/session-rekey.d.ts +40 -0
- package/dist/session/session-resume.d.ts +25 -0
- package/dist/structural-summary/__tests__/__fixtures__/fixture-helpers.d.ts +11 -0
- package/dist/structural-summary/__tests__/assembler.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/generator.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/language-detect.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/cargo.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/gomod.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/gradle.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/index.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/npm.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/podfile.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/manifest-parsers/pyproject.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/opt-in-store.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/privacy-filter.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/safe-file-read.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/user-ignore-matcher.test.d.ts +1 -0
- package/dist/structural-summary/__tests__/walker.test.d.ts +1 -0
- package/dist/structural-summary/generator.d.ts +8 -0
- package/dist/structural-summary/index.d.ts +7 -0
- package/dist/structural-summary/manifest-parsers/cargo.d.ts +3 -0
- package/dist/structural-summary/manifest-parsers/index.d.ts +7 -0
- package/dist/structural-summary/manifest-parsers/npm.d.ts +3 -0
- package/dist/structural-summary/manifest-parsers/other.d.ts +17 -0
- package/dist/structural-summary/opt-in-store.d.ts +24 -0
- package/dist/structural-summary/privacy-filter.d.ts +110 -0
- package/dist/structural-summary/safe-file-read.d.ts +11 -0
- package/dist/structural-summary/types.d.ts +215 -0
- package/dist/structural-summary/user-ignore-matcher.d.ts +9 -0
- package/dist/structural-summary/walker.d.ts +20 -0
- package/dist/types/events.d.ts +17 -2
- package/package.json +17 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { PlannerInput, PlannerDecision, PlannerProbeResult, Tier } from './types';
|
|
2
|
+
import type { PlannerAdapter } from './adapter';
|
|
3
|
+
import type { PlannerCacheLayer } from './cache';
|
|
4
|
+
import type { PlannerHealthMachine } from './health-state';
|
|
5
|
+
/**
|
|
6
|
+
* AppSync transport interface. Minimal shape so unit tests can inject
|
|
7
|
+
* a stub without mounting the full @quantiya/codevibe-core AppSyncClient.
|
|
8
|
+
*/
|
|
9
|
+
export interface PlannerAppSyncTransport {
|
|
10
|
+
classifyPlannerPrompt(input: {
|
|
11
|
+
sessionId: string;
|
|
12
|
+
prompt: string;
|
|
13
|
+
clarifications: string;
|
|
14
|
+
sessionContext: string;
|
|
15
|
+
budgetHint: string;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
decision: string;
|
|
18
|
+
cacheHit: boolean;
|
|
19
|
+
cacheKind: string | null;
|
|
20
|
+
serverLatencyMs: number;
|
|
21
|
+
providerUsed: string;
|
|
22
|
+
}>;
|
|
23
|
+
pingPlanner(input: {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
ok: boolean;
|
|
27
|
+
ms: number;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Crypto bridge — `encryptString` + `encryptJson` + `decryptJson`
|
|
32
|
+
* variants the adapter needs. Mirrors the existing
|
|
33
|
+
* codevibe-core CryptoService surface; injectable for tests.
|
|
34
|
+
*/
|
|
35
|
+
export interface PlannerCryptoBridge {
|
|
36
|
+
/** Encrypt a UTF-8 string to base64 AES-GCM ciphertext. */
|
|
37
|
+
encryptString(plaintext: string, sessionKeyB64: string): string;
|
|
38
|
+
/** Decrypt base64 AES-GCM → UTF-8 string. */
|
|
39
|
+
decryptString(ciphertextB64: string, sessionKeyB64: string): string;
|
|
40
|
+
/** Encrypt JSON-serializable value → base64 ciphertext. */
|
|
41
|
+
encryptJson(obj: unknown, sessionKeyB64: string): string;
|
|
42
|
+
}
|
|
43
|
+
export interface SessionKeyResolver {
|
|
44
|
+
getSessionKey(sessionId: string): Promise<string | null>;
|
|
45
|
+
}
|
|
46
|
+
export interface ShellEventEmit {
|
|
47
|
+
sessionId: string;
|
|
48
|
+
type: 'PLANNER_DECISION' | 'PLANNER_CACHE_HIT' | 'PLANNER_DEGRADED' | 'PLANNER_OUTAGE' | 'PLANNER_RECOVERED';
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
export type EmitShellEventFn = (args: ShellEventEmit) => Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* CP-1.b Stage 2 r2 M-3 — Typed errors that must NOT degrade health.
|
|
54
|
+
*
|
|
55
|
+
* The Lambda surfaces tier-gate / budget rejections as named-error
|
|
56
|
+
* GraphQL responses. Stage 2 r1's catch block recorded EVERY failure
|
|
57
|
+
* as a provider-health failure via `health.recordCall(elapsed, false)`,
|
|
58
|
+
* incorrectly driving the health machine toward Degraded/Outage on
|
|
59
|
+
* what are user-tier policy events (not provider outages). The
|
|
60
|
+
* client now classifies errors and ONLY records provider failures
|
|
61
|
+
* against health; tier/budget rejections emit NOTIFICATION events
|
|
62
|
+
* and throw without touching the machine.
|
|
63
|
+
*/
|
|
64
|
+
export declare class PlannerBudgetExceededError extends Error {
|
|
65
|
+
constructor(msg: string);
|
|
66
|
+
}
|
|
67
|
+
export declare class PlannerTierGateRejectedError extends Error {
|
|
68
|
+
constructor(msg: string);
|
|
69
|
+
}
|
|
70
|
+
export declare class BackendPlannerClient implements PlannerAdapter {
|
|
71
|
+
private transport;
|
|
72
|
+
private cache;
|
|
73
|
+
private health;
|
|
74
|
+
private crypto;
|
|
75
|
+
private sessionKeyResolver;
|
|
76
|
+
private emitShellEvent;
|
|
77
|
+
/** Shell-side tier-change detection (LOCK #30). */
|
|
78
|
+
lastClassifyTier: Tier | null;
|
|
79
|
+
/**
|
|
80
|
+
* CP-1.b Stage 2 r2 M-4 — Active session for probe(). The probe
|
|
81
|
+
* mutation requires a sessionId for ownership check; carrying the
|
|
82
|
+
* session in client state lets callers use the canonical
|
|
83
|
+
* `PlannerAdapter.probe()` contract. Set via `setActiveSession()`
|
|
84
|
+
* by orchestration-shell on session start.
|
|
85
|
+
*/
|
|
86
|
+
private activeSessionId;
|
|
87
|
+
constructor(transport: PlannerAppSyncTransport, cache: PlannerCacheLayer, health: PlannerHealthMachine, crypto: PlannerCryptoBridge, sessionKeyResolver: SessionKeyResolver, emitShellEvent: EmitShellEventFn);
|
|
88
|
+
/**
|
|
89
|
+
* CP-1.b Stage 2 r2 M-4 — Set the active session ID used by
|
|
90
|
+
* `probe()`. Called by the orchestration-shell on session start
|
|
91
|
+
* (and cleared to `null` on session end).
|
|
92
|
+
*/
|
|
93
|
+
setActiveSession(sessionId: string | null): void;
|
|
94
|
+
classify(input: PlannerInput): Promise<PlannerDecision>;
|
|
95
|
+
/**
|
|
96
|
+
* CP-1.b Stage 2 r2 M-4 — Honor the `PlannerAdapter.probe()`
|
|
97
|
+
* contract by reading the session from client state (set via
|
|
98
|
+
* `setActiveSession()`). Stage 2 r1 threw unconditionally and
|
|
99
|
+
* required callers to use the now-removed `probeWithSession()`
|
|
100
|
+
* method, which violated the adapter interface.
|
|
101
|
+
*/
|
|
102
|
+
probe(): Promise<PlannerProbeResult>;
|
|
103
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PlannerHealthState, PlannerHealthTransition } from './types';
|
|
2
|
+
export type { PlannerHealthState, PlannerHealthTransition };
|
|
3
|
+
export declare class PlannerHealthMachine {
|
|
4
|
+
private emitFn;
|
|
5
|
+
state: PlannerHealthState;
|
|
6
|
+
consecutiveFailures: number;
|
|
7
|
+
consecutiveSuccesses: number;
|
|
8
|
+
recentLatenciesMs: number[];
|
|
9
|
+
private readonly URGENT_FAILURE_FOR_DEGRADE;
|
|
10
|
+
private readonly P95_DEGRADE_THRESHOLD_MS;
|
|
11
|
+
private readonly P95_RECOVER_THRESHOLD_MS;
|
|
12
|
+
private readonly DEGRADED_TO_OUTAGE_FAILURES;
|
|
13
|
+
private readonly RECOVER_SUCCESSES_NEEDED;
|
|
14
|
+
private readonly RING_BUFFER_SIZE;
|
|
15
|
+
private readonly DEGRADED_PROBE_INTERVAL_MS;
|
|
16
|
+
private readonly OUTAGE_PROBE_INTERVAL_MS;
|
|
17
|
+
private lastProbeAt;
|
|
18
|
+
constructor(emitFn: (transition: PlannerHealthTransition) => void);
|
|
19
|
+
recordCall(latencyMs: number, success: boolean): PlannerHealthState;
|
|
20
|
+
shouldProbe(): boolean;
|
|
21
|
+
markProbeFired(): void;
|
|
22
|
+
private deriveNextState;
|
|
23
|
+
private p95Of;
|
|
24
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './adapter';
|
|
3
|
+
export { PlannerCacheLayer } from './cache';
|
|
4
|
+
export { PlannerHealthMachine } from './health-state';
|
|
5
|
+
export { BackendPlannerClient, PlannerBudgetExceededError, PlannerTierGateRejectedError, type PlannerAppSyncTransport, type PlannerCryptoBridge, type SessionKeyResolver, type ShellEventEmit, type EmitShellEventFn, } from './client';
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type Tier = 'FREE' | 'PRO' | 'MAX';
|
|
3
|
+
export interface SessionContext {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
tier: Tier;
|
|
7
|
+
currentTaskState: 'none' | 'in_progress' | 'awaiting_user' | 'awaiting_review' | 'merge_gate_pending';
|
|
8
|
+
structuralSummaryDigest: string;
|
|
9
|
+
recentEventCount: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const SessionContextSchema: z.ZodObject<{
|
|
12
|
+
sessionId: z.ZodString;
|
|
13
|
+
userId: z.ZodString;
|
|
14
|
+
tier: z.ZodEnum<["FREE", "PRO", "MAX"]>;
|
|
15
|
+
currentTaskState: z.ZodEnum<["none", "in_progress", "awaiting_user", "awaiting_review", "merge_gate_pending"]>;
|
|
16
|
+
structuralSummaryDigest: z.ZodString;
|
|
17
|
+
recentEventCount: z.ZodNumber;
|
|
18
|
+
}, "strip", z.ZodTypeAny, {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
userId: string;
|
|
21
|
+
structuralSummaryDigest: string;
|
|
22
|
+
tier: "FREE" | "PRO" | "MAX";
|
|
23
|
+
currentTaskState: "none" | "merge_gate_pending" | "in_progress" | "awaiting_user" | "awaiting_review";
|
|
24
|
+
recentEventCount: number;
|
|
25
|
+
}, {
|
|
26
|
+
sessionId: string;
|
|
27
|
+
userId: string;
|
|
28
|
+
structuralSummaryDigest: string;
|
|
29
|
+
tier: "FREE" | "PRO" | "MAX";
|
|
30
|
+
currentTaskState: "none" | "merge_gate_pending" | "in_progress" | "awaiting_user" | "awaiting_review";
|
|
31
|
+
recentEventCount: number;
|
|
32
|
+
}>;
|
|
33
|
+
export interface BudgetHint {
|
|
34
|
+
wallClockMsRemaining: number;
|
|
35
|
+
reviseAttempts: number;
|
|
36
|
+
}
|
|
37
|
+
export declare const BudgetHintSchema: z.ZodObject<{
|
|
38
|
+
wallClockMsRemaining: z.ZodNumber;
|
|
39
|
+
reviseAttempts: z.ZodNumber;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
wallClockMsRemaining: number;
|
|
42
|
+
reviseAttempts: number;
|
|
43
|
+
}, {
|
|
44
|
+
wallClockMsRemaining: number;
|
|
45
|
+
reviseAttempts: number;
|
|
46
|
+
}>;
|
|
47
|
+
export interface Clarification {
|
|
48
|
+
question: string;
|
|
49
|
+
answer: string;
|
|
50
|
+
}
|
|
51
|
+
export declare const ClarificationSchema: z.ZodObject<{
|
|
52
|
+
question: z.ZodString;
|
|
53
|
+
answer: z.ZodString;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
question: string;
|
|
56
|
+
answer: string;
|
|
57
|
+
}, {
|
|
58
|
+
question: string;
|
|
59
|
+
answer: string;
|
|
60
|
+
}>;
|
|
61
|
+
export interface PlannerInput {
|
|
62
|
+
prompt: string;
|
|
63
|
+
clarifications: Clarification[];
|
|
64
|
+
sessionContext: SessionContext;
|
|
65
|
+
budgetHint: BudgetHint;
|
|
66
|
+
}
|
|
67
|
+
export interface PlannerDecision {
|
|
68
|
+
action: 'start_task' | 'summarize_current_status' | 'advisory_response' | 'ask_user' | 'refuse';
|
|
69
|
+
rationale: string;
|
|
70
|
+
clarifying_question?: string;
|
|
71
|
+
advisory_summary?: string;
|
|
72
|
+
/** Opaque per parent §6 lines 967-972; CP-1 NEVER inspects fields. */
|
|
73
|
+
gateRequest?: Record<string, unknown>;
|
|
74
|
+
}
|
|
75
|
+
export declare const PlannerDecisionSchema: z.ZodObject<{
|
|
76
|
+
action: z.ZodEnum<["start_task", "summarize_current_status", "advisory_response", "ask_user", "refuse"]>;
|
|
77
|
+
rationale: z.ZodString;
|
|
78
|
+
clarifying_question: z.ZodOptional<z.ZodString>;
|
|
79
|
+
advisory_summary: z.ZodOptional<z.ZodString>;
|
|
80
|
+
gateRequest: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
action: "start_task" | "summarize_current_status" | "advisory_response" | "ask_user" | "refuse";
|
|
83
|
+
rationale: string;
|
|
84
|
+
clarifying_question?: string | undefined;
|
|
85
|
+
advisory_summary?: string | undefined;
|
|
86
|
+
gateRequest?: Record<string, unknown> | undefined;
|
|
87
|
+
}, {
|
|
88
|
+
action: "start_task" | "summarize_current_status" | "advisory_response" | "ask_user" | "refuse";
|
|
89
|
+
rationale: string;
|
|
90
|
+
clarifying_question?: string | undefined;
|
|
91
|
+
advisory_summary?: string | undefined;
|
|
92
|
+
gateRequest?: Record<string, unknown> | undefined;
|
|
93
|
+
}>;
|
|
94
|
+
export interface PlannerProbeResult {
|
|
95
|
+
ok: boolean;
|
|
96
|
+
latencyMs: number;
|
|
97
|
+
errorClass?: 'timeout' | 'rate_limited' | 'unreachable' | 'malformed_response' | 'auth_failed';
|
|
98
|
+
}
|
|
99
|
+
export type ClassificationKind = 'workflow_status_query' | 'workflow_audit_query' | 'workflow_review_query' | 'workflow_continuation_query' | 'advisory_response_safe' | 'ask_user_clarification';
|
|
100
|
+
export interface CachedClassification {
|
|
101
|
+
kind: ClassificationKind;
|
|
102
|
+
clarifyingQuestion?: string;
|
|
103
|
+
advisorySummary?: string;
|
|
104
|
+
}
|
|
105
|
+
export type PlannerHealthState = 'Available' | 'Degraded' | 'Outage';
|
|
106
|
+
export interface PlannerHealthTransition {
|
|
107
|
+
newState: PlannerHealthState;
|
|
108
|
+
fromState: PlannerHealthState;
|
|
109
|
+
reason: string;
|
|
110
|
+
consecutiveFailures: number;
|
|
111
|
+
consecutiveSuccesses: number;
|
|
112
|
+
p95Ms: number;
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -36,3 +36,43 @@ export interface RekeyOptions {
|
|
|
36
36
|
* @returns The number of new grants that succeeded.
|
|
37
37
|
*/
|
|
38
38
|
export declare function rekeySessionForNewDevices(sessionId: string, sessionKey: string, appSyncClient: AppSyncClient, options?: RekeyOptions): Promise<number>;
|
|
39
|
+
/**
|
|
40
|
+
* Options for {@link awaitOwnSessionKeyGrant}.
|
|
41
|
+
*/
|
|
42
|
+
export interface AwaitOwnGrantOptions {
|
|
43
|
+
/** Poll interval in ms. Default 5000. */
|
|
44
|
+
pollIntervalMs?: number;
|
|
45
|
+
/** Max poll attempts. Default 6 (30s total at 5s intervals). */
|
|
46
|
+
maxAttempts?: number;
|
|
47
|
+
/** Authenticated AppSyncClient. */
|
|
48
|
+
appSyncClient: AppSyncClient;
|
|
49
|
+
/** Fired on successful decrypt. Telemetry-only — never thrown. */
|
|
50
|
+
onSuccess?: (attemptCount: number) => void;
|
|
51
|
+
/** Fired after maxAttempts exhausted. Telemetry-only — never thrown. */
|
|
52
|
+
onTimeout?: (attemptCount: number) => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Wait for this device's deviceId to appear in `session.encryptedKeys`.
|
|
56
|
+
*
|
|
57
|
+
* Triggered when {@link keychainManager.getSessionKey} returned null on
|
|
58
|
+
* resume AND at least one other device IS in encryptedKeys (so some other
|
|
59
|
+
* device can mint a grant for us via grantSessionKey). Caller must have
|
|
60
|
+
* already invoked {@link registerDeviceEncryptionKey} BEFORE this helper —
|
|
61
|
+
* that's what causes mobile's DeviceKeyWatcher subscription to fire and
|
|
62
|
+
* grant the session key to our (possibly rotated) pubKey.
|
|
63
|
+
*
|
|
64
|
+
* This helper deliberately bypasses {@link keychainManager.getSessionKey}
|
|
65
|
+
* (which has a cache short-circuit) and instead:
|
|
66
|
+
* 1. Calls {@link AppSyncClient.getSession} each poll for fresh
|
|
67
|
+
* `encryptedKeys`.
|
|
68
|
+
* 2. Looks for our `deviceId` in the fresh list.
|
|
69
|
+
* 3. If found, calls {@link cryptoService.decryptSessionKey} directly.
|
|
70
|
+
* 4. On success, populates the keychain cache (so subsequent
|
|
71
|
+
* `getSessionKey` calls hit the cache). The cache is NEVER populated
|
|
72
|
+
* on failure — there's no null sentinel.
|
|
73
|
+
*
|
|
74
|
+
* Returns the decrypted session key on success, or `null` after timeout.
|
|
75
|
+
* Errors are swallowed inside the loop (best-effort polling); telemetry
|
|
76
|
+
* surfaces success vs timeout via the optional callbacks.
|
|
77
|
+
*/
|
|
78
|
+
export declare function awaitOwnSessionKeyGrant(sessionId: string, options: AwaitOwnGrantOptions): Promise<string | null>;
|
|
@@ -24,6 +24,30 @@ export interface ResumeOrCreateSessionResult {
|
|
|
24
24
|
/** The E2E session key (for encrypting/decrypting events), or null if no encryption */
|
|
25
25
|
sessionKey: string | null;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* CP-1.b IMPL r5 H-2 — Typed error thrown by `prepareSessionEncryption()`
|
|
29
|
+
* when `listServiceDeviceKeys()` returns an empty array across all
|
|
30
|
+
* attempts. Contract per r6/r7 fix: 4 fetch attempts, 3 backoff sleeps:
|
|
31
|
+
* 1s/2s/4s (total ~7s wall on full-failure path). Per CP-1.b design
|
|
32
|
+
* §6.1 lifecycle bullet "Fail-safe:
|
|
33
|
+
* shell-side createSession retries with 1s + 2s + 4s backoff" + LOCK
|
|
34
|
+
* #32 (prewarm custom-resource closes the first-cold-start window
|
|
35
|
+
* structurally; this retry is the disaster-recovery fail-safe).
|
|
36
|
+
*
|
|
37
|
+
* Surfacing this as a typed error (rather than the previous
|
|
38
|
+
* best-effort behavior which built sessions WITHOUT the planner-proxy
|
|
39
|
+
* grant — guaranteeing every subsequent Lambda decrypt would fail)
|
|
40
|
+
* lets the plugin / CLI wrappers display an actionable banner to the
|
|
41
|
+
* user instead of producing a half-broken session.
|
|
42
|
+
*
|
|
43
|
+
* The Lambda emits a matching `PlannerProxyServiceKeyMissing`
|
|
44
|
+
* CloudWatch metric in its `handleClassify` decrypt-failure path; the
|
|
45
|
+
* shell-side typed error closes the funnel at session-create time so
|
|
46
|
+
* the user never reaches a session that can't be decrypted.
|
|
47
|
+
*/
|
|
48
|
+
export declare class PlannerProxyServiceKeyMissingError extends Error {
|
|
49
|
+
constructor(msg: string);
|
|
50
|
+
}
|
|
27
51
|
/**
|
|
28
52
|
* Prepare E2E encryption for a new session.
|
|
29
53
|
*
|
|
@@ -36,6 +60,7 @@ export interface ResumeOrCreateSessionResult {
|
|
|
36
60
|
export declare function prepareSessionEncryption(sessionId: string, appSyncClient: AppSyncClient, logger: Logger): Promise<{
|
|
37
61
|
sessionKey: string;
|
|
38
62
|
encryptedKeys: EncryptedSessionKey[];
|
|
63
|
+
skippedDeviceIds: string[];
|
|
39
64
|
} | null>;
|
|
40
65
|
/**
|
|
41
66
|
* Resume an existing session or create a new one.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function makeTmpDir(prefix?: string): Promise<string>;
|
|
2
|
+
export declare function git(cwd: string, ...args: string[]): Promise<string>;
|
|
3
|
+
export declare function writeFile(file: string, content: string): Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* Initialises a git repo at `dir`, commits initial empty-tree marker so
|
|
6
|
+
* `git status --porcelain` works.
|
|
7
|
+
*/
|
|
8
|
+
export declare function initGitRepo(dir: string): Promise<void>;
|
|
9
|
+
export declare function gitAdd(cwd: string, file: string): Promise<void>;
|
|
10
|
+
export declare function gitCommit(cwd: string, msg?: string): Promise<void>;
|
|
11
|
+
export declare function cleanup(dir: string): Promise<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 @@
|
|
|
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 @@
|
|
|
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,8 @@
|
|
|
1
|
+
import { type ExclusionState, type StructuralSummaryGenerator } from './types';
|
|
2
|
+
export declare function createStructuralSummaryGenerator(): StructuralSummaryGenerator;
|
|
3
|
+
export interface ReadmeCounters {
|
|
4
|
+
excludedAsUntracked: number;
|
|
5
|
+
excludedByGitignore: number;
|
|
6
|
+
excludedByIgnoreFile: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function readReadmePreview(rootPath: string, exclusionState: ExclusionState, countedExactPaths: Set<string>, countedPrunedPrefixes: Set<string>, counters: ReadmeCounters): Promise<string>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createStructuralSummaryGenerator, readReadmePreview, } from './generator';
|
|
2
|
+
export { walk as walkRepoTree } from './walker';
|
|
3
|
+
export { isPathAdmissible, isPathInIgnoredPrefixes, isPathAccountedFor, matchesSecretDenyList, SECRET_DENY_LIST, } from './privacy-filter';
|
|
4
|
+
export { readOptIn, addBodyPath, removeBodyPath, optInFilePath, } from './opt-in-store';
|
|
5
|
+
export { compileUserIgnore, emptyUserIgnoreMatcher, } from './user-ignore-matcher';
|
|
6
|
+
export type { DirectoryNode, RepoSummary, StructuralSummary, StructuralSummaryGenerator, GenerateOpts, PrivacyEnvelope, WalkResult, ExclusionState, UserIgnoreMatcher, ParsedManifest, ManifestType, OptInFile, StructuralSummaryErrorKind, } from './types';
|
|
7
|
+
export { StructuralSummaryError } from './types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExclusionState, ParsedManifest } from '../types';
|
|
2
|
+
export interface ManifestCounters {
|
|
3
|
+
excludedAsUntracked: number;
|
|
4
|
+
excludedByGitignore: number;
|
|
5
|
+
excludedByIgnoreFile: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function parse(rootPath: string, exclusionState: ExclusionState, countedExactPaths: Set<string>, countedPrunedPrefixes: Set<string>, counters: ManifestCounters): Promise<ParsedManifest>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ParsedManifest } from '../types';
|
|
2
|
+
export declare const pyproject: {
|
|
3
|
+
findManifest(rootPath: string): Promise<string | null>;
|
|
4
|
+
parse(file: string): Promise<ParsedManifest>;
|
|
5
|
+
};
|
|
6
|
+
export declare const gomod: {
|
|
7
|
+
findManifest(rootPath: string): Promise<string | null>;
|
|
8
|
+
parse(file: string): Promise<ParsedManifest>;
|
|
9
|
+
};
|
|
10
|
+
export declare const podfile: {
|
|
11
|
+
findManifest(rootPath: string): Promise<string | null>;
|
|
12
|
+
parse(file: string): Promise<ParsedManifest>;
|
|
13
|
+
};
|
|
14
|
+
export declare const gradle: {
|
|
15
|
+
findManifest(rootPath: string): Promise<string | null>;
|
|
16
|
+
parse(file: string): Promise<ParsedManifest>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type OptInFile } from './types';
|
|
2
|
+
import type { Tier } from '../orchestration-shell/types';
|
|
3
|
+
export declare function optInFilePath(): string;
|
|
4
|
+
/**
|
|
5
|
+
* Per Stage 2 r1 Gemini M-1: reader takes `currentTier`. If
|
|
6
|
+
* `parsed.tierAtOptIn !== currentTier`, returns `null` (graceful tier-
|
|
7
|
+
* downgrade invalidation — no error throw).
|
|
8
|
+
*/
|
|
9
|
+
export declare function readOptIn(currentTier: Tier): Promise<OptInFile | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Per Stage 2 r1 Gemini H-3 option (a): widen to `Tier` so callers can
|
|
12
|
+
* pass `args.tier` directly without an unsafe type narrow. Runtime gate
|
|
13
|
+
* inside the function is authoritative; non-MAX throws `tier_gate`.
|
|
14
|
+
*
|
|
15
|
+
* Stage 2 r2 fix (H-1, Codex): validates that `bodyPath` is absolute
|
|
16
|
+
* BEFORE any persistence work. Normalises via `path.resolve()`
|
|
17
|
+
* (defense-in-depth — strips any residual `..` segments) and resolves
|
|
18
|
+
* symlinks via `fs.realpath()`. The realpath result is what gets
|
|
19
|
+
* persisted, so a future `cd` that lands the user in a different repo
|
|
20
|
+
* cannot trip a relative-path match. Throws `StructuralSummaryError(
|
|
21
|
+
* 'invalid_path')` for non-absolute or unresolvable inputs.
|
|
22
|
+
*/
|
|
23
|
+
export declare function addBodyPath(bodyPath: string, currentTier: Tier): Promise<OptInFile>;
|
|
24
|
+
export declare function removeBodyPath(bodyPath: string): Promise<OptInFile>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { ExclusionState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Stage 2 IMPL r2 fix (H-3, Codex H-2): strict path-containment helper.
|
|
4
|
+
*
|
|
5
|
+
* Returns true iff `rel` (the output of `path.relative(root, target)`)
|
|
6
|
+
* denotes a path OUTSIDE `root` via parent-directory traversal. Required
|
|
7
|
+
* because the naive `rel.startsWith('..')` form falsely classifies valid
|
|
8
|
+
* child names that happen to BEGIN with `..` (e.g., `..scratch/file.ts`,
|
|
9
|
+
* `..hidden`, `..foo/bar`) as outside the root.
|
|
10
|
+
*
|
|
11
|
+
* Correct semantics:
|
|
12
|
+
* rel === '..' → outside (parent of root)
|
|
13
|
+
* rel === '..' + path.sep + 'sib' → outside (sibling of root)
|
|
14
|
+
* rel === '..' + '/' + 'sib' → outside (POSIX form, used by
|
|
15
|
+
* git output / forward-slash
|
|
16
|
+
* callers on Windows)
|
|
17
|
+
* rel === '..foo' → INSIDE (child whose name
|
|
18
|
+
* starts with `..`)
|
|
19
|
+
*
|
|
20
|
+
* Used in: walker.ts `buildExclusionState` (realRootPath outside-repo
|
|
21
|
+
* check + untracked subtree filter) and privacy-filter.ts
|
|
22
|
+
* `isPathAdmissible` (relative-to-realRootPath admission).
|
|
23
|
+
*/
|
|
24
|
+
export declare function isOutsideRoot(rel: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Static secret-file deny-list. Matches `.env`, `.env.*`, `.aws/credentials`,
|
|
27
|
+
* and assorted private-key formats. Matched against absolute-path basename
|
|
28
|
+
* and a few suffix patterns. Per §4.3 step 2 first match.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SECRET_DENY_LIST: readonly string[];
|
|
31
|
+
/**
|
|
32
|
+
* Pure path test — returns true if `absolutePath` matches any secret
|
|
33
|
+
* deny-list pattern. The walker uses this to skip secret files silently
|
|
34
|
+
* (no counter increment per §4.3 hard-caps audit-quality note).
|
|
35
|
+
*/
|
|
36
|
+
export declare function matchesSecretDenyList(absolutePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Helper exported alongside `isPathAdmissible`: returns true if
|
|
39
|
+
* `absolutePath` is either:
|
|
40
|
+
* (a) an exact entry in `exactPaths` — file-level gitignore match,
|
|
41
|
+
* O(1) `Set.has(p)`; OR
|
|
42
|
+
* (b) equal to OR a descendant of an entry in `dirPrefixes` —
|
|
43
|
+
* directory-level gitignore match, implemented via check-then-step
|
|
44
|
+
* ancestor-walk:
|
|
45
|
+
*
|
|
46
|
+
* let p = absolutePath;
|
|
47
|
+
* while (true) {
|
|
48
|
+
* if (dirPrefixes.has(p)) return true;
|
|
49
|
+
* const parent = path.dirname(p);
|
|
50
|
+
* if (parent === p) return false; // filesystem root reached
|
|
51
|
+
* p = parent;
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* Key properties (per round-7 revision Codex r6 H-1 + Gemini r6 H-1/M-2):
|
|
55
|
+
*
|
|
56
|
+
* 1. **Signature is 3-arg** `(absolutePath, exactPaths, dirPrefixes)`.
|
|
57
|
+
* The helper does NOT receive `realRootPath`. The walk MUST proceed
|
|
58
|
+
* past `realRootPath` because `git ls-files --directory` may report
|
|
59
|
+
* an ignored ancestor ABOVE the launch root (e.g., parent
|
|
60
|
+
* `.gitignore` ignores `sub/` when launch root is `repo/sub/inner`).
|
|
61
|
+
* 2. **Check-then-step semantics**: check `dirPrefixes.has(p)` BEFORE
|
|
62
|
+
* advancing `p`. This handles the case where `absolutePath` is
|
|
63
|
+
* itself an entry in `dirPrefixes` (e.g., Step 0.5 root admission
|
|
64
|
+
* tests `realRootPath` directly when it is itself ignored).
|
|
65
|
+
* 3. **Loop termination**: when `path.dirname(p) === p` (POSIX `/`,
|
|
66
|
+
* Windows `C:\`). NO early termination at `realRootPath`.
|
|
67
|
+
*
|
|
68
|
+
* Lookup cost is O(absolute filesystem depth) (typically <30 on any sane
|
|
69
|
+
* mount tree), independent of `|dirPrefixes|`.
|
|
70
|
+
*/
|
|
71
|
+
export declare function isPathInIgnoredPrefixes(absolutePath: string, exactPaths: Set<string>, dirPrefixes: Set<string>): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* INTERNAL helper (not exported from the module index, but exported here
|
|
74
|
+
* so the manifest dispatcher + README reader can import it). Returns true
|
|
75
|
+
* iff `realFile` is already accounted for in the walker's two-set ledger
|
|
76
|
+
* (exact match OR equal-to-or-descendant-of an entry in pruned prefixes).
|
|
77
|
+
*
|
|
78
|
+
* Same canonical algorithm as `isPathInIgnoredPrefixes` — 3-arg signature,
|
|
79
|
+
* check-then-step, filesystem-root termination. Per round-7 revision
|
|
80
|
+
* Gemini r6 M-1 + Codex r6 H-1 + Gemini r6 M-2.
|
|
81
|
+
*/
|
|
82
|
+
export declare function isPathAccountedFor(realFile: string, countedExactPaths: Set<string>, countedPrunedPrefixes: Set<string>): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Order of checks (mirrors §4.3 step 2, first match wins):
|
|
85
|
+
* 1. secret (deny-list path-glob match — operates on basename + suffix).
|
|
86
|
+
* 2. untracked (`state.untrackedSet.has(absolutePath)`; SKIPPED if
|
|
87
|
+
* notInGitRepo).
|
|
88
|
+
* 3. gitignore (`isPathInIgnoredPrefixes(...)`; SKIPPED if notInGitRepo).
|
|
89
|
+
* 4. userIgnore (`state.userIgnoreMatcher.ignores(path.relative(
|
|
90
|
+
* realRootPath, absolutePath), isDir)`).
|
|
91
|
+
*
|
|
92
|
+
* Pure in-memory check; consults only the pre-built `state`. No I/O.
|
|
93
|
+
*
|
|
94
|
+
* `isDir` (Stage 2 r2 fix, M-2 Gemini M-1): walker passes
|
|
95
|
+
* `entry.isDirectory()` here. File-only callers (manifest dispatcher,
|
|
96
|
+
* README reader) accept the default `false`. The flag is consumed by
|
|
97
|
+
* `userIgnoreMatcher.ignores()` to honour trailing-slash `dir/` rules.
|
|
98
|
+
*
|
|
99
|
+
* Caller is responsible for incrementing the appropriate counter on
|
|
100
|
+
* `privacyEnvelope` when `admissible === false` (so audit signal is
|
|
101
|
+
* preserved). `reason === 'secret'` is silent (no counter — per §4.3
|
|
102
|
+
* hard-caps audit-quality note).
|
|
103
|
+
*/
|
|
104
|
+
export declare function isPathAdmissible(absolutePath: string, state: ExclusionState, isDir?: boolean): {
|
|
105
|
+
admissible: true;
|
|
106
|
+
} | {
|
|
107
|
+
admissible: false;
|
|
108
|
+
reason: 'secret' | 'untracked' | 'gitignore' | 'userIgnore';
|
|
109
|
+
};
|
|
110
|
+
export type { ExclusionState } from './types';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOCTOU-safe text file read. Returns the file contents as UTF-8 or
|
|
3
|
+
* `null` on any refusal / error. See module JSDoc for the syscall
|
|
4
|
+
* sequence + threat model.
|
|
5
|
+
*
|
|
6
|
+
* @param absPath Absolute filesystem path. Caller is responsible for
|
|
7
|
+
* path absolutism + admission-oracle checks BEFORE
|
|
8
|
+
* invoking this function; this helper only guards the
|
|
9
|
+
* lstat→open transition.
|
|
10
|
+
*/
|
|
11
|
+
export declare function safeReadTextFile(absPath: string): Promise<string | null>;
|