qlogicagent 2.18.2 → 2.18.3

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.
Files changed (69) hide show
  1. package/dist/agent.js +38 -24
  2. package/dist/cli.js +1 -1
  3. package/dist/index.js +515 -465
  4. package/dist/orchestration.js +11 -11
  5. package/dist/protocol.js +1 -1
  6. package/dist/skills/mcp/astraclaw-native-mcp-server.js +8 -6
  7. package/dist/types/agent/memory-recall-injection.d.ts +2 -1
  8. package/dist/types/agent/tool-loop/budget-continuation-policy.d.ts +4 -0
  9. package/dist/types/agent/tool-loop/completion-action-policy.d.ts +9 -1
  10. package/dist/types/cli/credential-vault.d.ts +6 -0
  11. package/dist/types/cli/handlers/turn-handler.d.ts +50 -1
  12. package/dist/types/cli/memory-coordinator.d.ts +4 -0
  13. package/dist/types/cli/pet-runtime.d.ts +2 -0
  14. package/dist/types/cli/rpc-registry.d.ts +11 -0
  15. package/dist/types/cli/runtime-hook-bootstrap.d.ts +2 -0
  16. package/dist/types/cli/skill-tools-bootstrap.d.ts +5 -0
  17. package/dist/types/cli/stdio-acp-request-host.d.ts +2 -1
  18. package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +1 -0
  19. package/dist/types/cli/stdio-server.d.ts +4 -0
  20. package/dist/types/cli/task-distillation-coordinator.d.ts +79 -0
  21. package/dist/types/cli/tool-bootstrap-core-registration.d.ts +24 -0
  22. package/dist/types/cli/turn-core.d.ts +0 -6
  23. package/dist/types/cli/turn-project-router.d.ts +9 -0
  24. package/dist/types/contracts/hooks.d.ts +3 -0
  25. package/dist/types/contracts/turn-event.d.ts +8 -4
  26. package/dist/types/orchestration/agent-instance.d.ts +4 -0
  27. package/dist/types/orchestration/context/reactive-compact.d.ts +4 -6
  28. package/dist/types/orchestration/error-handling/retry-loop.d.ts +0 -22
  29. package/dist/types/orchestration/goal-loop-coordinator.d.ts +6 -0
  30. package/dist/types/orchestration/goal-mode-adapters.d.ts +20 -1
  31. package/dist/types/orchestration/goal-run-types.d.ts +10 -0
  32. package/dist/types/orchestration/skill-improvement.d.ts +7 -2
  33. package/dist/types/orchestration/workflow/run-history-store.d.ts +2 -0
  34. package/dist/types/orchestration/workflow/workflow-runtime.d.ts +8 -0
  35. package/dist/types/protocol/wire/acp-agent-management.d.ts +3 -0
  36. package/dist/types/protocol/wire/agent-events.d.ts +2 -2
  37. package/dist/types/protocol/wire/memory-provider-lifecycle.d.ts +3 -0
  38. package/dist/types/protocol/wire/notification-payloads.d.ts +27 -0
  39. package/dist/types/runtime/config/tunable-defaults.d.ts +6 -0
  40. package/dist/types/runtime/execution/memory-decay.d.ts +5 -1
  41. package/dist/types/runtime/hooks/context-compression.d.ts +5 -0
  42. package/dist/types/runtime/hooks/memory-hooks.d.ts +10 -0
  43. package/dist/types/runtime/infra/acp-detector.d.ts +8 -0
  44. package/dist/types/runtime/infra/acp-protocol-adapter.d.ts +10 -0
  45. package/dist/types/runtime/infra/agent-process.d.ts +6 -0
  46. package/dist/types/runtime/infra/astraclaw-capabilities.d.ts +9 -0
  47. package/dist/types/runtime/infra/working-materials-store.d.ts +8 -14
  48. package/dist/types/runtime/pet/pet-profile-service.d.ts +7 -0
  49. package/dist/types/runtime/pet/petdex-forge-service.d.ts +3 -1
  50. package/dist/types/runtime/ports/memory-provider.d.ts +2 -0
  51. package/dist/types/runtime/ports/project-memory-store.d.ts +2 -0
  52. package/dist/types/runtime/prompt/environment-context.d.ts +15 -3
  53. package/dist/types/runtime/prompt/fresh-workspace-evidence.d.ts +7 -0
  54. package/dist/types/runtime/prompt/instruction-loader.d.ts +0 -1
  55. package/dist/types/runtime/session/inbound-upload-persistence.d.ts +4 -0
  56. package/dist/types/runtime/session/session-catalog.d.ts +8 -0
  57. package/dist/types/runtime/session/session-resume.d.ts +5 -0
  58. package/dist/types/runtime/session/session-transcript-store.d.ts +8 -1
  59. package/dist/types/skills/mcp/mcp-manager.d.ts +25 -1
  60. package/dist/types/skills/memory/local-memory-provider.d.ts +14 -0
  61. package/dist/types/skills/memory/local-store.d.ts +2 -0
  62. package/dist/types/skills/memory/memdir.d.ts +8 -0
  63. package/dist/types/skills/memory/task-distillation.d.ts +148 -0
  64. package/dist/types/skills/tools/search-tool.d.ts +6 -0
  65. package/dist/types/skills/tools/shell/task-output.d.ts +2 -0
  66. package/package.json +1 -1
  67. package/dist/types/agent/tool-loop/skill-instruction-policy.d.ts +0 -7
  68. package/dist/types/agent/tool-loop/tool-guardrails.d.ts +0 -24
  69. package/dist/types/cli/turn-skill-autopersist.d.ts +0 -22
