@buildaharness/aielia 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +832 -0
- package/dist/action-approval-service.d.ts +52 -0
- package/dist/action-snapshot.d.ts +173 -0
- package/dist/action-tools.d.ts +38 -0
- package/dist/agent-loop.d.ts +372 -0
- package/dist/answer-claim.d.ts +51 -0
- package/dist/ask-clarification-service.d.ts +70 -0
- package/dist/ask-mode-flag.d.ts +25 -0
- package/dist/ask-response-format.d.ts +8 -0
- package/dist/assistant-session.d.ts +267 -0
- package/dist/assistant-source.d.ts +14 -0
- package/dist/assistant-types.d.ts +158 -0
- package/dist/assistant.d.ts +419 -0
- package/dist/batch-list-detector.d.ts +15 -0
- package/dist/batch-research-fixtures.d.ts +50 -0
- package/dist/benchmark-injected-failure.d.ts +27 -0
- package/dist/claude-cli-llm-client.d.ts +139 -0
- package/dist/claude-cli-prompt.d.ts +86 -0
- package/dist/cli-config.d.ts +27 -0
- package/dist/cli-session-D0uLdT2A.js +7863 -0
- package/dist/cli-session-D0uLdT2A.js.map +1 -0
- package/dist/cli-session.d.ts +63 -0
- package/dist/cli.d.ts +65 -0
- package/dist/cli.js +1693 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +175 -0
- package/dist/contradiction-checker.d.ts +27 -0
- package/dist/debug-log.d.ts +16 -0
- package/dist/decomposition-classifier.d.ts +38 -0
- package/dist/doctor-checks.d.ts +8 -0
- package/dist/email-smtp.d.ts +19 -0
- package/dist/email.d.ts +60 -0
- package/dist/error-classifier.d.ts +13 -0
- package/dist/execution-mode.d.ts +85 -0
- package/dist/fact-extraction.d.ts +143 -0
- package/dist/failure-mode-matcher.d.ts +32 -0
- package/dist/file-tools-mcp-server.mjs +1027 -0
- package/dist/file-tools.d.ts +179 -0
- package/dist/first-run.d.ts +22 -0
- package/dist/harness-bridge.d.ts +103 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +212 -0
- package/dist/index.js.map +1 -0
- package/dist/ink-test-render.d.ts +24 -0
- package/dist/lexical/patterns/batch-list-markers.json +8 -0
- package/dist/lexical/patterns/batch-list-markers.json.d.ts +11 -0
- package/dist/lexical/patterns/coding-fact-markers.json +8 -0
- package/dist/lexical/patterns/coding-fact-markers.json.d.ts +11 -0
- package/dist/lexical/patterns/enumeration-markers.json +20 -0
- package/dist/lexical/patterns/enumeration-markers.json.d.ts +23 -0
- package/dist/lexical/patterns/fact-markers.json +16 -0
- package/dist/lexical/patterns/fact-markers.json.d.ts +19 -0
- package/dist/lexical/patterns/injection-patterns.json +20 -0
- package/dist/lexical/patterns/injection-patterns.json.d.ts +23 -0
- package/dist/lexical/patterns/plan-mode-markers.json +10 -0
- package/dist/lexical/patterns/plan-mode-markers.json.d.ts +13 -0
- package/dist/lexical/patterns/risk-patterns.json +122 -0
- package/dist/lexical/patterns/risk-patterns.json.d.ts +125 -0
- package/dist/lexical/patterns/task-cancel-markers.json +22 -0
- package/dist/lexical/patterns/task-cancel-markers.json.d.ts +25 -0
- package/dist/lexical/patterns/template-keywords.json +20 -0
- package/dist/lexical/patterns/template-keywords.json.d.ts +23 -0
- package/dist/lexical/patterns/tool-yield-markers.json +22 -0
- package/dist/lexical/patterns/tool-yield-markers.json.d.ts +25 -0
- package/dist/lexical/patterns.d.ts +64 -0
- package/dist/memory-service.d.ts +219 -0
- package/dist/model-pricing.d.ts +19 -0
- package/dist/network-containment.d.ts +21 -0
- package/dist/node-config-store.d.ts +29 -0
- package/dist/node-display-names.d.ts +26 -0
- package/dist/node-fs-backend.d.ts +8 -0
- package/dist/non-interactive-mode.d.ts +22 -0
- package/dist/one-loop-flag.d.ts +38 -0
- package/dist/plan-approval-service.d.ts +62 -0
- package/dist/plan-builder.d.ts +32 -0
- package/dist/plan-drafting-service.d.ts +87 -0
- package/dist/plan-drafting.d.ts +58 -0
- package/dist/plan-mode-flag.d.ts +34 -0
- package/dist/plan-service.d.ts +61 -0
- package/dist/plan-sketch-service.d.ts +24 -0
- package/dist/plan-sketch.d.ts +20 -0
- package/dist/plan-store.d.ts +232 -0
- package/dist/plan-templates/data/content_creation.json.d.ts +75 -0
- package/dist/plan-templates/data/decision_making.json.d.ts +66 -0
- package/dist/plan-templates/data/problem_solving.json.d.ts +75 -0
- package/dist/plan-templates/data/process_improvement.json.d.ts +57 -0
- package/dist/plan-templates/data/project_planning.json.d.ts +66 -0
- package/dist/plan-templates/data/research_analysis.json.d.ts +66 -0
- package/dist/plan-templates/data/trip_planning.json.d.ts +66 -0
- package/dist/plan-templates/index.d.ts +33 -0
- package/dist/plan-verification.d.ts +31 -0
- package/dist/reminder-tools.d.ts +13 -0
- package/dist/response-service.d.ts +73 -0
- package/dist/review-checker.d.ts +22 -0
- package/dist/risk-classifier.d.ts +7 -0
- package/dist/scripted-llm-client.d.ts +37 -0
- package/dist/semantic-criterion-coverage.d.ts +30 -0
- package/dist/shell-executor.d.ts +14 -0
- package/dist/shell-tools.d.ts +84 -0
- package/dist/spend-cap.d.ts +41 -0
- package/dist/spike.d.ts +1 -0
- package/dist/spike.js +18 -0
- package/dist/spike.js.map +1 -0
- package/dist/supervisor-decider.d.ts +3 -0
- package/dist/system-prompt.d.ts +8 -0
- package/dist/task-mapping.d.ts +42 -0
- package/dist/tool-control-plane.d.ts +67 -0
- package/dist/tool-policy.d.ts +45 -0
- package/dist/tool-step.d.ts +23 -0
- package/dist/tool-yield-classifier.d.ts +7 -0
- package/dist/trace-events.d.ts +126 -0
- package/dist/transcript-compaction.d.ts +13 -0
- package/dist/trust-tagging.d.ts +38 -0
- package/dist/tui-app-DxLPSGh2.js +481 -0
- package/dist/tui-app-DxLPSGh2.js.map +1 -0
- package/dist/tui-app.d.ts +125 -0
- package/dist/tui-input.d.ts +51 -0
- package/dist/tui-mode-flag.d.ts +36 -0
- package/dist/tui-output-capture.d.ts +30 -0
- package/dist/tui-spike.d.ts +1 -0
- package/dist/turn-intent-classifier.d.ts +96 -0
- package/dist/turn-interpreter.d.ts +71 -0
- package/dist/turn-policy.d.ts +45 -0
- package/dist/web-fetch-core.d.ts +65 -0
- package/dist/web-search-provider.d.ts +12 -0
- package/dist/web-tools.d.ts +26 -0
- package/package.json +69 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { ExternalContradictionInput } from '@buildaharness/harness';
|
|
3
|
+
export interface BeliefCandidate {
|
|
4
|
+
id: string;
|
|
5
|
+
statement: string;
|
|
6
|
+
}
|
|
7
|
+
/** Zero-LLM-call gate: true when a belief statement reads like a structured/technical (build, test, service, file) claim rather than a natural-language personal fact. */
|
|
8
|
+
export declare function looksLikeCodingFact(statement: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* `AUDIT_SEMANTIC_CONTRADICTION` gate — feature-value audit (Phase A4 of
|
|
11
|
+
* plans/feature_audit_automation_plan.html). Default **ON**: the semantic contradiction-checker
|
|
12
|
+
* LLM call ships enabled, so an unset / empty / truthy value keeps today's behaviour. Set to a
|
|
13
|
+
* falsy value (`0` / `false` / `off` / `no` / `disabled`) to skip the LLM call entirely and fall
|
|
14
|
+
* back to the harness's always-on lexical / negation-pair check only. Read at exactly one call
|
|
15
|
+
* site — `harness-bridge.ts`, where the `contradictionChecker` host hook is wired.
|
|
16
|
+
*/
|
|
17
|
+
export declare function semanticContradictionEnabled(env?: Record<string, string | undefined>): boolean;
|
|
18
|
+
/** A newBelief restating/reinforcing an uncertainFacts or rejectedFacts entry in different words — see checkForContradictions' doc comment. Caller resolves which pool `existingId` came from by id membership (both ids are always from this call's own known-id set, filtered below). */
|
|
19
|
+
export interface Corroboration {
|
|
20
|
+
existingId: string;
|
|
21
|
+
newId: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ContradictionCheckResult {
|
|
24
|
+
contradictions: ExternalContradictionInput[];
|
|
25
|
+
corroborations: Corroboration[];
|
|
26
|
+
}
|
|
27
|
+
export declare function checkForContradictions(newBeliefs: BeliefCandidate[], existingBeliefs: BeliefCandidate[], llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void, uncertainFacts?: BeliefCandidate[], rejectedFacts?: BeliefCandidate[]): Promise<ContradictionCheckResult>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full conversation content, for a caller that wants live visibility while debugging — a
|
|
3
|
+
* user's message, the assistant's final reply/reason, or one real tool call's name/input/
|
|
4
|
+
* result. Not privacy-scrubbed and not truncated to name-only the way TraceEvent is; a
|
|
5
|
+
* caller opts into this explicitly (see PersonalAssistantOptions.onDebugLog) knowing it
|
|
6
|
+
* carries real content, not just metadata.
|
|
7
|
+
*
|
|
8
|
+
* Split into its own file so both assistant.ts (user_message/assistant_reply kinds, emitted from
|
|
9
|
+
* `turn()`) and agent-loop.ts (tool_call kind, emitted from the ReAct loop) can depend on it
|
|
10
|
+
* without either owning the other.
|
|
11
|
+
*/
|
|
12
|
+
export interface DebugLogEntry {
|
|
13
|
+
kind: 'user_message' | 'assistant_reply' | 'tool_call';
|
|
14
|
+
sessionId: string;
|
|
15
|
+
content: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
/**
|
|
3
|
+
* True if `message` looks like an enumeration of multiple distinct items — the strong signals
|
|
4
|
+
* above (sequencing markers, comma/semicolon/numbered lists), deliberately WITHOUT a word-count
|
|
5
|
+
* fallback: a single long reminder isn't multiple reminders just because it's wordy. Used by
|
|
6
|
+
* risk-classifier.ts to gate bulk reminder creation on confirmation instead of letting the model
|
|
7
|
+
* silently create several reminders in one turn.
|
|
8
|
+
*/
|
|
9
|
+
export declare function looksLikeEnumeratedItems(message: string): boolean;
|
|
10
|
+
export interface DecomposedTaskSpec {
|
|
11
|
+
id: string;
|
|
12
|
+
description: string;
|
|
13
|
+
depends_on: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Per-task risk (LOW/MEDIUM/HIGH), not the turn-level risk broadcast across every task —
|
|
16
|
+
* see Phase 4.2 of the harness layer activation plan: a step like "delete the draft file"
|
|
17
|
+
* shouldn't inherit an unrelated sibling step's risk profile just because they were rendered
|
|
18
|
+
* from the same turn. classifyTurnIntent's LLM call judges this directly for ad hoc
|
|
19
|
+
* decompositions; buildPlanFromTemplate (plan-builder.ts) attaches it from the template's own
|
|
20
|
+
* already-curated per-task risk_level instead of asking the LLM to re-derive it.
|
|
21
|
+
*/
|
|
22
|
+
riskLevel: 'LOW' | 'MEDIUM' | 'HIGH';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Reframes a single-task turn's description to lead with its subject — the same phrasing
|
|
26
|
+
* classifyTurnIntent's own decomposedTasks and buildPlanFromTemplate (plan-builder.ts) already
|
|
27
|
+
* produce for their own tasks, applied here for the much more common case where a turn goes
|
|
28
|
+
* through neither: an ad hoc single-task turn whose description otherwise stays the raw verbatim userMessage (see
|
|
29
|
+
* assistant.ts's initialTasks fallback). Without this, only decomposed/planned tasks got
|
|
30
|
+
* subject-first descriptions, so the "Completed: <description>" belief statementsOpposed/
|
|
31
|
+
* isNegation compare against was structured for some tasks and not others. Deliberately not
|
|
32
|
+
* called unconditionally — the caller gates this behind looksLikeCodingFact AND riskLevel !==
|
|
33
|
+
* 'LOW' (the actual precondition for a single task's description to ever reach that belief; see
|
|
34
|
+
* assistant.ts's call site for why looksLikeCodingFact alone isn't a safe gate for a new call).
|
|
35
|
+
* Falls back to null (caller keeps the original message) on any parse failure or LLM error,
|
|
36
|
+
* matching this codebase's other LLM-backed classifiers.
|
|
37
|
+
*/
|
|
38
|
+
export declare function reframeTaskDescriptionWithLLM(message: string, llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<string | null>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FsBackend } from '@buildaharness/runtime';
|
|
2
|
+
import { DoctorCheck } from './cli-session.js';
|
|
3
|
+
/** GET <proxyUrl>/health, expecting {status:'ok'} (see packages/proxy/src/index.ts) — hard-timed so a dead proxy can't hang /doctor. */
|
|
4
|
+
export declare function checkProxyHealth(proxyUrl: string): Promise<DoctorCheck>;
|
|
5
|
+
/** Spawns `<claudePath> --version`, same path resolution ClaudeCliLLMClient uses — hard-timed so a hung/missing binary can't hang /doctor. */
|
|
6
|
+
export declare function checkClaudeCli(claudePath: string): Promise<DoctorCheck>;
|
|
7
|
+
export declare function checkWorkspaceRoot(workspaceRoot: string): Promise<DoctorCheck>;
|
|
8
|
+
export declare function checkDataDirWritable(backend: FsBackend, dataDir: string): Promise<DoctorCheck>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SendEmail } from './email.js';
|
|
2
|
+
export interface SmtpSenderOptions {
|
|
3
|
+
host: string;
|
|
4
|
+
port: number;
|
|
5
|
+
/** true for implicit TLS (port 465); false for STARTTLS (587) or plain (25). */
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
auth?: {
|
|
8
|
+
user: string;
|
|
9
|
+
pass: string;
|
|
10
|
+
};
|
|
11
|
+
/** Default sender address, used when a message omits `from`. */
|
|
12
|
+
from: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* SMTP transport via nodemailer. All connection details come from config
|
|
16
|
+
* (ASSISTANT_EMAIL_SMTP_* / config.json), never from the model. `nodemailer` is a dependency of
|
|
17
|
+
* this package but imported dynamically so it is only loaded when SMTP is actually configured.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createSmtpSender(options: SmtpSenderOptions): SendEmail;
|
package/dist/email.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email as a real, approval-gated "effect" tool (adoption plan F2, path (a)).
|
|
3
|
+
*
|
|
4
|
+
* The assistant's flagship demo — "send an email to my boss saying I quit" → the risk gate
|
|
5
|
+
* stops before anything leaves the machine — only means something if there is an actual send
|
|
6
|
+
* behind the gate. `send_email` is that action, staged exactly like `write_file`/`run_shell_command`
|
|
7
|
+
* (see file-tools.ts's stagePendingAction): the model can only ever *propose* a message, never
|
|
8
|
+
* deliver one, and `applyPendingAction` calls the injected `SendEmail` transport only after a human
|
|
9
|
+
* approves the concrete recipient/subject/body.
|
|
10
|
+
*
|
|
11
|
+
* This module is browser-safe (no static Node imports) so it can be reached from
|
|
12
|
+
* assistant.ts/index.ts, which chat-ui bundles. The Resend transport below is pure `fetch`. The
|
|
13
|
+
* SMTP transport lives in email-smtp.ts (Node-only, lazy-loads nodemailer) and is wired in only by
|
|
14
|
+
* Node callers (cli.ts), the same split shell-executor.ts / node-fs-backend.ts already use.
|
|
15
|
+
*/
|
|
16
|
+
/** A concrete message the model has proposed. `from` is filled in by the transport if omitted. */
|
|
17
|
+
export interface EmailMessage {
|
|
18
|
+
to: string;
|
|
19
|
+
subject: string;
|
|
20
|
+
body: string;
|
|
21
|
+
from?: string;
|
|
22
|
+
cc?: string;
|
|
23
|
+
bcc?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SendEmailResult {
|
|
26
|
+
/** Provider-assigned id for the delivered message, when the transport returns one. */
|
|
27
|
+
id?: string;
|
|
28
|
+
provider: 'resend' | 'smtp';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Delivers a message for real. Injected into applyPendingAction (file-tools.ts) rather than
|
|
32
|
+
* imported, so the staging/approval path has no transport dependency and stays unit-testable with
|
|
33
|
+
* a spy. Throws on a delivery failure — applyPendingAction lets that propagate to the caller.
|
|
34
|
+
*/
|
|
35
|
+
export type SendEmail = (message: EmailMessage) => Promise<SendEmailResult>;
|
|
36
|
+
export declare class EmailDeliveryError extends Error {
|
|
37
|
+
readonly provider: 'resend' | 'smtp';
|
|
38
|
+
constructor(provider: 'resend' | 'smtp', detail: string);
|
|
39
|
+
}
|
|
40
|
+
/** Minimal RFC-5322-ish address check — a staged action with a malformed recipient is rejected before it is ever shown for approval. */
|
|
41
|
+
export declare function isLikelyEmailAddress(value: string): boolean;
|
|
42
|
+
export interface ResendSenderOptions {
|
|
43
|
+
apiKey: string;
|
|
44
|
+
/** The verified sender address Resend delivers as. Required — Resend rejects a send with no `from`. */
|
|
45
|
+
from: string;
|
|
46
|
+
/** Override for tests; defaults to the global fetch. */
|
|
47
|
+
fetchImpl?: typeof fetch;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resend transport (https://resend.com) — a single authenticated POST, works in Node and the
|
|
51
|
+
* browser. `apiKey` and `from` come from config (ASSISTANT_EMAIL_* / config.json), never from the
|
|
52
|
+
* model.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createResendSender(options: ResendSenderOptions): SendEmail;
|
|
55
|
+
/**
|
|
56
|
+
* One-line human-readable summary of a staged email, for the approval prompt and trace. Kept here
|
|
57
|
+
* (not in agent-loop.ts) so the MCP server (file-tools-mcp-server.mjs) and the CLI can format the
|
|
58
|
+
* same way without importing the loop.
|
|
59
|
+
*/
|
|
60
|
+
export declare function formatEmailApprovalReason(message: Pick<EmailMessage, 'to' | 'subject' | 'body'>): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AssistantConfig } from './config.js';
|
|
2
|
+
export interface ErrorClassification {
|
|
3
|
+
message: string;
|
|
4
|
+
retryable: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Maps a thrown turn error to user-facing copy and whether retrying is worth offering. Defaults
|
|
8
|
+
* to a generic, still-retryable message for anything unrecognized. `backend` (the caller's
|
|
9
|
+
* current `config.llmBackend`) disambiguates errors whose shape is identical across backends but
|
|
10
|
+
* whose actual cause/remedy differs — see the FlowExecutionError pattern's comment above; omit it
|
|
11
|
+
* only when no backend context exists (e.g. classifying a local file-write error).
|
|
12
|
+
*/
|
|
13
|
+
export declare function classifyError(err: unknown, backend?: AssistantConfig['llmBackend']): ErrorClassification;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 4 of plans/harness_and_assistant_architecture_remediation_plan.html: a named,
|
|
3
|
+
* typed replacement for the three implicit bypass branches runTurn() used to make on its
|
|
4
|
+
* own, ad hoc, with no shared vocabulary between them:
|
|
5
|
+
* - classification.isTrivial → skip the harness run entirely (assistant.ts:1487-1495)
|
|
6
|
+
* - the plan-cancel bypass → skip classifyTurnIntent entirely (assistant.ts:1341-1370)
|
|
7
|
+
* - the batch-confirmation resume → skip the per-turn HarnessRuntime run entirely (assistant.ts:2467-2487)
|
|
8
|
+
* Each of those is a real, distinct guarantee-level a turn can run at — README's "every ordinary
|
|
9
|
+
* message walks the full 11-layer harness" claim is only true for two of the five modes below, and
|
|
10
|
+
* classifyExecutionMode() makes that precise instead of leaving it to be inferred from call-site
|
|
11
|
+
* reading order.
|
|
12
|
+
*/
|
|
13
|
+
export type ExecutionMode = 'FAST' | 'TOOL' | 'PLAN' | 'CONSEQUENTIAL' | 'RESEARCH';
|
|
14
|
+
/**
|
|
15
|
+
* Per-mode guarantee documentation — what a caller can and can't rely on for a turn classified
|
|
16
|
+
* into each mode. Kept next to the type (not just in this file's header comment) so a reader
|
|
17
|
+
* inspecting one mode's behavior sees its contract without having to scroll up.
|
|
18
|
+
*
|
|
19
|
+
* - FAST: Trivial, self-contained factual turns (turn-intent-classifier.ts's isTrivial
|
|
20
|
+
* contract). No HarnessRuntime run at all this turn — no verification, no
|
|
21
|
+
* control-state, no reviewer pass, no checkpoint. Fastest path, weakest
|
|
22
|
+
* guarantees; safe only because isTrivial is deliberately conservative.
|
|
23
|
+
* - PLAN: A durable-plan bookkeeping turn (cancel/abandon a task) that never leaves this
|
|
24
|
+
* session's own plan-store state — no external effect, so no harness run and no
|
|
25
|
+
* tool loop either.
|
|
26
|
+
* - RESEARCH: The batch-research path (an explicit N-item list). Runs its own self-calibrating
|
|
27
|
+
* per-item tool-call budget (see budget.ts / BATCH_* constants) instead of the
|
|
28
|
+
* harness's task graph; a confirmed-large batch pauses for approval before
|
|
29
|
+
* spending it. No per-turn HarnessRuntime run backs this mode's own tool calls
|
|
30
|
+
* (though a resumed confirmation still skips it too, matching the direct path).
|
|
31
|
+
* - TOOL: An ordinary tool-using turn with no approval gate tripped. Walks the full
|
|
32
|
+
* HarnessRuntime run (world model, hypothesis, contradiction, control state,
|
|
33
|
+
* verification, recovery, reviewer pass) over the tool loop's already-produced
|
|
34
|
+
* reply — today's real guarantee level, still post-hoc bookkeeping rather than
|
|
35
|
+
* an in-loop control plane (see ToolPolicy for where deterministic, harness-
|
|
36
|
+
* state-informed gating is actually enforced).
|
|
37
|
+
* - CONSEQUENTIAL: turn-policy.ts's evaluateTurnPolicy() returned REQUIRE_APPROVAL, or the
|
|
38
|
+
* turn's tool calls include a write_file/run_shell_command (always staged,
|
|
39
|
+
* independent of risk classification — see ToolPolicy). Never executes without
|
|
40
|
+
* an explicit approve-by-ID round trip; the harness run (when one applies)
|
|
41
|
+
* still runs on top for bookkeeping, but TurnPolicy/ToolPolicy — not
|
|
42
|
+
* classification.riskLevel/requiresApproval directly — are the actual
|
|
43
|
+
* authoritative decision for whether this turn's action proceeds (Phase D3).
|
|
44
|
+
*/
|
|
45
|
+
export declare const EXECUTION_MODE_GUARANTEES: Record<ExecutionMode, string>;
|
|
46
|
+
export interface ExecutionModeInput {
|
|
47
|
+
/** True when the plan-cancel bypass (matchTaskCancelAttempt) short-circuited before
|
|
48
|
+
* classifyTurnIntent ever ran this turn. */
|
|
49
|
+
isPlanCancelBypass: boolean;
|
|
50
|
+
/** True when this turn is resolving a batch-research confirmation pause
|
|
51
|
+
* (resolvePendingBatchConfirmation) or is about to enter the batch-research path
|
|
52
|
+
* (runBatchToolLoop) fresh. */
|
|
53
|
+
isBatchResearch: boolean;
|
|
54
|
+
/** turn-intent-classifier.ts's own isTrivial verdict — only meaningful once classification has
|
|
55
|
+
* actually run (never true when isPlanCancelBypass/isBatchResearch already short-circuited). */
|
|
56
|
+
isTrivial: boolean;
|
|
57
|
+
/** turn-policy.ts's evaluateTurnPolicy() decision (REQUIRE_APPROVAL), recomputed from
|
|
58
|
+
* turn-intent-classifier.ts's riskLevel/isBulkReminderRequest signals rather than read directly
|
|
59
|
+
* off its requiresApproval boolean — OR a write_file/run_shell_command tool call was proposed
|
|
60
|
+
* this turn (file-tools.ts's unconditional per-call staging gate). See ToolPolicy for the
|
|
61
|
+
* per-tool-call analog of this same deterministic-gate shape. */
|
|
62
|
+
requiresApproval: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Pure classification — no I/O, no LLM call. Order matters: earlier bypasses in runTurn's own
|
|
66
|
+
* control flow take precedence over classification fields that were never computed for that path
|
|
67
|
+
* (e.g. isTrivial is meaningless once isPlanCancelBypass already fired), mirroring the exact
|
|
68
|
+
* precedence runTurn's own if/else chain already encodes today.
|
|
69
|
+
*/
|
|
70
|
+
export declare function classifyExecutionMode(input: ExecutionModeInput): ExecutionMode;
|
|
71
|
+
/**
|
|
72
|
+
* classifyExecutionMode() plus the trace-emission wrapper every call site used to repeat inline
|
|
73
|
+
* (PersonalAssistant.classifyAndTraceExecutionMode, before the Phase 4d module split) — always
|
|
74
|
+
* traces unconditionally (the ASSISTANT_CONTROL_PLANE flag this used to gate on was removed in
|
|
75
|
+
* Phase 4b). Shared by every module that needs to classify-and-trace this turn's ExecutionMode
|
|
76
|
+
* (action-approval-service.ts's resolvePendingBatchConfirmation, and assistant.ts's own
|
|
77
|
+
* sequencer — TurnInterpreter deliberately never touches onTrace at all, see its own doc
|
|
78
|
+
* comment) instead of each repeating `onTrace?.(...)` separately. Takes the narrowest event
|
|
79
|
+
* shape it actually emits (not the full TraceEvent union) so this file never needs to import
|
|
80
|
+
* trace-events.ts, which itself imports ExecutionMode from here.
|
|
81
|
+
*/
|
|
82
|
+
export declare function classifyAndTraceExecutionMode(onTrace: ((event: {
|
|
83
|
+
kind: 'execution_mode_classified';
|
|
84
|
+
mode: ExecutionMode;
|
|
85
|
+
}) => void) | undefined, input: ExecutionModeInput): ExecutionMode;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { FactConfidence, FactCategory } from './turn-intent-classifier.js';
|
|
2
|
+
/**
|
|
3
|
+
* Provenance of a captured fact — Phase 5 of the harness/personal-assistant remediation plan
|
|
4
|
+
* (plans/harness_and_assistant_architecture_remediation_plan.html), replacing the previous bare
|
|
5
|
+
* `durable: boolean` with a typed source plus a promotion policy keyed off it (see
|
|
6
|
+
* assistant.ts's recordFacts()). USER_ASSERTED is this file's own free lexical marker pass
|
|
7
|
+
* (extractFactsFromTurn) — unchanged in behavior and still auto-promotable, exactly as before
|
|
8
|
+
* this phase. MODEL_INFERRED is classifyTurnIntent's statesDurableFact free-form LLM read, only
|
|
9
|
+
* ever consulted when the lexical pass found nothing — no longer auto-promoted to durable status
|
|
10
|
+
* on its own (see recordFacts). OBSERVED and EXTERNALLY_VERIFIED have no producer in this
|
|
11
|
+
* codebase yet (e.g. a future tool-observed state claim, or Phase 6's AnswerClaim evidence
|
|
12
|
+
* trail) — defined now so a future producer has a typed slot to land in rather than overloading
|
|
13
|
+
* MODEL_INFERRED for something with a different trust profile.
|
|
14
|
+
*
|
|
15
|
+
* Storage-taxonomy note (Phase 5b, superseded by Phase E's typed `MemoryTier` below): `UserFact`
|
|
16
|
+
* is this codebase's Knowledge-shaped data ("what we believe") — `text`/`durable` is the belief
|
|
17
|
+
* itself; `FactSource` is its provenance ("why we believe it"). See
|
|
18
|
+
* packages/aielia/README.md's "Memory tiers" section for the full tier map this fits
|
|
19
|
+
* into, and memory-service.ts's DURABLE_FACTS_KEY doc comment for where promoted facts are stored.
|
|
20
|
+
*/
|
|
21
|
+
export type FactSource = 'user_asserted' | 'model_inferred' | 'observed' | 'externally_verified';
|
|
22
|
+
export interface UserFact {
|
|
23
|
+
text: string;
|
|
24
|
+
extractedAt: string;
|
|
25
|
+
sourceTurn: string;
|
|
26
|
+
/**
|
|
27
|
+
* True for a fact currently promoted to the cross-session store that survives /new (name,
|
|
28
|
+
* stated preference, health/dietary — see DURABLE_MARKERS below), false for a session-scoped
|
|
29
|
+
* detail (current location, current job, "remember that"-style context, or an unconfirmed
|
|
30
|
+
* MODEL_INFERRED claim) that's expected to change more often or hasn't earned promotion yet.
|
|
31
|
+
* Derived from `source` via the promotion policy in recordFacts(), not set independently.
|
|
32
|
+
* assistant.ts's recordFacts() stores promoted facts in a second, never-cleared store in
|
|
33
|
+
* addition to the per-session one.
|
|
34
|
+
*/
|
|
35
|
+
durable: boolean;
|
|
36
|
+
/** See FactSource. */
|
|
37
|
+
source: FactSource;
|
|
38
|
+
/**
|
|
39
|
+
* Confidence `classifyTurnIntent`'s `StatedFact.confidence` (turn-intent-classifier.ts) assigns
|
|
40
|
+
* a `model_inferred` fact — undefined for `user_asserted`/`observed`/`externally_verified`
|
|
41
|
+
* facts, which have no confidence gradient (they either matched a lexical pattern or didn't).
|
|
42
|
+
* Added in Phase 2 of plans/personal_assistant_fact_extraction_llm_confidence_plan.html for
|
|
43
|
+
* `recordFacts()`'s three-way promotion policy; Phase 4 additionally uses it to adjust
|
|
44
|
+
* `tierForFact()` and to annotate the per-turn facts prompt block. `migrateFact()` needs no
|
|
45
|
+
* change for this field — a pre-existing on-disk fact with no `confidence` reads back as
|
|
46
|
+
* `undefined`, which every reader here already treats as "no confidence signal, most
|
|
47
|
+
* conservative".
|
|
48
|
+
*/
|
|
49
|
+
confidence?: FactConfidence;
|
|
50
|
+
/**
|
|
51
|
+
* `StatedFact.category` (turn-intent-classifier.ts) carried through onto the stored fact —
|
|
52
|
+
* undefined for `user_asserted`/`observed`/`externally_verified` facts, same "no signal from
|
|
53
|
+
* that source" convention `confidence` already follows. Added in Phase 3 of
|
|
54
|
+
* plans/personal_assistant_fact_extraction_llm_confidence_plan.html so a medium-confidence
|
|
55
|
+
* fact queued to `facts:pending-confirmation` (memory-service.ts) carries the topic its
|
|
56
|
+
* `/memory` grouping needs — see that file's `PendingFact`.
|
|
57
|
+
*/
|
|
58
|
+
category?: FactCategory;
|
|
59
|
+
/**
|
|
60
|
+
* The project label this fact is scoped to — undefined means global (always shown, regardless
|
|
61
|
+
* of which project is active). Set by `MemoryService.recordFacts()`/`buildTurnFacts()` only for
|
|
62
|
+
* a fact classified `category: 'project'` (see FactCategory), using whatever
|
|
63
|
+
* `PersonalAssistant`'s `currentProject()` getter resolves to at capture time: an explicit
|
|
64
|
+
* `config.activeProject` override if the user set one via `/project <name>`, else the workspace
|
|
65
|
+
* root the assistant is running in. A fact in any other category is inherently about the user,
|
|
66
|
+
* not a codebase, so it stays global on purpose even while a project is active.
|
|
67
|
+
* `loadFacts()`/`getMemorySummary()` still return every fact regardless of `project` — only the
|
|
68
|
+
* turn's `factsBlock` (what the model actually sees) filters to global-or-current-project, so
|
|
69
|
+
* `/memory` stays a complete inventory the user can review/forget from regardless of which
|
|
70
|
+
* project is currently active.
|
|
71
|
+
*/
|
|
72
|
+
project?: string;
|
|
73
|
+
}
|
|
74
|
+
/** Every fact has a certainty for `/memory` display purposes, even one with no `confidence` gradient (user_asserted/observed/externally_verified) — those are exactly as certain as a stated fact gets, so they display as 'high' rather than blank. Never used for promotion/tier logic, which still reads `fact.confidence` directly and treats undefined as "no LLM confidence signal" (see that field's own doc comment) — this is purely a rendering convenience. */
|
|
75
|
+
export declare function certaintyLabel(fact: UserFact): FactConfidence;
|
|
76
|
+
export declare function migrateFact(fact: UserFact): UserFact;
|
|
77
|
+
/**
|
|
78
|
+
* The six-tier taxonomy (Phase E of the harness consolidation plan, criticism001 #8 /
|
|
79
|
+
* criticism002 #6: "transcript ≠ memory"), made real as a type instead of the doc-comment-only
|
|
80
|
+
* split this file's `FactSource` note above already described. `UserFact` only ever populates
|
|
81
|
+
* four of these — `procedural` (the `ExperienceStore`) and `commitment` (`ReminderStore`) are
|
|
82
|
+
* separate stores with their own writers and never routed through `tierForFact`; keeping them in
|
|
83
|
+
* this union (rather than a narrower `UserFactTier`) is what lets `TIER_RULES.procedural`'s empty
|
|
84
|
+
* `allowedSources` structurally enforce INV-16 (no Experience entry is ever reachable as a
|
|
85
|
+
* `UserFact`, let alone a Knowledge one) instead of relying on every caller to remember to check.
|
|
86
|
+
*/
|
|
87
|
+
export type MemoryTier = 'episodic' | 'semantic' | 'procedural' | 'preference' | 'commitment' | 'identity';
|
|
88
|
+
export interface TierRule {
|
|
89
|
+
/** FactSource values allowed to populate this tier — see TIER_RULES. */
|
|
90
|
+
allowedSources: FactSource[];
|
|
91
|
+
/** 'session': cleared with the rest of `facts:${sessionId}` on /new. 'durable': survives /new (DURABLE_FACTS_KEY today). */
|
|
92
|
+
retention: 'session' | 'durable';
|
|
93
|
+
/** Whether contradiction detection considers entries in this tier (see harness-bridge.ts's factExtractor). */
|
|
94
|
+
contradictionChecked: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Retention / contradiction / (implicitly, via `retention`) deletion rule per tier, plus the
|
|
98
|
+
* `FactSource` provenances allowed to populate it — the four properties Phase E's scope calls
|
|
99
|
+
* for. `procedural` and `commitment` have an empty `allowedSources`: no `UserFact` is ever tagged
|
|
100
|
+
* with either tier (see `tierForFact` below), so a `UserFact` can never populate the Experience or
|
|
101
|
+
* Commitment stores through this path — that's the structural half of INV-16, not just a runtime
|
|
102
|
+
* check.
|
|
103
|
+
*/
|
|
104
|
+
export declare const TIER_RULES: Record<MemoryTier, TierRule>;
|
|
105
|
+
/**
|
|
106
|
+
* Routes a `UserFact` to its `MemoryTier` per Phase E / E3's rule, extended by Phase 4 of
|
|
107
|
+
* plans/personal_assistant_fact_extraction_llm_confidence_plan.html: `observed` (a future
|
|
108
|
+
* tool-observed claim) always stays `episodic` — an uncorroborated observation, never Knowledge.
|
|
109
|
+
* `model_inferred` (the LLM's `statesDurableFacts` guess) stays `episodic` too UNLESS it's both
|
|
110
|
+
* `durable` and `confidence === 'high'` — Phase 1's own definition of high confidence ("the user
|
|
111
|
+
* states it directly and unhedged about themselves in first person") is the same trust bar
|
|
112
|
+
* `user_asserted` facts clear by construction, so a high-confidence durable guess is routed
|
|
113
|
+
* exactly the same way from here on; medium/low confidence (or no confidence signal at all) stays
|
|
114
|
+
* a musing until/unless it's promoted via `/memory confirm` or corroboration reaches high — see
|
|
115
|
+
* `memory-service.ts`'s `promoteConfirmedFact()`, which re-sources a confirmed fact to
|
|
116
|
+
* `externally_verified` rather than relying on this function's `durable` check, since a fact
|
|
117
|
+
* queued via the low-confidence corroboration path isn't guaranteed to carry `durable: true`.
|
|
118
|
+
* `user_asserted`/`externally_verified`/qualifying `model_inferred` facts land in the durable
|
|
119
|
+
* `identity` or `preference` tier when the text itself reads as a name/preference statement and
|
|
120
|
+
* the fact earned promotion (`durable: true`); every other such fact (a stated job, location, or
|
|
121
|
+
* coding-fact-shaped claim — see `looksLikeCodingFact` — none of which are `durable` under
|
|
122
|
+
* `isDurable()` above) is `semantic`: still a stated claim about what's currently true, still
|
|
123
|
+
* eligible for contradiction detection (the "tests passed"/"tests failed" and nurse-vs-designer
|
|
124
|
+
* job-flip cases this file's admission logic exists to support), just not promoted to
|
|
125
|
+
* cross-session storage. Pure and total — every `UserFact` maps to exactly one tier, and
|
|
126
|
+
* `procedural`/`commitment` are never returned (see `TIER_RULES`'s doc comment).
|
|
127
|
+
*/
|
|
128
|
+
export declare function tierForFact(fact: UserFact): MemoryTier;
|
|
129
|
+
/** Whether `tier` counts as the Knowledge tier for contradiction-detection purposes — see harness-bridge.ts's factExtractor and TIER_RULES.*.contradictionChecked. */
|
|
130
|
+
export declare function isKnowledgeTier(tier: MemoryTier): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Extracts at most one durable fact from a user message — verbatim, not summarized. Returns []
|
|
133
|
+
* when the message doesn't look like a fact statement.
|
|
134
|
+
*
|
|
135
|
+
* Also admits anything looksLikeCodingFact (contradiction-checker.ts) recognizes, unless the
|
|
136
|
+
* message also reads as a request or a question rather than a claim — a build/test/service-state
|
|
137
|
+
* claim like "the tests passed" is exactly what the World Model's belief/contradiction machinery
|
|
138
|
+
* (CODING_FACT_MARKERS, NEGATION_PAIRS) is built to track, but FACT_MARKERS' personal-fact
|
|
139
|
+
* phrasing never matched statements like that, so no belief was ever created for the
|
|
140
|
+
* contradiction checks to compare — a "tests passed" / "tests failed" flip produced zero beliefs
|
|
141
|
+
* and thus zero contradiction detection at any layer, lexical or LLM.
|
|
142
|
+
*/
|
|
143
|
+
export declare function extractFactsFromTurn(userMessage: string, sourceTurn: string): UserFact[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ILLMClient, TokenUsage } from '@buildaharness/runtime';
|
|
2
|
+
import { FailureModeEntry } from '@buildaharness/harness';
|
|
3
|
+
/**
|
|
4
|
+
* `AUDIT_SEMANTIC_FAILURE_MATCH` gate — feature-value audit (Phase A6 of
|
|
5
|
+
* plans/feature_audit_automation_plan.html). Default **ON**: the semantic failure-mode-matcher
|
|
6
|
+
* LLM call ships enabled, so an unset / empty / truthy value keeps today's behaviour. Set to a
|
|
7
|
+
* falsy value (`0` / `false` / `off` / `no` / `disabled`) to skip the LLM call entirely and fall
|
|
8
|
+
* back to `FailureModeLibrary.match()`'s exact-string-overlap check only. Read at exactly one call
|
|
9
|
+
* site — `harness-bridge.ts`, where the `semanticFailureMatcher` host hook is wired. Same shape as
|
|
10
|
+
* `semanticContradictionEnabled()` (contradiction-checker.ts) / `llmInjectionDetectEnabled()`
|
|
11
|
+
* (trust-tagging.ts) and the harness's `supervisorEnabled()`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function semanticFailureMatchEnabled(env?: Record<string, string | undefined>): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* One LLM call checking a symptom set against the whole failure-mode library at once (never
|
|
16
|
+
* one call per entry) — layered on top of FailureModeLibrary.match()'s own exact-string-overlap
|
|
17
|
+
* check, which requires a symptom to be byte-for-byte identical to a curated one. That exact-match
|
|
18
|
+
* floor (and the shared-subject gates in detect-contradictions.ts / review-proposed-change.ts —
|
|
19
|
+
* see looksLikeCodingFact's doc comment in contradiction-checker.ts) is why decomposition-classifier.ts
|
|
20
|
+
* and plan-builder.ts prompt task descriptions to lead with their concrete subject: consistent
|
|
21
|
+
* subject vocabulary gives every lexical layer, not just this one, real overlap to match on. Since
|
|
22
|
+
* observations are free text ("Task executed: ...", "Result: ..."), exact equality against a
|
|
23
|
+
* curated list almost never happens by chance — this is what actually lets the library
|
|
24
|
+
* recognize a known failure pattern described in different words. Falls back to "no match" on
|
|
25
|
+
* any parse failure or LLM error, matching this codebase's other LLM-backed classifiers — a
|
|
26
|
+
* missed match costs nothing worse than the exact-match-only behavior this is layered on top of.
|
|
27
|
+
*/
|
|
28
|
+
export declare function checkSemanticFailureMatch(symptoms: string[], libraryEntries: readonly FailureModeEntry[], llmClient: ILLMClient, model?: string, onUsage?: (usage: TokenUsage) => void): Promise<{
|
|
29
|
+
failure_class: string;
|
|
30
|
+
confidence: number;
|
|
31
|
+
matched_pattern: string;
|
|
32
|
+
} | null>;
|