fixo-cli 1.0.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/LICENSE +201 -0
- package/README.md +530 -0
- package/dist/agent/agent-client.d.ts +108 -0
- package/dist/agent/agent-client.d.ts.map +1 -0
- package/dist/agent/agent-client.js +1247 -0
- package/dist/agent/agent-client.js.map +1 -0
- package/dist/agent/agent-pool.d.ts +20 -0
- package/dist/agent/agent-pool.d.ts.map +1 -0
- package/dist/agent/agent-pool.js +217 -0
- package/dist/agent/agent-pool.js.map +1 -0
- package/dist/agent/background-awareness.d.ts +55 -0
- package/dist/agent/background-awareness.d.ts.map +1 -0
- package/dist/agent/background-awareness.js +104 -0
- package/dist/agent/background-awareness.js.map +1 -0
- package/dist/agent/command-parser.d.ts +33 -0
- package/dist/agent/command-parser.d.ts.map +1 -0
- package/dist/agent/command-parser.js +120 -0
- package/dist/agent/command-parser.js.map +1 -0
- package/dist/agent/context-budget.d.ts +91 -0
- package/dist/agent/context-budget.d.ts.map +1 -0
- package/dist/agent/context-budget.js +219 -0
- package/dist/agent/context-budget.js.map +1 -0
- package/dist/agent/conversation.d.ts +190 -0
- package/dist/agent/conversation.d.ts.map +1 -0
- package/dist/agent/conversation.js +547 -0
- package/dist/agent/conversation.js.map +1 -0
- package/dist/agent/hooks.d.ts +72 -0
- package/dist/agent/hooks.d.ts.map +1 -0
- package/dist/agent/hooks.js +214 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/mcp-bridge.d.ts +13 -0
- package/dist/agent/mcp-bridge.d.ts.map +1 -0
- package/dist/agent/mcp-bridge.js +86 -0
- package/dist/agent/mcp-bridge.js.map +1 -0
- package/dist/agent/mcp-client.d.ts +24 -0
- package/dist/agent/mcp-client.d.ts.map +1 -0
- package/dist/agent/mcp-client.js +146 -0
- package/dist/agent/mcp-client.js.map +1 -0
- package/dist/agent/mcp-manager.d.ts +13 -0
- package/dist/agent/mcp-manager.d.ts.map +1 -0
- package/dist/agent/mcp-manager.js +84 -0
- package/dist/agent/mcp-manager.js.map +1 -0
- package/dist/agent/mcp-registry.d.ts +45 -0
- package/dist/agent/mcp-registry.d.ts.map +1 -0
- package/dist/agent/mcp-registry.js +98 -0
- package/dist/agent/mcp-registry.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +14 -0
- package/dist/agent/orchestrator.d.ts.map +1 -0
- package/dist/agent/orchestrator.js +118 -0
- package/dist/agent/orchestrator.js.map +1 -0
- package/dist/agent/parser-adapter.d.ts +120 -0
- package/dist/agent/parser-adapter.d.ts.map +1 -0
- package/dist/agent/parser-adapter.js +265 -0
- package/dist/agent/parser-adapter.js.map +1 -0
- package/dist/agent/parsers/imports.d.ts +11 -0
- package/dist/agent/parsers/imports.d.ts.map +1 -0
- package/dist/agent/parsers/imports.js +94 -0
- package/dist/agent/parsers/imports.js.map +1 -0
- package/dist/agent/parsers/shell.d.ts +23 -0
- package/dist/agent/parsers/shell.d.ts.map +1 -0
- package/dist/agent/parsers/shell.js +200 -0
- package/dist/agent/parsers/shell.js.map +1 -0
- package/dist/agent/parsers/symbols.d.ts +17 -0
- package/dist/agent/parsers/symbols.d.ts.map +1 -0
- package/dist/agent/parsers/symbols.js +103 -0
- package/dist/agent/parsers/symbols.js.map +1 -0
- package/dist/agent/permissions.d.ts +65 -0
- package/dist/agent/permissions.d.ts.map +1 -0
- package/dist/agent/permissions.js +219 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/predictive-gate.d.ts +69 -0
- package/dist/agent/predictive-gate.d.ts.map +1 -0
- package/dist/agent/predictive-gate.js +128 -0
- package/dist/agent/predictive-gate.js.map +1 -0
- package/dist/agent/provider-cooldown.d.ts +144 -0
- package/dist/agent/provider-cooldown.d.ts.map +1 -0
- package/dist/agent/provider-cooldown.js +300 -0
- package/dist/agent/provider-cooldown.js.map +1 -0
- package/dist/agent/providers-manager.d.ts +109 -0
- package/dist/agent/providers-manager.d.ts.map +1 -0
- package/dist/agent/providers-manager.js +464 -0
- package/dist/agent/providers-manager.js.map +1 -0
- package/dist/agent/repo-map.d.ts +6 -0
- package/dist/agent/repo-map.d.ts.map +1 -0
- package/dist/agent/repo-map.js +221 -0
- package/dist/agent/repo-map.js.map +1 -0
- package/dist/agent/retry.d.ts +103 -0
- package/dist/agent/retry.d.ts.map +1 -0
- package/dist/agent/retry.js +276 -0
- package/dist/agent/retry.js.map +1 -0
- package/dist/agent/search/index.d.ts +61 -0
- package/dist/agent/search/index.d.ts.map +1 -0
- package/dist/agent/search/index.js +314 -0
- package/dist/agent/search/index.js.map +1 -0
- package/dist/agent/single-agent.d.ts +76 -0
- package/dist/agent/single-agent.d.ts.map +1 -0
- package/dist/agent/single-agent.js +697 -0
- package/dist/agent/single-agent.js.map +1 -0
- package/dist/agent/skills.d.ts +22 -0
- package/dist/agent/skills.d.ts.map +1 -0
- package/dist/agent/skills.js +139 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/stream-glue.d.ts +85 -0
- package/dist/agent/stream-glue.d.ts.map +1 -0
- package/dist/agent/stream-glue.js +120 -0
- package/dist/agent/stream-glue.js.map +1 -0
- package/dist/agent/subagent.d.ts +72 -0
- package/dist/agent/subagent.d.ts.map +1 -0
- package/dist/agent/subagent.js +193 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/telemetry.d.ts +192 -0
- package/dist/agent/telemetry.d.ts.map +1 -0
- package/dist/agent/telemetry.js +400 -0
- package/dist/agent/telemetry.js.map +1 -0
- package/dist/agent/tokenizer.d.ts +42 -0
- package/dist/agent/tokenizer.d.ts.map +1 -0
- package/dist/agent/tokenizer.js +107 -0
- package/dist/agent/tokenizer.js.map +1 -0
- package/dist/agent/tool-executor.d.ts +289 -0
- package/dist/agent/tool-executor.d.ts.map +1 -0
- package/dist/agent/tool-executor.js +2519 -0
- package/dist/agent/tool-executor.js.map +1 -0
- package/dist/agent/web-impl.d.ts +2 -0
- package/dist/agent/web-impl.d.ts.map +1 -0
- package/dist/agent/web-impl.js +34 -0
- package/dist/agent/web-impl.js.map +1 -0
- package/dist/agent/web.d.ts +8 -0
- package/dist/agent/web.d.ts.map +1 -0
- package/dist/agent/web.js +8 -0
- package/dist/agent/web.js.map +1 -0
- package/dist/agent/worker-agent.d.ts +27 -0
- package/dist/agent/worker-agent.d.ts.map +1 -0
- package/dist/agent/worker-agent.js +503 -0
- package/dist/agent/worker-agent.js.map +1 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/context/fixo-md-watcher.d.ts +42 -0
- package/dist/context/fixo-md-watcher.d.ts.map +1 -0
- package/dist/context/fixo-md-watcher.js +126 -0
- package/dist/context/fixo-md-watcher.js.map +1 -0
- package/dist/context/fixo-md.d.ts +50 -0
- package/dist/context/fixo-md.d.ts.map +1 -0
- package/dist/context/fixo-md.js +118 -0
- package/dist/context/fixo-md.js.map +1 -0
- package/dist/context/todo.d.ts +65 -0
- package/dist/context/todo.d.ts.map +1 -0
- package/dist/context/todo.js +194 -0
- package/dist/context/todo.js.map +1 -0
- package/dist/git/git-manager.d.ts +33 -0
- package/dist/git/git-manager.d.ts.map +1 -0
- package/dist/git/git-manager.js +293 -0
- package/dist/git/git-manager.js.map +1 -0
- package/dist/git/git-ops.d.ts +10 -0
- package/dist/git/git-ops.d.ts.map +1 -0
- package/dist/git/git-ops.js +131 -0
- package/dist/git/git-ops.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +352 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +30 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +273 -0
- package/dist/indexer.js.map +1 -0
- package/dist/lsp/lsp-client.d.ts +24 -0
- package/dist/lsp/lsp-client.d.ts.map +1 -0
- package/dist/lsp/lsp-client.js +205 -0
- package/dist/lsp/lsp-client.js.map +1 -0
- package/dist/lsp/lsp-manager.d.ts +17 -0
- package/dist/lsp/lsp-manager.d.ts.map +1 -0
- package/dist/lsp/lsp-manager.js +154 -0
- package/dist/lsp/lsp-manager.js.map +1 -0
- package/dist/lsp/lsp-pre-save.d.ts +137 -0
- package/dist/lsp/lsp-pre-save.d.ts.map +1 -0
- package/dist/lsp/lsp-pre-save.js +245 -0
- package/dist/lsp/lsp-pre-save.js.map +1 -0
- package/dist/lsp/syntax-fallback.d.ts +83 -0
- package/dist/lsp/syntax-fallback.d.ts.map +1 -0
- package/dist/lsp/syntax-fallback.js +275 -0
- package/dist/lsp/syntax-fallback.js.map +1 -0
- package/dist/model-outcomes.d.ts +12 -0
- package/dist/model-outcomes.d.ts.map +1 -0
- package/dist/model-outcomes.js +46 -0
- package/dist/model-outcomes.js.map +1 -0
- package/dist/planner.d.ts +32 -0
- package/dist/planner.d.ts.map +1 -0
- package/dist/planner.js +163 -0
- package/dist/planner.js.map +1 -0
- package/dist/project-memory.d.ts +29 -0
- package/dist/project-memory.d.ts.map +1 -0
- package/dist/project-memory.js +349 -0
- package/dist/project-memory.js.map +1 -0
- package/dist/review.d.ts +2 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +61 -0
- package/dist/review.js.map +1 -0
- package/dist/runtime/background-jobs.d.ts +97 -0
- package/dist/runtime/background-jobs.d.ts.map +1 -0
- package/dist/runtime/background-jobs.js +331 -0
- package/dist/runtime/background-jobs.js.map +1 -0
- package/dist/runtime/credential-vault.d.ts +124 -0
- package/dist/runtime/credential-vault.d.ts.map +1 -0
- package/dist/runtime/credential-vault.js +184 -0
- package/dist/runtime/credential-vault.js.map +1 -0
- package/dist/runtime/loop-trap.d.ts +197 -0
- package/dist/runtime/loop-trap.d.ts.map +1 -0
- package/dist/runtime/loop-trap.js +420 -0
- package/dist/runtime/loop-trap.js.map +1 -0
- package/dist/runtime/policy.d.ts +15 -0
- package/dist/runtime/policy.d.ts.map +1 -0
- package/dist/runtime/policy.js +60 -0
- package/dist/runtime/policy.js.map +1 -0
- package/dist/runtime/redaction.d.ts +66 -0
- package/dist/runtime/redaction.d.ts.map +1 -0
- package/dist/runtime/redaction.js +155 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/session-snapshots.d.ts +76 -0
- package/dist/runtime/session-snapshots.d.ts.map +1 -0
- package/dist/runtime/session-snapshots.js +166 -0
- package/dist/runtime/session-snapshots.js.map +1 -0
- package/dist/runtime/staging.d.ts +205 -0
- package/dist/runtime/staging.d.ts.map +1 -0
- package/dist/runtime/staging.js +526 -0
- package/dist/runtime/staging.js.map +1 -0
- package/dist/runtime/task-session.d.ts +95 -0
- package/dist/runtime/task-session.d.ts.map +1 -0
- package/dist/runtime/task-session.js +263 -0
- package/dist/runtime/task-session.js.map +1 -0
- package/dist/runtime/worktree.d.ts +55 -0
- package/dist/runtime/worktree.d.ts.map +1 -0
- package/dist/runtime/worktree.js +175 -0
- package/dist/runtime/worktree.js.map +1 -0
- package/dist/setup-wizard.d.ts +8 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +73 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/shared/content.d.ts +43 -0
- package/dist/shared/content.d.ts.map +1 -0
- package/dist/shared/content.js +61 -0
- package/dist/shared/content.js.map +1 -0
- package/dist/shared/types.d.ts +217 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/test-runner.d.ts +5 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +42 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/ascii.d.ts +23 -0
- package/dist/ui/ascii.d.ts.map +1 -0
- package/dist/ui/ascii.js +45 -0
- package/dist/ui/ascii.js.map +1 -0
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +166 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/image-attach.d.ts +27 -0
- package/dist/ui/image-attach.d.ts.map +1 -0
- package/dist/ui/image-attach.js +100 -0
- package/dist/ui/image-attach.js.map +1 -0
- package/dist/ui/index.d.ts +18 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/markdown-stream.d.ts +91 -0
- package/dist/ui/markdown-stream.d.ts.map +1 -0
- package/dist/ui/markdown-stream.js +524 -0
- package/dist/ui/markdown-stream.js.map +1 -0
- package/dist/ui/plan-renderer.d.ts +36 -0
- package/dist/ui/plan-renderer.d.ts.map +1 -0
- package/dist/ui/plan-renderer.js +79 -0
- package/dist/ui/plan-renderer.js.map +1 -0
- package/dist/ui/prompt.d.ts +11 -0
- package/dist/ui/prompt.d.ts.map +1 -0
- package/dist/ui/prompt.js +1960 -0
- package/dist/ui/prompt.js.map +1 -0
- package/dist/ui/render-primitives.d.ts +117 -0
- package/dist/ui/render-primitives.d.ts.map +1 -0
- package/dist/ui/render-primitives.js +322 -0
- package/dist/ui/render-primitives.js.map +1 -0
- package/dist/ui/render.d.ts +133 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +547 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/session-header.d.ts +30 -0
- package/dist/ui/session-header.d.ts.map +1 -0
- package/dist/ui/session-header.js +74 -0
- package/dist/ui/session-header.js.map +1 -0
- package/dist/workspace-guard.d.ts +68 -0
- package/dist/workspace-guard.d.ts.map +1 -0
- package/dist/workspace-guard.js +168 -0
- package/dist/workspace-guard.js.map +1 -0
- package/dist/workspace-lock.d.ts +27 -0
- package/dist/workspace-lock.d.ts.map +1 -0
- package/dist/workspace-lock.js +95 -0
- package/dist/workspace-lock.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic Workspace Shadow Staging — Pillar 2 of the Phase 2 safety
|
|
3
|
+
* refactor. The problem: a direct `fs.writeFileSync` to a user's
|
|
4
|
+
* source file is a non-atomic, non-rollbackable operation. If the
|
|
5
|
+
* process is killed mid-write, the user is left with a partially
|
|
6
|
+
* truncated file. If a downstream validation step fails, the
|
|
7
|
+
* user is left with a corrupted file. Both outcomes are
|
|
8
|
+
* unacceptable for a tool that markets itself as "enterprise
|
|
9
|
+
* safe".
|
|
10
|
+
*
|
|
11
|
+
* The fix: route every file write through a `.fixo/staging/`
|
|
12
|
+
* shadow directory, validate it (Pillar 3 LSP gate will plug in
|
|
13
|
+
* here), and only then perform an atomic `fs.renameSync` swap.
|
|
14
|
+
* If anything goes wrong, restore the original from a sibling
|
|
15
|
+
* `.pending.bak` file and the user is none the wiser.
|
|
16
|
+
*
|
|
17
|
+
* Layout under `cwd`:
|
|
18
|
+
*
|
|
19
|
+
* .fixo/staging/<run-id>/
|
|
20
|
+
* <sha256(targetPath)>.pending # staged content
|
|
21
|
+
* <sha256(targetPath)>.meta.json # { targetPath, mode, createdAt }
|
|
22
|
+
*
|
|
23
|
+
* <targetPath>.pending.bak # temporary backup, only
|
|
24
|
+
* # present during commit()
|
|
25
|
+
*
|
|
26
|
+
* The staging directory is created with mode `0o700`. Pending
|
|
27
|
+
* files and their metadata are written with mode `0o600`.
|
|
28
|
+
*
|
|
29
|
+
* The manager is synchronous (writes are small, no streaming),
|
|
30
|
+
* safe to construct at the start of a run, and thread-agnostic —
|
|
31
|
+
* the run-id is the only thing that disambiguates concurrent
|
|
32
|
+
* runs against the same workspace.
|
|
33
|
+
*/
|
|
34
|
+
import crypto from 'node:crypto';
|
|
35
|
+
import fs from 'node:fs';
|
|
36
|
+
import path from 'node:path';
|
|
37
|
+
import { WorkspaceGuard } from '../workspace-guard.js';
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Errors
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
/** Thrown when a requested staged write does not exist. */
|
|
42
|
+
export class StagedWriteNotFoundError extends Error {
|
|
43
|
+
id;
|
|
44
|
+
constructor(id) {
|
|
45
|
+
super(`No staged write with id ${id}`);
|
|
46
|
+
this.name = 'StagedWriteNotFoundError';
|
|
47
|
+
this.id = id;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Thrown when commit() rolls back due to a pre-commit hook failure. */
|
|
51
|
+
export class PreCommitHookRejectedError extends Error {
|
|
52
|
+
id;
|
|
53
|
+
cause;
|
|
54
|
+
constructor(id, cause) {
|
|
55
|
+
super(`Pre-commit hook rejected staged write ${id}: ${String(cause)}`);
|
|
56
|
+
this.name = 'PreCommitHookRejectedError';
|
|
57
|
+
this.id = id;
|
|
58
|
+
this.cause = cause;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Thrown when a target path escapes the workspace root. */
|
|
62
|
+
export class StagingPathEscapeError extends Error {
|
|
63
|
+
attempted;
|
|
64
|
+
constructor(attempted) {
|
|
65
|
+
super(`Staging refused: path escapes workspace root: ${attempted}`);
|
|
66
|
+
this.name = 'StagingPathEscapeError';
|
|
67
|
+
this.attempted = attempted;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Constants
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000; // 24h
|
|
74
|
+
const STAGING_DIR_NAME = 'staging';
|
|
75
|
+
const META_SUFFIX = '.meta.json';
|
|
76
|
+
const PENDING_SUFFIX = '.pending';
|
|
77
|
+
const BACKUP_SUFFIX = '.pending.bak';
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Helpers
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
const sha256 = (input) => crypto.createHash('sha256').update(input, 'utf-8').digest('hex');
|
|
82
|
+
/** Try to chmod; ignore on platforms that don't support it. */
|
|
83
|
+
const chmodSafe = (filePath, mode) => {
|
|
84
|
+
try {
|
|
85
|
+
fs.chmodSync(filePath, mode);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// ignore
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
/** Best-effort deletion that does not throw. */
|
|
92
|
+
const rmSafe = (target) => {
|
|
93
|
+
try {
|
|
94
|
+
fs.unlinkSync(target);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// ignore
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// AtomicStagingManager
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
export class AtomicStagingManager {
|
|
104
|
+
cwd;
|
|
105
|
+
runId;
|
|
106
|
+
options;
|
|
107
|
+
/** Absolute path of the staging directory for this run. */
|
|
108
|
+
stagingDir;
|
|
109
|
+
constructor(cwd, runId, options = {}) {
|
|
110
|
+
if (!runId || !/^[A-Za-z0-9._-]+$/.test(runId)) {
|
|
111
|
+
throw new Error(`runId must match [A-Za-z0-9._-]+ (got: ${JSON.stringify(runId)})`);
|
|
112
|
+
}
|
|
113
|
+
this.cwd = path.resolve(cwd);
|
|
114
|
+
this.runId = runId;
|
|
115
|
+
this.options = {
|
|
116
|
+
ttlMs: options.ttlMs ?? DEFAULT_TTL_MS,
|
|
117
|
+
enabled: options.enabled ?? true,
|
|
118
|
+
preCommitHook: options.preCommitHook,
|
|
119
|
+
syntaxHealthCheck: options.syntaxHealthCheck,
|
|
120
|
+
};
|
|
121
|
+
this.stagingDir = path.join(this.cwd, '.fixo', STAGING_DIR_NAME, this.runId);
|
|
122
|
+
}
|
|
123
|
+
/** Ensure the staging directory exists with mode 0o700. */
|
|
124
|
+
ensureStagingDir() {
|
|
125
|
+
fs.mkdirSync(this.stagingDir, { recursive: true, mode: 0o700 });
|
|
126
|
+
chmodSafe(this.stagingDir, 0o700);
|
|
127
|
+
}
|
|
128
|
+
/** Reject paths that escape the workspace root. */
|
|
129
|
+
resolveTarget(relativeOrAbsolute) {
|
|
130
|
+
const guard = new WorkspaceGuard(this.cwd);
|
|
131
|
+
try {
|
|
132
|
+
return guard.resolve(relativeOrAbsolute, 'file');
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw new StagingPathEscapeError(relativeOrAbsolute);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Stage a file for atomic write. Writes the content to
|
|
140
|
+
* `<staging>/<sha256(target)>.pending` and a sidecar
|
|
141
|
+
* `<staging>/<sha256(target)>.meta.json` containing the target
|
|
142
|
+
* path, mode, and timestamp. Returns the staged write metadata.
|
|
143
|
+
*/
|
|
144
|
+
stage(target, content, mode = 0o644) {
|
|
145
|
+
const resolved = this.resolveTarget(target);
|
|
146
|
+
const id = sha256(resolved);
|
|
147
|
+
this.ensureStagingDir();
|
|
148
|
+
const pendingPath = path.join(this.stagingDir, `${id}${PENDING_SUFFIX}`);
|
|
149
|
+
const metaPath = path.join(this.stagingDir, `${id}${META_SUFFIX}`);
|
|
150
|
+
// Write pending content (atomic: write to temp + rename).
|
|
151
|
+
const tmpPath = `${pendingPath}.tmp`;
|
|
152
|
+
fs.writeFileSync(tmpPath, content, { encoding: 'utf-8', mode: 0o600 });
|
|
153
|
+
chmodSafe(tmpPath, 0o600);
|
|
154
|
+
fs.renameSync(tmpPath, pendingPath);
|
|
155
|
+
// Write meta sidecar.
|
|
156
|
+
const meta = {
|
|
157
|
+
targetPath: resolved,
|
|
158
|
+
mode,
|
|
159
|
+
createdAt: Date.now(),
|
|
160
|
+
};
|
|
161
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta), {
|
|
162
|
+
encoding: 'utf-8',
|
|
163
|
+
mode: 0o600,
|
|
164
|
+
});
|
|
165
|
+
chmodSafe(metaPath, 0o600);
|
|
166
|
+
return {
|
|
167
|
+
id,
|
|
168
|
+
targetPath: resolved,
|
|
169
|
+
pendingPath,
|
|
170
|
+
metaPath,
|
|
171
|
+
createdAt: meta.createdAt,
|
|
172
|
+
mode,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Read a staged write's content (lazy — only read on demand). */
|
|
176
|
+
read(id) {
|
|
177
|
+
const entry = this.readEntry(id);
|
|
178
|
+
return fs.readFileSync(entry.pendingPath, 'utf-8');
|
|
179
|
+
}
|
|
180
|
+
/** Look up a staged write by id without touching the file system further. */
|
|
181
|
+
readEntry(id) {
|
|
182
|
+
const pendingPath = path.join(this.stagingDir, `${id}${PENDING_SUFFIX}`);
|
|
183
|
+
const metaPath = path.join(this.stagingDir, `${id}${META_SUFFIX}`);
|
|
184
|
+
if (!fs.existsSync(pendingPath) || !fs.existsSync(metaPath)) {
|
|
185
|
+
throw new StagedWriteNotFoundError(id);
|
|
186
|
+
}
|
|
187
|
+
const raw = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
188
|
+
return {
|
|
189
|
+
id,
|
|
190
|
+
targetPath: raw.targetPath,
|
|
191
|
+
pendingPath,
|
|
192
|
+
metaPath,
|
|
193
|
+
createdAt: raw.createdAt,
|
|
194
|
+
mode: raw.mode,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/** List all staged writes for this run. */
|
|
198
|
+
list() {
|
|
199
|
+
if (!fs.existsSync(this.stagingDir))
|
|
200
|
+
return [];
|
|
201
|
+
const names = fs.readdirSync(this.stagingDir);
|
|
202
|
+
const entries = [];
|
|
203
|
+
for (const name of names) {
|
|
204
|
+
if (!name.endsWith(META_SUFFIX))
|
|
205
|
+
continue;
|
|
206
|
+
const id = name.slice(0, -META_SUFFIX.length);
|
|
207
|
+
try {
|
|
208
|
+
entries.push(this.readEntry(id));
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Stale meta without a pending counterpart — skip.
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return entries;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Remove a staged write without touching the target. Used by the
|
|
218
|
+
* LSP pre-save gate when it rejects a write.
|
|
219
|
+
*/
|
|
220
|
+
discard(id) {
|
|
221
|
+
const entry = this.readEntry(id);
|
|
222
|
+
rmSafe(entry.pendingPath);
|
|
223
|
+
rmSafe(entry.metaPath);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Commit a staged write to its target path. The flow is:
|
|
227
|
+
*
|
|
228
|
+
* 1. Run the optional pre-commit hook (Pillar 3 plugs in here).
|
|
229
|
+
* 2. Ensure the parent directory of the target exists.
|
|
230
|
+
* 3. If the target exists, rename it to `<target>.pending.bak`.
|
|
231
|
+
* 4. Rename the pending file to the target.
|
|
232
|
+
* 5. Delete the backup.
|
|
233
|
+
*
|
|
234
|
+
* If any step fails, the backup (if any) is restored to the
|
|
235
|
+
* target and the backup itself is removed. The pending and
|
|
236
|
+
* metadata files are always cleaned up on success.
|
|
237
|
+
*/
|
|
238
|
+
async commit(id) {
|
|
239
|
+
const entry = this.readEntry(id);
|
|
240
|
+
const target = entry.targetPath;
|
|
241
|
+
const backup = `${target}${BACKUP_SUFFIX}`;
|
|
242
|
+
const existed = fs.existsSync(target);
|
|
243
|
+
// 1. Pre-commit hook (Pillar 3 plugs in here).
|
|
244
|
+
if (this.options.preCommitHook) {
|
|
245
|
+
try {
|
|
246
|
+
await this.options.preCommitHook(entry);
|
|
247
|
+
}
|
|
248
|
+
catch (cause) {
|
|
249
|
+
// Hook rejected — discard the staged write but do NOT
|
|
250
|
+
// touch the target.
|
|
251
|
+
this.discard(id);
|
|
252
|
+
throw new PreCommitHookRejectedError(id, cause);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// 1.5 Pillar 5 / Protection 3 — structural syntax health
|
|
256
|
+
// check. Runs *after* the LSP gate and *before* the rename
|
|
257
|
+
// swap. If the staged content is syntactically broken the
|
|
258
|
+
// write is rejected and discarded; the target is preserved.
|
|
259
|
+
if (this.options.syntaxHealthCheck) {
|
|
260
|
+
const content = fs.readFileSync(entry.pendingPath, 'utf-8');
|
|
261
|
+
try {
|
|
262
|
+
await this.options.syntaxHealthCheck(entry, content);
|
|
263
|
+
}
|
|
264
|
+
catch (cause) {
|
|
265
|
+
this.discard(id);
|
|
266
|
+
throw new PreCommitHookRejectedError(id, cause);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (!this.options.enabled) {
|
|
270
|
+
// Dry-run mode: leave the staged write in place.
|
|
271
|
+
const bytes = Buffer.byteLength(fs.readFileSync(entry.pendingPath), 'utf-8');
|
|
272
|
+
return {
|
|
273
|
+
committed: false,
|
|
274
|
+
targetPath: target,
|
|
275
|
+
backupCreated: false,
|
|
276
|
+
bytesWritten: bytes,
|
|
277
|
+
committedAt: new Date().toISOString(),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
// 2. Ensure parent directory exists.
|
|
281
|
+
const parent = path.dirname(target);
|
|
282
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
283
|
+
try {
|
|
284
|
+
// 3. Back up the existing file (if any).
|
|
285
|
+
if (existed) {
|
|
286
|
+
// If a stale backup is present from a previous failed
|
|
287
|
+
// commit, clear it first.
|
|
288
|
+
rmSafe(backup);
|
|
289
|
+
fs.renameSync(target, backup);
|
|
290
|
+
}
|
|
291
|
+
// 4. Swap pending into place.
|
|
292
|
+
fs.renameSync(entry.pendingPath, target);
|
|
293
|
+
// Apply mode.
|
|
294
|
+
try {
|
|
295
|
+
fs.chmodSync(target, entry.mode);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
// ignore
|
|
299
|
+
}
|
|
300
|
+
// 5. Clear the backup.
|
|
301
|
+
if (existed)
|
|
302
|
+
rmSafe(backup);
|
|
303
|
+
const bytes = Buffer.byteLength(fs.readFileSync(target, 'utf-8'), 'utf-8');
|
|
304
|
+
// Tidy up the meta sidecar.
|
|
305
|
+
rmSafe(entry.metaPath);
|
|
306
|
+
return {
|
|
307
|
+
committed: true,
|
|
308
|
+
targetPath: target,
|
|
309
|
+
backupCreated: existed,
|
|
310
|
+
bytesWritten: bytes,
|
|
311
|
+
committedAt: new Date().toISOString(),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
// Rollback: restore the backup, remove the .pending if any.
|
|
316
|
+
try {
|
|
317
|
+
if (existed && fs.existsSync(backup)) {
|
|
318
|
+
if (fs.existsSync(target))
|
|
319
|
+
fs.unlinkSync(target);
|
|
320
|
+
fs.renameSync(backup, target);
|
|
321
|
+
}
|
|
322
|
+
else if (!existed && fs.existsSync(target)) {
|
|
323
|
+
// We created the file but the rename to target itself
|
|
324
|
+
// succeeded — only reached if chmod fails. Target is
|
|
325
|
+
// already correct; nothing to undo.
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
// Last-ditch: leave the backup in place so a human can
|
|
330
|
+
// recover. The next GC pass will clean it up.
|
|
331
|
+
}
|
|
332
|
+
// Pending may have been consumed; if not, leave it.
|
|
333
|
+
throw err;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Apply a surgical in-place edit to an existing file. The new
|
|
338
|
+
* content is staged under the same `.fixo/staging/<runId>/<id>.pending`
|
|
339
|
+
* layout and the commit step mirrors `commit()`: backup the
|
|
340
|
+
* target, atomic rename, clear the backup, clear the meta.
|
|
341
|
+
*
|
|
342
|
+
* This is functionally `stage() + commit()` collapsed into a
|
|
343
|
+
* single call, but the on-disk layout, backup semantics, and
|
|
344
|
+
* rollback path are identical. Provided so `str_replace` (and
|
|
345
|
+
* future surgical-edit tools) can route their edits through the
|
|
346
|
+
* same atomic staging pipeline as `write_file` without touching
|
|
347
|
+
* the existing `stage()` / `commit()` flow.
|
|
348
|
+
*
|
|
349
|
+
* The optional `meta` argument is recorded into `.meta.json` so
|
|
350
|
+
* the audit trail records the originator of the edit (e.g. a
|
|
351
|
+
* `str_replace` tool call vs. a `subagent`). The method never
|
|
352
|
+
* weakens the Pillar 2 atomicity guarantee: if the rename
|
|
353
|
+
* swap fails, the backup is restored and the original file is
|
|
354
|
+
* preserved byte-for-byte.
|
|
355
|
+
*/
|
|
356
|
+
async applySurgicalReplace(target, newContent, meta) {
|
|
357
|
+
const resolved = this.resolveTarget(target);
|
|
358
|
+
const id = sha256(resolved);
|
|
359
|
+
this.ensureStagingDir();
|
|
360
|
+
const pendingPath = path.join(this.stagingDir, `${id}${PENDING_SUFFIX}`);
|
|
361
|
+
const metaPath = path.join(this.stagingDir, `${id}${META_SUFFIX}`);
|
|
362
|
+
const backup = `${resolved}${BACKUP_SUFFIX}`;
|
|
363
|
+
const existed = fs.existsSync(resolved);
|
|
364
|
+
// 1. Write the new content to the .pending file (atomic via temp+rename).
|
|
365
|
+
const tmpPath = `${pendingPath}.tmp`;
|
|
366
|
+
fs.writeFileSync(tmpPath, newContent, { encoding: 'utf-8', mode: 0o600 });
|
|
367
|
+
chmodSafe(tmpPath, 0o600);
|
|
368
|
+
fs.renameSync(tmpPath, pendingPath);
|
|
369
|
+
// 2. Write the sidecar meta with audit trail.
|
|
370
|
+
const metaPayload = {
|
|
371
|
+
targetPath: resolved,
|
|
372
|
+
mode: 0o644,
|
|
373
|
+
createdAt: Date.now(),
|
|
374
|
+
reason: meta.reason,
|
|
375
|
+
actorId: meta.actorId,
|
|
376
|
+
runId: meta.runId,
|
|
377
|
+
};
|
|
378
|
+
fs.writeFileSync(metaPath, JSON.stringify(metaPayload), {
|
|
379
|
+
encoding: 'utf-8',
|
|
380
|
+
mode: 0o600,
|
|
381
|
+
});
|
|
382
|
+
chmodSafe(metaPath, 0o600);
|
|
383
|
+
// 3. Ensure parent dir exists.
|
|
384
|
+
const parent = path.dirname(resolved);
|
|
385
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
386
|
+
try {
|
|
387
|
+
// 4. Back up the existing file (if any).
|
|
388
|
+
if (existed) {
|
|
389
|
+
// Clear any stale backup from a previous failed commit.
|
|
390
|
+
rmSafe(backup);
|
|
391
|
+
fs.renameSync(resolved, backup);
|
|
392
|
+
}
|
|
393
|
+
// 5. Atomic swap of the pending file into the target.
|
|
394
|
+
fs.renameSync(pendingPath, resolved);
|
|
395
|
+
// 6. Apply file mode (best-effort across platforms).
|
|
396
|
+
try {
|
|
397
|
+
fs.chmodSync(resolved, 0o644);
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
// ignore
|
|
401
|
+
}
|
|
402
|
+
// 7. Clear backup and meta sidecar.
|
|
403
|
+
if (existed)
|
|
404
|
+
rmSafe(backup);
|
|
405
|
+
rmSafe(metaPath);
|
|
406
|
+
const bytes = Buffer.byteLength(fs.readFileSync(resolved, 'utf-8'), 'utf-8');
|
|
407
|
+
return { ok: true, path: resolved, bytes };
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
// Rollback: restore the backup, clean up the .pending if any.
|
|
411
|
+
try {
|
|
412
|
+
if (existed && fs.existsSync(backup)) {
|
|
413
|
+
if (fs.existsSync(resolved))
|
|
414
|
+
fs.unlinkSync(resolved);
|
|
415
|
+
fs.renameSync(backup, resolved);
|
|
416
|
+
}
|
|
417
|
+
else if (!existed && fs.existsSync(resolved)) {
|
|
418
|
+
// We created the file but the rename to target itself
|
|
419
|
+
// succeeded — only reached if chmod fails. Target is
|
|
420
|
+
// already correct; nothing to undo.
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
// Last-ditch: leave the backup in place so a human can
|
|
425
|
+
// recover. The next GC pass will clean it up.
|
|
426
|
+
}
|
|
427
|
+
// Pending may have been consumed; if not, leave it.
|
|
428
|
+
throw err;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Remove any staged write older than `ttlMs`. Returns the number
|
|
433
|
+
* of entries removed. Designed to be cheap at run start
|
|
434
|
+
* (typically <2ms for a few hundred entries).
|
|
435
|
+
*/
|
|
436
|
+
gc(now = Date.now()) {
|
|
437
|
+
if (!fs.existsSync(this.stagingDir))
|
|
438
|
+
return 0;
|
|
439
|
+
const cutoff = now - this.options.ttlMs;
|
|
440
|
+
let removed = 0;
|
|
441
|
+
for (const entry of this.list()) {
|
|
442
|
+
if (entry.createdAt < cutoff) {
|
|
443
|
+
this.discard(entry.id);
|
|
444
|
+
removed += 1;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return removed;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Sweep every run-id directory under `<cwd>/.fixo/staging/`.
|
|
451
|
+
* Returns the total number of expired entries removed. Called
|
|
452
|
+
* automatically at the start of every streaming run and is also
|
|
453
|
+
* exposed via the `/fixo gc` slash command.
|
|
454
|
+
*/
|
|
455
|
+
static garbageCollectAll(cwd, ttlMs) {
|
|
456
|
+
const root = path.resolve(cwd);
|
|
457
|
+
const stagingRoot = path.join(root, '.fixo', STAGING_DIR_NAME);
|
|
458
|
+
if (!fs.existsSync(stagingRoot))
|
|
459
|
+
return 0;
|
|
460
|
+
let removed = 0;
|
|
461
|
+
let runDirs;
|
|
462
|
+
try {
|
|
463
|
+
runDirs = fs.readdirSync(stagingRoot);
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
for (const runDir of runDirs) {
|
|
469
|
+
const runPath = path.join(stagingRoot, runDir);
|
|
470
|
+
let stat;
|
|
471
|
+
try {
|
|
472
|
+
stat = fs.lstatSync(runPath);
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
if (!stat.isDirectory())
|
|
478
|
+
continue;
|
|
479
|
+
// Safe: runDir names are sanitised in the constructor.
|
|
480
|
+
const mgr = new AtomicStagingManager(root, runDir, { ttlMs });
|
|
481
|
+
removed += mgr.gc();
|
|
482
|
+
}
|
|
483
|
+
return removed;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Discard every staged write for the given (cwd, runId) pair. Used
|
|
487
|
+
* when an agent is force-killed (e.g. loop-trap hard-abort) so the
|
|
488
|
+
* workspace is left in its pre-run state. Returns the number of
|
|
489
|
+
* entries removed.
|
|
490
|
+
*
|
|
491
|
+
* Best-effort: a failure to remove a single entry is logged and
|
|
492
|
+
* swallowed so the caller never sees an exception from cleanup.
|
|
493
|
+
*/
|
|
494
|
+
static rollbackAll(cwd, runId) {
|
|
495
|
+
const root = path.resolve(cwd);
|
|
496
|
+
let removed = 0;
|
|
497
|
+
let mgr;
|
|
498
|
+
try {
|
|
499
|
+
mgr = new AtomicStagingManager(root, runId);
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
return 0;
|
|
503
|
+
}
|
|
504
|
+
if (!fs.existsSync(mgr.stagingDir))
|
|
505
|
+
return 0;
|
|
506
|
+
const entries = mgr.list();
|
|
507
|
+
for (const entry of entries) {
|
|
508
|
+
try {
|
|
509
|
+
mgr.discard(entry.id);
|
|
510
|
+
removed += 1;
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
console.error(`[AtomicStagingManager.rollbackAll] failed to discard ${entry.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// Best-effort: remove the now-empty run directory.
|
|
517
|
+
try {
|
|
518
|
+
fs.rmSync(mgr.stagingDir, { recursive: true, force: true });
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
// ignore
|
|
522
|
+
}
|
|
523
|
+
return removed;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
//# sourceMappingURL=staging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/runtime/staging.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { WorkspaceGuard } from '../workspace-guard.js';
|
|
2
|
+
import type { PolicyProfile } from './policy.js';
|
|
3
|
+
export interface TaskEvent {
|
|
4
|
+
type: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface TaskSessionSummary {
|
|
9
|
+
id: string;
|
|
10
|
+
task: string;
|
|
11
|
+
model: string;
|
|
12
|
+
cwd: string;
|
|
13
|
+
startedAt: string;
|
|
14
|
+
endedAt?: string;
|
|
15
|
+
status: 'running' | 'success' | 'error';
|
|
16
|
+
modifiedFiles: string[];
|
|
17
|
+
verification: string[];
|
|
18
|
+
response?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ChangeRecord {
|
|
21
|
+
file: string;
|
|
22
|
+
beforeHash: string | null;
|
|
23
|
+
afterHash: string | null;
|
|
24
|
+
beforeExists: boolean;
|
|
25
|
+
afterExists: boolean;
|
|
26
|
+
beforeSnapshot?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class TaskSession {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly cwd: string;
|
|
31
|
+
readonly guard: WorkspaceGuard;
|
|
32
|
+
readonly policy: PolicyProfile;
|
|
33
|
+
readonly runDir: string;
|
|
34
|
+
readonly startedAt: string;
|
|
35
|
+
readonly readFiles: Map<string, string | null>;
|
|
36
|
+
readonly changedFiles: Map<string, ChangeRecord>;
|
|
37
|
+
/**
|
|
38
|
+
* Tracks which files the agent has done a *structural* pre-scan on
|
|
39
|
+
* (via `extract_symbols` / `extract_imports`). The map is read by
|
|
40
|
+
* Pillar 3 (Context-Budget Guard) to verify that a large file the
|
|
41
|
+
* LLM wants to read was first reduced to its declarations. The
|
|
42
|
+
* `noteStructuralMap` and `hasStructuralMap` helpers below are
|
|
43
|
+
* intentionally side-effect-free for tests.
|
|
44
|
+
*/
|
|
45
|
+
readonly structuralMaps: Map<string, {
|
|
46
|
+
symbols: boolean;
|
|
47
|
+
imports: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
private summary;
|
|
50
|
+
constructor(opts: {
|
|
51
|
+
cwd: string;
|
|
52
|
+
task: string;
|
|
53
|
+
model: string;
|
|
54
|
+
policy?: PolicyProfile;
|
|
55
|
+
});
|
|
56
|
+
record(type: string, data?: Record<string, unknown>): void;
|
|
57
|
+
noteRead(file: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Mark a file as having been pre-scanned structurally. The
|
|
60
|
+
* `flags` object records which dimensions were extracted so
|
|
61
|
+
* Pillar 3 can decide whether the LLM is still missing
|
|
62
|
+
* information when it later calls `read_file` on the same path.
|
|
63
|
+
*/
|
|
64
|
+
noteStructuralMap(file: string, flags: {
|
|
65
|
+
symbols: boolean;
|
|
66
|
+
imports: boolean;
|
|
67
|
+
}): void;
|
|
68
|
+
/**
|
|
69
|
+
* Returns the structural pre-scan flags recorded for a file.
|
|
70
|
+
* Returns `null` if the file has never been pre-scanned — the
|
|
71
|
+
* caller should treat this as a hard-fail for the
|
|
72
|
+
* Context-Budget Guard rule.
|
|
73
|
+
*/
|
|
74
|
+
hasStructuralMap(file: string): {
|
|
75
|
+
symbols: boolean;
|
|
76
|
+
imports: boolean;
|
|
77
|
+
} | null;
|
|
78
|
+
captureBefore(file: string): void;
|
|
79
|
+
noteChange(file: string): void;
|
|
80
|
+
canMutate(file: string): {
|
|
81
|
+
ok: boolean;
|
|
82
|
+
reason?: string;
|
|
83
|
+
};
|
|
84
|
+
addVerification(message: string): void;
|
|
85
|
+
finish(status: 'success' | 'error', response: string): void;
|
|
86
|
+
private writeSummary;
|
|
87
|
+
private writeChanges;
|
|
88
|
+
}
|
|
89
|
+
export declare function hashFile(file: string): string | null;
|
|
90
|
+
export declare function gcRuns(cwd: string, keepLimit?: number): void;
|
|
91
|
+
export declare function listRuns(cwd: string, limit?: number): TaskSessionSummary[];
|
|
92
|
+
export declare function showRun(cwd: string, id: string): string;
|
|
93
|
+
export declare function undoRun(cwd: string, id: string): string;
|
|
94
|
+
export declare function revertAgentCommit(cwd: string): string;
|
|
95
|
+
//# sourceMappingURL=task-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-session.d.ts","sourceRoot":"","sources":["../../src/runtime/task-session.ts"],"names":[],"mappings":"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"}
|