@@ -10,6 +10,10 @@ export interface BudgetContinuationPolicyInput {
10
10
  thinkingBlocks: readonly ThinkingBlock[];
11
11
  getBudgetContinuationMessage(usagePct: number, totalUsed: number, tokenBudget?: number): string;
12
12
  log: Pick<AgentLogger, "info">;
13
+ /** The loop's per-turn recovery trace (surfaced on the final `end` event). Stop
14
+ * reasons are recorded here as `budget_continuation_stop:<reason>` so an engine-side
15
+ * end of nudging is visible to callers/UI, not only in the debug log. */
16
+ recoveryTrace?: Map<string, number>;
13
17
  }
14
18
  export interface BudgetContinuationPolicyDecision {
15
19
  messages: unknown[];
@@ -17,7 +17,15 @@ export interface CompletionActionPolicyDecision {
17
17
  transition: ToolLoopTransition;
18
18
  }
19
19
  export declare function findMissingExplicitRequiredFiles(inputMessages: readonly ChatMessage[], messages: unknown[]): string[];
20
- export declare function buildExplicitRequiredFilesFailureContent(input: {
20
+ /**
21
+ * Terminal-path NOTE (not a replacement): when a forced stop ends the turn with
22
+ * explicitly-requested output files still missing, this returns an engine-attributed
23
+ * note to APPEND to whatever the turn is already ending with. It used to return a
24
+ * "<FAIL-marker> ..." string that REPLACED the model's final text — an extraction
25
+ * misfire then handed the user an engine-authored FAIL verdict the model never made
26
+ * (2026-07-07 review, F5). The engine reports evidence; it does not speak as the model.
27
+ */
28
+ export declare function buildMissingRequiredFilesNote(input: {
21
29
  inputMessages: readonly ChatMessage[];
22
30
  messages: unknown[];
23
31
  reason: string;
@@ -24,6 +24,12 @@ export interface CredentialSummary {
24
24
  updatedAt: string;
25
25
  /** Secret-free hints for pickers (e.g. apiKey header name, oauth2 scopes). */
26
26
  meta?: Record<string, unknown>;
27
+ /**
28
+ * Set when the on-disk envelope could not be read/parsed. The entry is unusable (get()
29
+ * throws) but stays VISIBLE in list() so the list-driven UI shows the loss instead of the
30
+ * credential silently vanishing; delete works on it.
31
+ */
32
+ corrupt?: true;
27
33
  }
28
34
  /**
29
35
  * Secret payload shapes by type (validated on create):
@@ -4,6 +4,9 @@
4
4
  */
5
5
  import { type ModelPurpose } from "../../runtime/infra/model-registry.js";
6
6
  import { type UnderstandMediaClient, type UnderstandMediaKind } from "../media-understanding.js";
7
+ import { type InstructionFileInfo } from "../../runtime/prompt/instruction-loader.js";
8
+ import type { HookRegistry } from "../../contracts/hooks.js";
9
+ import type { AppendMessageOutcome } from "../../runtime/session/session-transcript-store.js";
7
10
  import type { PermissionMetadataResolver, ToolCatalog } from "../../runtime/ports/index.js";
8
11
  import type { ChatMessage, TokenUsage, ToolDefinition, TurnConfig } from "../../agent/types.js";
9
12
  import type { AgentRpcRequest } from "../../protocol/wire/agent-rpc.js";
@@ -59,6 +62,40 @@ export interface FirstTurnTitleGenerationDeps {
59
62
  log(message: string): void;
60
63
  }
61
64
  export declare function runFirstTurnTitleGeneration(deps: FirstTurnTitleGenerationDeps): Promise<void>;
65
+ /**
66
+ * Loud trace for fire-and-forget background persistence work inside the turn pipeline.
67
+ * Replaces the old silent `.catch(() => {})` pattern (judgment-over-mechanism: a failed write
68
+ * must at least be diagnosable in the engine log, never swallowed).
69
+ */
70
+ export declare function logTurnBackgroundFailure(context: string, err: unknown): void;
71
+ /**
72
+ * Per-turn transcript-persist failure reporter. A lost transcript write means the conversation is
73
+ * missing messages after a reload — that must be VISIBLE: console.error every failure with turn
74
+ * context, and emit ONE `turn.recovery` notification per turn (first failure only) so the user is
75
+ * told without flooding the stream when several writes of the same turn fail.
76
+ * "skipped-deleted" is the legal late-write no-op on a deleted session — not a failure, no trace.
77
+ */
78
+ export declare function createTranscriptPersistFailureReporter(deps: {
79
+ turnId: string;
80
+ sessionId: string;
81
+ sendNotification(method: string, params: Record<string, unknown>): void;
82
+ }): (which: string, outcome: AppendMessageOutcome | {
83
+ rejected: unknown;
84
+ }) => void;
85
+ /**
86
+ * Load the INSTRUCTIONS.md / project-rules block for a turn. A load failure means the WHOLE turn
87
+ * runs without the user's standing rules — the old inline catch called that "non-fatal" and left
88
+ * zero trace. Degrading is still the right call (the turn can proceed), but it must be visible:
89
+ * console.error + a `turn.recovery` note in the turn event stream.
90
+ * `loadInstructions` is injectable so tests can force a failure; defaults to getInstructions.
91
+ */
92
+ export declare function loadInstructionBlockForTurn(deps: {
93
+ cwd: string;
94
+ turnId: string;
95
+ hooks?: HookRegistry;
96
+ sendNotification(method: string, params: Record<string, unknown>): void;
97
+ loadInstructions?(cwd: string, hooks?: HookRegistry): Promise<InstructionFileInfo[]>;
98
+ }): Promise<string | undefined>;
62
99
  export declare function hydrateTurnConfigFromModelMetadata(config: TurnConfig): TurnConfig;
63
100
  export declare function hydrateAttachmentReferenceUrlsForTurn(messages: ChatMessage[]): ChatMessage[];
64
101
  export declare function getFocusedAttachmentToolNamesForTurn(messages: ChatMessage[]): Set<string> | null;
@@ -85,8 +122,20 @@ export declare function augmentLastUserMessageContent(messages: ChatMessage[], m
85
122
  * invisible to those user-intent scans. The original array/objects are never mutated.
86
123
  */
87
124
  export declare function injectSkillContextBeforeLastUser(messages: ChatMessage[], skillContext: string): ChatMessage[];
125
+ /**
126
+ * Insert the per-turn DOMAIN guidance block as a SYSTEM-role message immediately BEFORE the
127
+ * last user message (LLM view only) — the prompt-cache alignment path.
128
+ *
129
+ * Same rationale as injectSkillContextBeforeLastUser: the domain block carries markdown headers
130
+ * ("# Doing Tasks"), the word "artifact", and example file paths — baking it into the user message
131
+ * would poison the user-intent scans (final-marker extraction, artifact counting, round/tool
132
+ * budgets) that read `role === "user"` content. A system message keeps the model bound to the
133
+ * guidance while staying invisible to those scans. Kept out of the system PROMPT so a domain
134
+ * switch never re-encodes the byte-stable prefix or the conversation history. The original
135
+ * array/objects are never mutated.
136
+ */
137
+ export declare function injectDomainGuidanceBeforeLastUser(messages: ChatMessage[], domainGuidance: string): ChatMessage[];
88
138
  export declare function getFocusedAttachmentModelPurposeForTurn(messages: ChatMessage[]): FocusedAttachmentModelPurpose | null;
89
- export declare function requiresPreToolPreambleForTurn(messages: readonly ChatMessage[]): boolean;
90
139
  export declare function refreshPermissionCheckerToolMeta(permissionChecker: PermissionMetadataResolver | null | undefined, tools: ToolDefinition[]): void;
91
140
  export declare function handleUserResponse(this: TurnControlHandlerHost, msg: AgentRpcRequest): void;
92
141
  /**
@@ -25,6 +25,10 @@ export interface RegisterMemoryRuntimeHooksDeps {
25
25
  apiKey: string;
26
26
  model: string;
27
27
  } | null;
28
+ /** Part B recall visibility: forwards turn.memory_recall to the client. */
29
+ sendNotification?: (method: string, params: Record<string, unknown>) => void;
30
+ /** V3.2 usage 仪表落盘目录(memory-hooks 记录 procedure 复用维度)。 */
31
+ profileMemoryDir?: () => string;
28
32
  }
29
33
  export declare function registerMemoryRuntimeHooks(deps: RegisterMemoryRuntimeHooksDeps): MemoryProviderState;
30
34
  export interface RegisterMemoryToolDeps {
@@ -23,6 +23,8 @@ export interface PetdexForgeOutput {
23
23
  spritesheet: Buffer;
24
24
  validation: PetdexValidationReport;
25
25
  productionRun?: PetdexProductionRun;
26
+ /** Jobs accepted WITHOUT a working vision-QA verdict (QA call failed → fail-open, but traced). */
27
+ qaSkippedJobs?: string[];
26
28
  mediaUsage?: {
27
29
  provider: string;
28
30
  model: string;
@@ -36,7 +36,18 @@ export type RpcMethodHandler = (msg: AgentRpcRequest) => void;
36
36
  * The pattern mirrors the existing createDreamHandlerHost / createMultiAgentHandlerHost
37
37
  * adapters, just applied uniformly across every RPC domain.
38
38
  */
39
+ export interface TaskDistillationRpcSurface {
40
+ runPass(reason: "manual"): Promise<object>;
41
+ listProposals(): unknown[];
42
+ dismissProposal(id: string): boolean;
43
+ acknowledgeProposal(id: string): boolean;
44
+ getMetrics(): object;
45
+ promote(id: string): Promise<object>;
46
+ demote(id: string): Promise<object>;
47
+ }
39
48
  export interface RpcHandlerHosts {
49
+ /** R3/V3 蒸馏晋升面(惰性:首调时构造 coordinator)。 */
50
+ getTaskDistillation?: () => TaskDistillationRpcSurface;
40
51
  config: ConfigHandlerHost;
41
52
  control: ControlHandlerHost;
42
53
  session: SessionHandlerHost;
@@ -28,6 +28,8 @@ export interface RuntimeHookBootstrapDeps {
28
28
  apiKey: string;
29
29
  };
30
30
  sendNotification?(method: string, params: Record<string, unknown>): void;
31
+ /** V3.2 usage 仪表落盘目录。 */
32
+ profileMemoryDir?: () => string;
31
33
  }
32
34
  export interface RuntimeHookBootstrapResult {
33
35
  hooks: HookRegistry;
@@ -26,3 +26,8 @@ export declare function configureSkillToolsBootstrap(host: SkillToolsHost, deps:
26
26
  * content path, never the raw supporting-file write).
27
27
  */
28
28
  export declare function resolveSupportingFilePath(skillDir: string, filePath: string): string | null;
29
+ /**
30
+ * 读技能文件:ENOENT(文件不存在)→ null(语义 = 技能/文件未安装);其余失败
31
+ * (EPERM/EISDIR 等)抛出真实错误 —— 读失败不能伪装成"技能不存在"。导出仅为单测。
32
+ */
33
+ export declare function readSkillFileOrNull(label: string, filePath: string): Promise<string | null>;
@@ -16,6 +16,7 @@ export type StdioAcpRequestHostSource = Pick<CliAcpRequestHandlerHost, "activeTu
16
16
  petRuntime: unknown;
17
17
  projectMemoryStoreFactory: unknown;
18
18
  toolCatalog: unknown;
19
+ taskDistillation: unknown;
19
20
  cancelBackgroundTasksForSession(sessionId?: string): void;
20
21
  configureTurnMedia(config: Record<string, unknown> | undefined, turnId: string): void;
21
22
  drainPendingTaskNotifications(): string[];
@@ -25,5 +26,5 @@ export type StdioAcpRequestHostSource = Pick<CliAcpRequestHandlerHost, "activeTu
25
26
  };
26
27
  /** Host members the shared turn pipeline reads/writes — keep in sync with
27
28
  * `grep -oE "this\.[a-zA-Z]+" src/cli/handlers/turn-handler.ts | sort -u`. */
28
- export declare const TURN_PIPELINE_HOST_MEMBERS: readonly ["activeTurn", "configureTurnMedia", "currentHooks", "currentModel", "currentTurnId", "drainPendingTaskNotifications", "getActiveProjectRoot", "lastAssistantMessageForExtract", "lastUserMessageForAutoExtract", "log", "mcpReady", "memdir", "pendingAskUser", "permissionChecker", "petRuntime", "projectMemoryStoreFactory", "resolveAgent", "resolveClientForPurpose", "sendNotification", "sendResponse", "sessionHistory", "sessionState", "setActiveWorkdir", "toolCatalog"];
29
+ export declare const TURN_PIPELINE_HOST_MEMBERS: readonly ["activeTurn", "configureTurnMedia", "currentHooks", "currentModel", "currentTurnId", "drainPendingTaskNotifications", "getActiveProjectRoot", "lastAssistantMessageForExtract", "lastUserMessageForAutoExtract", "log", "mcpReady", "memdir", "pendingAskUser", "permissionChecker", "petRuntime", "projectMemoryStoreFactory", "resolveAgent", "resolveClientForPurpose", "sendNotification", "sendResponse", "sessionHistory", "sessionState", "setActiveWorkdir", "taskDistillation", "toolCatalog"];
29
30
  export declare function createStdioAcpRequestHandlerHost(host: StdioAcpRequestHostSource): CliAcpRequestHandlerHost;
@@ -10,6 +10,7 @@ type DirectStdioRpcHost = RpcHandlerHosts["config"] & RpcHandlerHosts["control"]
10
10
  readonly workflowHandlerHost: RpcHandlerHosts["workflow"];
11
11
  };
12
12
  type StdioRpcAdapterSource = DirectStdioRpcHost & {
13
+ ensureTaskDistillation(): import("./rpc-registry.js").TaskDistillationRpcSurface;
13
14
  activeTurn: RpcHandlerHosts["turn"]["activeTurn"];
14
15
  currentSessionId: NonNullable<RpcHandlerHosts["session"]["currentSessionId"]>;
15
16
  currentModel: NonNullable<RpcHandlerHosts["session"]["currentModel"]>;
@@ -8,6 +8,7 @@
8
8
  * Protocol: each message is a single JSON-RPC 2.0 object.
9
9
  * The physical I/O layer is abstracted via the Transport interface.
10
10
  */
11
+ import { TaskDistillationCoordinator } from "./task-distillation-coordinator.js";
11
12
  import type { Transport } from "./transport.js";
12
13
  import type { Agent } from "../agent/agent.js";
13
14
  import type { TurnConfig } from "../agent/types.js";
@@ -195,6 +196,9 @@ export declare class StdioServer {
195
196
  * Opening the DB is cheap and side-effect-free (list() does not embed).
196
197
  */
197
198
  ensureMemoryProvider(): void;
199
+ private _taskDistillation;
200
+ get taskDistillation(): TaskDistillationCoordinator;
201
+ ensureTaskDistillation(): TaskDistillationCoordinator;
198
202
  resolveAgent(config: TurnConfig): Agent | null;
199
203
  private invalidateResolvedLlmCache;
200
204
  /** Emit an `agents.status` notification when a child process state changes. */
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Task distillation coordinator (R3 wiring) — 候选采集/空闲窗蒸馏/晋升通知。
3
+ * 纯逻辑在 skills/memory/task-distillation.ts;本模块只做依赖装配与生命周期:
4
+ * · recordTurn: turn-handler 回合完成处调用(轻量,embedding 异步)
5
+ * · runPass: idle 空闲窗(stdio-server onIdle 并联)与 memory.distill RPC 共用入口
6
+ * · 蒸馏产物: category=procedure 进长期记忆(tag distilled@v1+sig),召回自然带出;
7
+ * LLM 摘要(dream 同款小模型)失败时降级确定性模板 —— 蒸馏永不因模型不可用而丢样本。
8
+ * · 晋升(spec:唯一技能入口): accessCount ≥ 阈值且未被负反馈沉底 → system.activity 推荐。
9
+ */
10
+ import { type PromotionMetrics, type CandidateStoreFile, type PromotionProposal } from "../skills/memory/task-distillation.js";
11
+ export interface TaskDistillationDeps {
12
+ profileMemoryDir: () => string;
13
+ /** 签名 embedding;null=不可用(候选照存但不参与聚类,宁严勿松) */
14
+ embed: (text: string) => Promise<Float32Array | null>;
15
+ /** 落库:返回是否成功(候选只在成功后标 distilled) */
16
+ addProcedure: (text: string, tags: string[]) => Promise<boolean>;
17
+ /** 小模型摘要(dream 同款);null/失败 → 降级模板 */
18
+ llmExtract?: (prompt: string) => Promise<string | null>;
19
+ /** 晋升扫描数据源:全部 distilled 条目 {id,text,accessCount,importance} */
20
+ listDistilled: () => Promise<Array<{
21
+ id: string;
22
+ text: string;
23
+ accessCount: number;
24
+ importance: number;
25
+ }>>;
26
+ /** V3 promote/demote:archive(技能接棒)/unarchive(降格回归) */
27
+ setMemoryArchived: (id: string, archived: boolean) => boolean;
28
+ sendNotification: (method: string, params: Record<string, unknown>) => void;
29
+ log: (message: string) => void;
30
+ }
31
+ export interface RecordTurnInput {
32
+ sessionId: string;
33
+ promptHead: string;
34
+ toolSequence: string[];
35
+ durationMs: number;
36
+ ok: boolean;
37
+ }
38
+ export interface DistillPassResult {
39
+ distilled: number;
40
+ promotionsNotified: number;
41
+ pendingCandidates: number;
42
+ }
43
+ export declare class TaskDistillationCoordinator {
44
+ private readonly deps;
45
+ private readonly turnIndexBySession;
46
+ /** 已通知过晋升的条目(进程内防重复打扰;跨重启重复通知无害) */
47
+ private readonly promotionNotified;
48
+ constructor(deps: TaskDistillationDeps);
49
+ /** 回合完成时采集候选。异步(embedding 网络调用),错误吞掉不碰回合主链。 */
50
+ recordTurn(input: RecordTurnInput): Promise<void>;
51
+ /** 空闲窗/手动共用的蒸馏 pass。 */
52
+ runPass(reason: "idle" | "manual"): Promise<DistillPassResult>;
53
+ private renderProcedure;
54
+ /** 晋升扫描(spec:技能的唯一产生入口):复用达标且未被负反馈沉底 → 写持久提议。
55
+ * V3.1:提议是持久待办(promotion-proposals.json),UI 双入口消费;activity 仅作日志。 */
56
+ private scanPromotions;
57
+ listProposals(): PromotionProposal[];
58
+ /** V3.2 仪表(接受率/降格率/自动档解锁态);技能激活计数由 skill-lifecycle useCount 承载。 */
59
+ getMetrics(): PromotionMetrics;
60
+ /** 自动升格开场确认卡「知道了」。 */
61
+ acknowledgeProposal(procedureId: string): boolean;
62
+ dismissProposal(procedureId: string): boolean;
63
+ /** 升格执行链:配方→SKILL.md(LLM 格式转换,降级模板)→落盘+lifecycle(默认启用)
64
+ * →procedure archive(技能接棒,拍板①)→proposal accepted。 */
65
+ promote(procedureId: string, opts?: {
66
+ auto?: boolean;
67
+ }): Promise<{
68
+ ok: boolean;
69
+ skillName?: string;
70
+ error?: string;
71
+ }>;
72
+ /** 降格(可撤销是信任基础):删技能+unarchive 回 procedure;proposal 置 dismissed(用户明确否定,不再纠缠)。 */
73
+ demote(procedureId: string): Promise<{
74
+ ok: boolean;
75
+ error?: string;
76
+ }>;
77
+ private renderSkillMarkdown;
78
+ }
79
+ export declare function buildCandidateStoreSnapshot(profileMemoryDir: string): CandidateStoreFile;
@@ -32,3 +32,27 @@ export declare function registerLocalCoreTools(context: LocalCoreToolRegistratio
32
32
  export declare function validateExecCommand(command: string, workdir: string, groupMode?: boolean): string | null;
33
33
  /** office/pdf 文档扩展名 → mime;非文档返回 undefined。导出仅为单测。 */
34
34
  export declare function documentMimeForExtension(ext: string): string | undefined;
35
+ export interface RipgrepGrepOutcome {
36
+ matches: Array<{
37
+ path: string;
38
+ line: number;
39
+ text: string;
40
+ }>;
41
+ truncated: boolean;
42
+ /** Model-facing incompleteness note (search tool appends it to content). */
43
+ note?: string;
44
+ }
45
+ /**
46
+ * Map an rg execFile exit to a grep outcome. Returns null for real errors (caller
47
+ * rejects and falls back to native grep). When rg was killed (30s timeout or the
48
+ * 10MB maxBuffer cap) the stdout is a partial result set cut mid-stream: it must be
49
+ * flagged truncated with a model-visible note — otherwise the model treats a
50
+ * mid-flight kill as the complete match set. Exported for unit tests only.
51
+ */
52
+ export declare function resolveRipgrepOutcome(err: (Error & {
53
+ killed?: boolean;
54
+ code?: number | string | null;
55
+ }) | null, stdout: string, options: {
56
+ headLimit?: number;
57
+ offset?: number;
58
+ }): RipgrepGrepOutcome | null;
@@ -27,8 +27,6 @@ export interface TurnCoreAgent {
27
27
  export interface TurnCoreHooks {
28
28
  /** Invoked for every side event handled by `forwardTurnSideEvent` (e.g. tool-call accounting). */
29
29
  onSideEvent?: (event: TurnEvent) => void;
30
- /** Transform assistant content before it is emitted in `turn.end` (e.g. literal-response requirements). */
31
- transformContent?: (content: string) => string;
32
30
  /** Extra work after `turn.end` is emitted (usage tracking, `turn.usage_update`, transcript persistence). */
33
31
  onEnd?: (event: Extract<TurnEvent, {
34
32
  type: "end";
@@ -37,10 +35,6 @@ export interface TurnCoreHooks {
37
35
  onError?: (event: Extract<TurnEvent, {
38
36
  type: "error";
39
37
  }>) => void;
40
- /** Handle a `skill_instruction` event (notify + auto-persist). */
41
- onSkillInstruction?: (event: Extract<TurnEvent, {
42
- type: "skill_instruction";
43
- }>) => void;
44
38
  }
45
39
  export interface TurnCoreResult {
46
40
  content: string;
@@ -13,6 +13,15 @@ export interface TurnProjectRoutingResult {
13
13
  sessionProjectId?: string;
14
14
  projectHintStale: boolean;
15
15
  staleProjectHintContext?: StaleProjectHintContext;
16
+ /**
17
+ * Set when the turn's config CARRIES a projectId that could not be resolved to a registered
18
+ * project. The caller must treat this as fatal for the turn (reject it) — silently falling back
19
+ * to the active project root would run every file read/write of the turn in the WRONG workspace
20
+ * (docs/judgment-over-mechanism.md: failures must be visible, never silently degraded).
21
+ * A session with NO projectId at all (legacy session) is NOT an error — it legitimately anchors
22
+ * to the active project (sessionProjectRoot) and only leaves a host.log trace.
23
+ */
24
+ projectResolutionError?: string;
16
25
  }
17
26
  export declare function routeTurnProjectContext(params: {
18
27
  config?: Record<string, unknown>;
@@ -123,6 +123,9 @@ export interface HookContextMap {
123
123
  };
124
124
  "memory.after_recall": HookTurnContext & {
125
125
  blockCount?: number;
126
+ recalledSummaries?: string[];
127
+ injectedCount?: number;
128
+ droppedCount?: number;
126
129
  };
127
130
  "subagent.started": HookSubagentContext;
128
131
  "subagent.stopped": HookSubagentContext;
@@ -21,6 +21,14 @@ export type SkillInstruction = SkillCreateInstruction | SkillImproveInstruction;
21
21
  export type TurnEvent = {
22
22
  type: "start";
23
23
  turnId: string;
24
+ /**
25
+ * Effective per-turn budgets (rounds / total tool calls) after engine caps and
26
+ * intent-based floors. Echoed at turn start so gateways/UIs can see the ceiling
27
+ * the loop actually runs under — a caller request silently clamped to the hard
28
+ * cap would otherwise be an invisible engine-imposed limit.
29
+ */
30
+ effectiveMaxRounds?: number;
31
+ effectiveMaxToolCalls?: number;
24
32
  } | {
25
33
  type: "delta";
26
34
  turnId: string;
@@ -47,10 +55,6 @@ export type TurnEvent = {
47
55
  error: string;
48
56
  code?: string;
49
57
  usage?: WireTokenUsage;
50
- } | {
51
- type: "skill_instruction";
52
- turnId: string;
53
- instruction: SkillInstruction;
54
58
  } | {
55
59
  type: "tool_result";
56
60
  turnId: string;
@@ -33,6 +33,10 @@ export interface ProductCallbacks {
33
33
  onTaskFailed?: (productId: string, taskId: string, error: string) => void;
34
34
  onCheckpointed?: (productId: string, timestamp: string) => void;
35
35
  onBudgetWarning?: (productId: string, usedTokens: number, maxTotalTokens: number, percentage: number) => void;
36
+ /** Budget hard limit hit → the run auto-paused. The 100% counterpart of onBudgetWarning (80%): the
37
+ * warning notified the user while the actual auto-pause was log-only — the strongest budget
38
+ * intervention must be at least as loud as its warning. `reason` says WHICH limit tripped. */
39
+ onBudgetExceeded?: (productId: string, usedTokens: number, maxTotalTokens: number | undefined, reason: string) => void;
36
40
  onCompleted?: (productId: string, summary: string, phase: Extract<ProductPhase, "completed" | "failed">) => void;
37
41
  /** DAG topology resolved and sent to client for visualization. */
38
42
  onDagTopology?: (productId: string, nodes: {
@@ -12,8 +12,6 @@
12
12
  * - Tool delta re-injection (new/removed tools since last compact)
13
13
  */
14
14
  export interface ReactiveCompactConfig {
15
- /** Maximum consecutive auto-compact failures before giving up (CC: 3). */
16
- maxConsecutiveFailures: number;
17
15
  /** Minimum messages to keep after reactive compact. */
18
16
  minMessagesAfterCompact: number;
19
17
  /** Target token usage after compact (percentage of context window). */
@@ -50,8 +48,6 @@ export interface PostCompactRestorationPayload {
50
48
  */
51
49
  export declare function buildPostCompactRestorationMessage(payload: PostCompactRestorationPayload): string | null;
52
50
  export interface ReactiveCompactState {
53
- /** Number of consecutive compact failures. */
54
- consecutiveFailures: number;
55
51
  /** Whether reactive compact has been attempted in this turn. */
56
52
  attemptedThisTurn: boolean;
57
53
  /** Last compact timestamp. */
@@ -61,9 +57,11 @@ export interface ReactiveCompactState {
61
57
  }
62
58
  export declare function createReactiveCompactState(): ReactiveCompactState;
63
59
  /**
64
- * Determine if reactive compact should be attempted.
60
+ * Determine if reactive compact should be attempted. The once-per-turn latch is the
61
+ * real loop guard; there is intentionally no failure counter (a zombie counter that
62
+ * nothing incremented used to live here).
65
63
  */
66
- export declare function shouldAttemptReactiveCompact(state: ReactiveCompactState, config?: ReactiveCompactConfig): boolean;
64
+ export declare function shouldAttemptReactiveCompact(state: ReactiveCompactState): boolean;
67
65
  /**
68
66
  * Calculate the tool delta since last compact.
69
67
  */
@@ -1,25 +1,3 @@
1
- export declare function executeBoundedRetryLoop<TResult>(params: {
2
- maxIterations: number;
3
- onRetryLimit: (params: {
4
- iterations: number;
5
- maxIterations: number;
6
- }) => Promise<TResult> | TResult;
7
- executeIteration: (params: {
8
- iteration: number;
9
- }) => Promise<{
10
- kind: "continue";
11
- } | {
12
- kind: "return";
13
- result: TResult;
14
- }>;
15
- }): Promise<TResult>;
16
- export declare function resolveScaledRetryIterations(params: {
17
- candidateCount: number;
18
- baseIterations?: number;
19
- perCandidateIterations?: number;
20
- minIterations?: number;
21
- maxIterations?: number;
22
- }): number;
23
1
  export declare function isForegroundSource(source: string | undefined): boolean;
24
2
  /** Is this a transient capacity error (429 or 529/overloaded)? */
25
3
  export declare function isTransientCapacityError(status: number | undefined): boolean;
@@ -60,6 +60,12 @@ export declare class GoalLoopCoordinator {
60
60
  * (finishPhase). Honest-fail ONLY if resume itself throws — a started phase is recovered, never lost,
61
61
  * but progress is never fabricated. Bounded by an abort handle so pause() can still drain it. */
62
62
  private recoverCrashedPhase;
63
+ /** #4: classify how an in-flight phase's throw should land. A user pause aborts the signal (whatever
64
+ * error then surfaces → "user_pause"); the adapter's GOAL_DRAIN_TIMEOUT_MS wall throws an AbortError
65
+ * WITHOUT the signal being aborted, tagged pauseReason="drain_timeout" (untagged AbortErrors from
66
+ * simpler runner ports default to drain_timeout — the only engine-side AbortError source). Anything
67
+ * else is a real failure → undefined (the caller honest-FAILs). */
68
+ private pauseReasonOf;
63
69
  /** I3: true when the loaded state shows a phase that started (currentProductId set) but never reached
64
70
  * its assessment/boundary — i.e. a process died mid-phase. Inspects the durable event log because
65
71
  * the snapshot alone can't distinguish "just started" from "started and crashed". */
@@ -3,6 +3,12 @@ import type { AcpDetector } from "../runtime/infra/acp-detector.js";
3
3
  import type { ProductOrchestrator } from "./agent-instance.js";
4
4
  import type { LeaderPort, PhaseRunnerPort } from "./goal-loop-coordinator.js";
5
5
  import { type AcceptanceCriterion, type AcceptanceDelta, type PhaseSpec } from "./goal-run-types.js";
6
+ /**
7
+ * #2 verify 输出的头尾截断:测试/构建命令的失败摘要通常在输出**末尾**(框架的 summary 行),裸
8
+ * slice(0,N) 保头丢尾会把真正的失败原因截掉,判官只能看到无关的开头。超限时保留头尾各半,并在
9
+ * 中间插入可见的省略注记(对齐 ASSESS 路径 "…(已截断)" 的风格 —— 截断必须留痕,不静默)。
10
+ */
11
+ export declare function capVerifyOutput(text: string, cap?: number): string;
6
12
  /**
7
13
  * Deterministic runtime verification — the cc/codex-style "the runner OBSERVES the result" applied to
8
14
  * the judge, run EVERY phase as a continuous regression gate (not a one-time entry ticket). For each
@@ -88,9 +94,22 @@ export declare function parsePhaseSpec(reply: string, availableAgentIds: string[
88
94
  * - `passed` delta: keep only evidence items with a non-empty `source` AND non-empty `quote`, AND
89
95
  * whose `source` is PRIMARY — i.e. it matches one of the run's actual `changedFiles` (exact or
90
96
  * basename/suffix match, since the judge may cite a relative path) OR is the literal `"output"`.
91
- * If, after filtering, a passed delta has zero evidence items, DROP it (do not flip)and log.
97
+ * If, after filtering, a passed delta has zero evidence items, do NOT flip it demote it to a
98
+ * VISIBLE `pending` note delta (#1③: it reaches the phase_assessed event, the progress summary and
99
+ * the next phase's "受阻原因", instead of vanishing with only an engine log line).
92
100
  * - `failed` / other deltas: kept as-is (their reason is informational; failed needs no evidence).
93
101
  */
94
102
  export declare function validateAssessDeltas(rawDeltas: AcceptanceDelta[], changedFiles: string[], log?: {
95
103
  warn(msg: string): void;
96
104
  }): AcceptanceDelta[];
105
+ /**
106
+ * #1②: the judge-prompt view of this phase's project changed files. The PROMPT is windowed to stay
107
+ * bounded, but the truncation is DISCLOSED in-band — a hidden remainder must not read as "没有更多改动"
108
+ * (and the whitelist gate in assess() always uses the untruncated set, so citing an unlisted-but-real
109
+ * file still counts as primary evidence).
110
+ */
111
+ export declare const ASSESS_FILES_WINDOW = 50;
112
+ export declare function buildProjectFilesBlock(allFiles: string[], window?: number): string;
113
+ /** Build the evidence block for the judge from a live Product status (task outputs + changed files).
114
+ * Exported for the #3 regression test: the >ASSESS_MAX_TASKS window note must never silently vanish. */
115
+ export declare function buildEvidenceBlock(status: ReturnType<ProductOrchestrator["getStatus"]>): string;
@@ -5,6 +5,10 @@ export declare const GOAL_DRAIN_TIMEOUT_MS: number;
5
5
  export declare const GOAL_UNREACHABLE_MIN_STREAK = 2;
6
6
  export type GoalRunStatus = "running" | "ended";
7
7
  export type GoalPauseState = "running" | "draining" | "paused";
8
+ /** Why a run is paused: the user's explicit pause vs the engine's GOAL_DRAIN_TIMEOUT_MS wall expiring
9
+ * on its own. Carried on the `paused` event payload, the snapshot and goal.run_state_changed so an
10
+ * engine-imposed pause is never indistinguishable from a user action (限制必须可见,不静默)。 */
11
+ export type GoalPauseReason = "user_pause" | "drain_timeout";
8
12
  export type GoalEndReason = "done" | "stopped" | "failed";
9
13
  export type AcceptanceStatus = "pending" | "passed" | "failed" | "superseded";
10
14
  /** FINAL evidence type (I9 — not staged). source = file path / check name; quote = cited excerpt. */
@@ -44,6 +48,10 @@ export interface PhaseSpec {
44
48
  criterionId: string;
45
49
  reason: string;
46
50
  }[];
51
+ /** fail-open 打标:critique 判官坏 JSON 重试后仍失败,本计划未经精修直接执行。 */
52
+ critiqueSkipped?: boolean;
53
+ /** 截断收据:超 MAX_TASKS_PER_PHASE 被丢弃的任务数(其对应标准仍未通过,下一阶段会重新规划)。 */
54
+ droppedTaskCount?: number;
47
55
  }
48
56
  /** Output of assess() — one per criterion the phase touched. */
49
57
  export interface AcceptanceDelta {
@@ -85,6 +93,8 @@ export interface PersistedGoalRunState {
85
93
  agentPool: string[];
86
94
  wallClockStartedAt: string;
87
95
  pausedAt?: string;
96
+ /** #4: how the run became paused (user_pause / drain_timeout) — cleared on resume. */
97
+ pauseReason?: GoalPauseReason;
88
98
  stopReason?: string;
89
99
  endReason?: GoalEndReason;
90
100
  failedReason?: string;
@@ -1,6 +1,11 @@
1
1
  /**
2
- * Skill self-learning: decides whether a completed turn should
3
- * trigger skill creation or improvement instructions.
2
+ * Task-pattern learning gates (R3 蒸馏管道的候选判定基建)。
3
+ *
4
+ * 原消费者(tool-loop 回合内即时产技能路径)已于 2026-07-07 整链废弃删除——
5
+ * 即时产出无法验证做法正确性,且其产物是用户永远看不见的默认禁用技能(死链)。
6
+ * 本模块的门槛判定/模式签名/冷却状态机保留,作为 R3 任务后蒸馏的候选采集核心
7
+ * (docs/memory-layering-and-distillation-spec.md):蒸馏产 procedure 记忆,
8
+ * 高复用 procedure 晋升为技能(默认启用——质量闸已前移到真实复用数据)。
4
9
  *
5
10
  * Guards against proliferation:
6
11
  * - Project-level pattern repetition: same workflow signature must appear
@@ -34,6 +34,8 @@ export interface RunNodeRecord {
34
34
  cacheHit?: boolean;
35
35
  /** Per-node disposition; "failed" with a surviving run = onError errorPort/continue (D32). */
36
36
  nodeStatus?: "completed" | "failed";
37
+ /** Engine-imposed limit surfaced on this node (e.g. a loop forced out at its iteration cap). */
38
+ warning?: string;
37
39
  }
38
40
  export interface RunHistoryEntry {
39
41
  runId: string;
@@ -59,6 +59,9 @@ export interface NodeRunStats {
59
59
  cacheHit: boolean;
60
60
  /** Final per-node disposition (errorPort/continue keep the run alive but mark failed). */
61
61
  status: "completed" | "failed";
62
+ /** Engine-imposed limit surfaced on this node (e.g. a loop forced out at its iteration cap) —
63
+ * rendered into the run history so caps are visible in the run record, never silent. */
64
+ warning?: string;
62
65
  }
63
66
  export interface RunResult {
64
67
  status: "completed" | "failed" | "paused";
@@ -156,6 +159,11 @@ export declare class WorkflowRuntime {
156
159
  /** Loop entry: fire the "loop" port once to kick the first iteration. */
157
160
  private enterLoop;
158
161
  private decideLoopBack;
162
+ /** A loop forced out at its maxIterations cap (the scheduler marks error="loop_cap_reached:N",
163
+ * which previously had NO consumer — the run just took the "done" port as if the loop finished
164
+ * naturally). Surface it as a node-level warning: a warn log line + a trace entry the run history
165
+ * renders (run-history-store.buildNodeRecords), so the engine-imposed cap is visible in the record. */
166
+ private surfaceLoopCap;
159
167
  /** Loop again? No condition → loop until the scheduler's maxIterations cap. */
160
168
  private evalLoopCondition;
161
169
  /** Collect inputs for a node from completed upstream outputs along forward data edges. */
@@ -243,6 +243,9 @@ export interface SoloSpecJudgeParams {
243
243
  export interface SoloSpecJudgeResult {
244
244
  ok: boolean;
245
245
  issues: string[];
246
+ /** True when ok=true came from a SKIPPED judgement (no LLM / judge call failed) — an unjudged
247
+ * soft-gate pass, not a real "spec reviewed OK". Fail-open stays, but honestly labeled. */
248
+ judgeSkipped?: boolean;
246
249
  }
247
250
  /** x/workflow.chat RPC params(M4 自动化页对话式搭图/改图)。history 含到本轮的完整对话;
248
251
  * currentWorkflow 为已有图的渲染文本(改图上下文,前端从 store 提供)。 */