@aiassesstech/sam 0.3.15 → 0.4.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.
Files changed (49) hide show
  1. package/README.md +41 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/pipeline/types.d.ts +26 -0
  7. package/dist/pipeline/types.d.ts.map +1 -1
  8. package/dist/pipeline/types.js +9 -0
  9. package/dist/pipeline/types.js.map +1 -1
  10. package/dist/plugin.d.ts.map +1 -1
  11. package/dist/plugin.js +240 -12
  12. package/dist/plugin.js.map +1 -1
  13. package/dist/tools/engine-session-manager.d.ts +18 -0
  14. package/dist/tools/engine-session-manager.d.ts.map +1 -0
  15. package/dist/tools/engine-session-manager.js +29 -0
  16. package/dist/tools/engine-session-manager.js.map +1 -0
  17. package/dist/tools/sam-artifact.d.ts +2 -1
  18. package/dist/tools/sam-artifact.d.ts.map +1 -1
  19. package/dist/tools/sam-artifact.js +15 -2
  20. package/dist/tools/sam-artifact.js.map +1 -1
  21. package/dist/tools/sam-engineer-diff.d.ts +39 -0
  22. package/dist/tools/sam-engineer-diff.d.ts.map +1 -0
  23. package/dist/tools/sam-engineer-diff.js +61 -0
  24. package/dist/tools/sam-engineer-diff.js.map +1 -0
  25. package/dist/tools/sam-engineer-resume.d.ts +34 -0
  26. package/dist/tools/sam-engineer-resume.d.ts.map +1 -0
  27. package/dist/tools/sam-engineer-resume.js +91 -0
  28. package/dist/tools/sam-engineer-resume.js.map +1 -0
  29. package/dist/tools/sam-engineer-status.d.ts +34 -0
  30. package/dist/tools/sam-engineer-status.d.ts.map +1 -0
  31. package/dist/tools/sam-engineer-status.js +66 -0
  32. package/dist/tools/sam-engineer-status.js.map +1 -0
  33. package/dist/tools/sam-engineer-terminate.d.ts +41 -0
  34. package/dist/tools/sam-engineer-terminate.d.ts.map +1 -0
  35. package/dist/tools/sam-engineer-terminate.js +88 -0
  36. package/dist/tools/sam-engineer-terminate.js.map +1 -0
  37. package/dist/tools/sam-engineer.d.ts +60 -0
  38. package/dist/tools/sam-engineer.d.ts.map +1 -0
  39. package/dist/tools/sam-engineer.js +195 -0
  40. package/dist/tools/sam-engineer.js.map +1 -0
  41. package/dist/tools/sam-pipeline.d.ts.map +1 -1
  42. package/dist/tools/sam-pipeline.js +10 -0
  43. package/dist/tools/sam-pipeline.js.map +1 -1
  44. package/dist/tools/sam-status.d.ts +2 -1
  45. package/dist/tools/sam-status.d.ts.map +1 -1
  46. package/dist/tools/sam-status.js +11 -3
  47. package/dist/tools/sam-status.js.map +1 -1
  48. package/openclaw.plugin.json +62 -0
  49. package/package.json +3 -2
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # @aiassesstech/sam
2
+
3
+ Sam — Chief Engineer plugin for OpenClaw. Engineering pipeline management, Docker sandbox execution, autonomous code execution, and fleet-bus communications.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @aiassesstech/sam
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ```bash
14
+ npx @aiassesstech/sam setup --model anthropic/claude-haiku-4-5
15
+ ```
16
+
17
+ ## Tools
18
+
19
+ | Tool | Description |
20
+ |------|-------------|
21
+ | `sam_status` | Current agent state, pipeline summary, sandbox/fleet status |
22
+ | `sam_pipeline` | View engineering pipeline with filters (active/blocked/complete) |
23
+ | `sam_request` | Create, update, or close Engineering Requests |
24
+ | `sam_report` | Generate summary, detailed, or debt reports |
25
+ | `sam_execute` | Run code in Docker sandbox (Node.js, Python, bash) |
26
+ | `sam_sandbox` | Manage sandbox lifecycle (status, build, cleanup) |
27
+ | `sam_test` | Run test suites in sandbox (vitest, jest, pytest, custom) |
28
+ | `sam_artifact` | List, package, and clean up build artifacts |
29
+ | `sam_fleet_task_status` | Report ER status to Jessie via fleet-bus |
30
+ | `sam_fleet_task_complete` | Report ER completion with artifact reference |
31
+
32
+ ## Architecture
33
+
34
+ - **PipelineManager** — Engineering Request lifecycle (INTAKE → ANALYSIS → BUILD → SELF-REVIEW → ARCHIE-REVIEW → DELIVERED)
35
+ - **SandboxManager** — Docker container lifecycle with resource limits
36
+ - **DirectMemoryWriter** — Filesystem-based memory persistence (compatible with Mighty Mark vector search)
37
+ - **Fleet-bus integration** — Cross-agent task coordination with Jessie
38
+
39
+ ## Repository
40
+
41
+ Part of the [compsi](https://github.com/spehargreg/compsi) monorepo — `packages/sam/`.
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export type { PipelineStage, EngineeringRequest, PipelineData, SamStatusResult,
8
8
  export { PIPELINE_STAGES, STAGE_ORDER, DEFAULT_CONFIG } from './pipeline/types.js';
9
9
  export type { FleetContext } from './tools/sam-fleet-tools.js';
10
10
  export type { MemoryWriterLike } from './memory/sam-memory.js';
11
+ export { EngineSessionManager } from './tools/engine-session-manager.js';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEnF,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,aAAa,EACb,UAAU,EACV,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEnF,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC"}
package/dist/index.js CHANGED
@@ -5,4 +5,5 @@ export { SamMemory } from './memory/sam-memory.js';
5
5
  export { DirectMemoryWriter } from './memory/direct-writer.js';
6
6
  export { SandboxManager } from './sandbox/sandbox-manager.js';
7
7
  export { PIPELINE_STAGES, STAGE_ORDER, DEFAULT_CONFIG } from './pipeline/types.js';
8
+ export { EngineSessionManager } from './tools/engine-session-manager.js';
8
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAa9D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAa9D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAInF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC"}
@@ -19,6 +19,12 @@ export interface EngineeringRequest {
19
19
  deliveredAt?: string;
20
20
  buildAttempts: number;
21
21
  notes: string[];
22
+ engineSessionId?: string;
23
+ engineTurnCount?: number;
24
+ engineCostUsd?: number;
25
+ engineAuditHead?: string;
26
+ engineWorktreePath?: string;
27
+ engineLastGrilloVerdict?: 'allow' | 'allow_with_comment' | 'block';
22
28
  }
23
29
  export interface PipelineData {
24
30
  version: number;
@@ -44,6 +50,13 @@ export interface SamStatusResult {
44
50
  status: 'unavailable' | 'available' | 'busy';
45
51
  };
46
52
  fleetBus: 'connected' | 'observer' | 'standalone';
53
+ engine?: {
54
+ status: 'disabled' | 'enabled' | 'active';
55
+ activeSessions: number;
56
+ activeErIds: string[];
57
+ model: string;
58
+ grilloFailMode: string;
59
+ };
47
60
  }
48
61
  export interface PipelineFilter {
49
62
  filter?: 'all' | 'active' | 'blocked' | 'complete';
@@ -68,6 +81,19 @@ export interface SamPluginConfig {
68
81
  artifactRetentionDays: number;
69
82
  telegramToken?: string;
70
83
  telegramChatId?: string;
84
+ engineEnabled: boolean;
85
+ anthropicApiKey?: string;
86
+ engineModel?: string;
87
+ worktreeBasePath?: string;
88
+ maxBudgetUsd?: number;
89
+ maxBudgetTokens?: number;
90
+ maxIterations?: number;
91
+ sessionTimeoutMs?: number;
92
+ grilloFailMode?: 'fail_closed' | 'fail_open';
93
+ jessieResponseTimeoutMs?: number;
94
+ grilloEndpoint?: string;
95
+ noahEndpoint?: string;
96
+ jessieEndpoint?: string;
71
97
  }
72
98
  export declare const DEFAULT_CONFIG: SamPluginConfig;
73
99
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,UAAU,GACV,OAAO,GACP,aAAa,GACb,eAAe,GACf,WAAW,CAAC;AAEhB,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAO1C,CAAC;AAEX,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAOrD,CAAC;AAIF,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAID,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE;QACP,MAAM,EAAE,aAAa,GAAG,WAAW,GAAG,MAAM,CAAC;KAC9C,CAAC;IACF,QAAQ,EAAE,WAAW,GAAG,UAAU,GAAG,YAAY,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;CACpD;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CACxC;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,cAAc,EAAE,eAM5B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"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"}
@@ -26,5 +26,14 @@ export const DEFAULT_CONFIG = {
26
26
  sandboxImage: 'sam-sandbox:latest',
27
27
  artifactDir: '.sam-artifacts',
28
28
  artifactRetentionDays: 7,
29
+ engineEnabled: false,
30
+ engineModel: 'claude-sonnet-4-6',
31
+ worktreeBasePath: '/root/sam/worktrees',
32
+ maxBudgetUsd: 10.0,
33
+ maxBudgetTokens: 500_000,
34
+ maxIterations: 50,
35
+ sessionTimeoutMs: 1_800_000,
36
+ grilloFailMode: 'fail_closed',
37
+ jessieResponseTimeoutMs: 1_800_000,
29
38
  };
30
39
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,QAAQ;IACR,UAAU;IACV,OAAO;IACP,aAAa;IACb,eAAe;IACf,WAAW;CACH,CAAC;AAEX,MAAM,CAAC,MAAM,WAAW,GAAkC;IACxD,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,eAAe,EAAE,CAAC;IAClB,WAAW,EAAE,CAAC;CACf,CAAC;AA+EF,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,WAAW;IACpB,cAAc,EAAE,KAAK;IACrB,YAAY,EAAE,oBAAoB;IAClC,WAAW,EAAE,gBAAgB;IAC7B,qBAAqB,EAAE,CAAC;CACzB,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,QAAQ;IACR,UAAU;IACV,OAAO;IACP,aAAa;IACb,eAAe;IACf,WAAW;CACH,CAAC;AAEX,MAAM,CAAC,MAAM,WAAW,GAAkC;IACxD,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,eAAe,EAAE,CAAC;IAClB,WAAW,EAAE,CAAC;CACf,CAAC;AA6GF,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,WAAW;IACpB,cAAc,EAAE,KAAK;IACrB,YAAY,EAAE,oBAAoB;IAClC,WAAW,EAAE,gBAAgB;IAC7B,qBAAqB,EAAE,CAAC;IACxB,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,mBAAmB;IAChC,gBAAgB,EAAE,qBAAqB;IACvC,YAAY,EAAE,IAAI;IAClB,eAAe,EAAE,OAAO;IACxB,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,SAAS;IAC3B,cAAc,EAAE,aAAa;IAC7B,uBAAuB,EAAE,SAAS;CACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA0FH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QA+WxC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA4GH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAucxC"}
package/dist/plugin.js CHANGED
@@ -34,6 +34,12 @@ import { createExecuteTool } from './tools/sam-execute.js';
34
34
  import { createSandboxTool } from './tools/sam-sandbox.js';
35
35
  import { createTestTool } from './tools/sam-test.js';
36
36
  import { createArtifactTool } from './tools/sam-artifact.js';
37
+ import { createEngineerTool } from './tools/sam-engineer.js';
38
+ import { createEngineerStatusTool } from './tools/sam-engineer-status.js';
39
+ import { createEngineerDiffTool } from './tools/sam-engineer-diff.js';
40
+ import { createEngineerResumeTool } from './tools/sam-engineer-resume.js';
41
+ import { createEngineerTerminateTool } from './tools/sam-engineer-terminate.js';
42
+ import { EngineSessionManager } from './tools/engine-session-manager.js';
37
43
  import { SamMemory } from './memory/sam-memory.js';
38
44
  import { SandboxManager } from './sandbox/sandbox-manager.js';
39
45
  import { DEFAULT_CONFIG } from './pipeline/types.js';
@@ -45,7 +51,6 @@ function resolveOpenClawHome() {
45
51
  function loadOpenClawConfig() {
46
52
  const candidates = [
47
53
  path.join(resolveOpenClawHome(), 'openclaw.json'),
48
- path.join(process.env.HOME || '~', '.clawdbot', 'openclaw.json'),
49
54
  ];
50
55
  for (const configPath of candidates) {
51
56
  try {
@@ -76,6 +81,19 @@ function resolveConfig(api) {
76
81
  artifactRetentionDays: raw.artifactRetentionDays ?? DEFAULT_CONFIG.artifactRetentionDays,
77
82
  telegramToken: raw.telegramToken,
78
83
  telegramChatId: raw.telegramChatId,
84
+ engineEnabled: raw.engineEnabled ?? DEFAULT_CONFIG.engineEnabled,
85
+ anthropicApiKey: raw.anthropicApiKey,
86
+ engineModel: raw.engineModel ?? DEFAULT_CONFIG.engineModel,
87
+ worktreeBasePath: raw.worktreeBasePath ?? DEFAULT_CONFIG.worktreeBasePath,
88
+ maxBudgetUsd: raw.maxBudgetUsd ?? DEFAULT_CONFIG.maxBudgetUsd,
89
+ maxBudgetTokens: raw.maxBudgetTokens ?? DEFAULT_CONFIG.maxBudgetTokens,
90
+ maxIterations: raw.maxIterations ?? DEFAULT_CONFIG.maxIterations,
91
+ sessionTimeoutMs: raw.sessionTimeoutMs ?? DEFAULT_CONFIG.sessionTimeoutMs,
92
+ grilloFailMode: raw.grilloFailMode ?? DEFAULT_CONFIG.grilloFailMode,
93
+ jessieResponseTimeoutMs: raw.jessieResponseTimeoutMs ?? DEFAULT_CONFIG.jessieResponseTimeoutMs,
94
+ grilloEndpoint: raw.grilloEndpoint,
95
+ noahEndpoint: raw.noahEndpoint,
96
+ jessieEndpoint: raw.jessieEndpoint,
79
97
  };
80
98
  }
81
99
  // ── Tool Registration Helper ─────────────────────────────────────
@@ -106,6 +124,14 @@ export default function register(api) {
106
124
  let validatedToolFactory = null;
107
125
  let validationSchemas = {};
108
126
  let validationBusinessRules = {};
127
+ // Engine Bridge (Phase 3) — session manager + deferred bridge loader
128
+ const engineSessions = new EngineSessionManager();
129
+ let bridgeLoader = null;
130
+ if (cfg.engineEnabled) {
131
+ const bridgeMod = '@aiassesstech/sam-engine-bridge';
132
+ bridgeLoader = () => import(bridgeMod);
133
+ console.log(`[sam] Engine bridge enabled — model: ${cfg.engineModel}, grilloFailMode: ${cfg.grilloFailMode}`);
134
+ }
109
135
  const getFleetBusStatus = () => fleetBusState;
110
136
  function validationErrorResponse(message) {
111
137
  return {
@@ -113,7 +139,7 @@ export default function register(api) {
113
139
  isError: true,
114
140
  };
115
141
  }
116
- const ENFORCE_TOOLS = new Set(['sam_execute', 'sam_sandbox']);
142
+ const ENFORCE_TOOLS = new Set(['sam_execute', 'sam_sandbox', 'sam_engineer']);
117
143
  let alertBus = null;
118
144
  const fleetAlertingMod = '@aiassesstech/fleet-alerting';
119
145
  import(fleetAlertingMod)
@@ -138,7 +164,7 @@ export default function register(api) {
138
164
  return { ok: true, params: result };
139
165
  }
140
166
  // ── Phase 1: Management Tools (always available) ────────────
141
- const statusTool = createStatusTool(pipeline, cfg, getFleetBusStatus);
167
+ const statusTool = createStatusTool(pipeline, cfg, getFleetBusStatus, engineSessions);
142
168
  const origStatusExec = statusTool.execute.bind(statusTool);
143
169
  statusTool.execute = async function (_toolCallId, params) {
144
170
  const v = await validateToolParams('sam_status', _toolCallId, params);
@@ -208,7 +234,7 @@ export default function register(api) {
208
234
  return origTestExec(_toolCallId, v.params);
209
235
  };
210
236
  registerTool(api, testTool);
211
- const artifactTool = createArtifactTool(sandbox);
237
+ const artifactTool = createArtifactTool(sandbox, engineSessions);
212
238
  const origArtifactExec = artifactTool.execute.bind(artifactTool);
213
239
  artifactTool.execute = async function (_toolCallId, params) {
214
240
  const v = await validateToolParams('sam_artifact', _toolCallId, params);
@@ -240,6 +266,54 @@ export default function register(api) {
240
266
  };
241
267
  registerTool(api, fleetTaskCompleteTool);
242
268
  console.log('[sam] Fleet tools registered: sam_fleet_task_status, sam_fleet_task_complete (fleet context pending)');
269
+ // ── Phase 4: Engine Tools (always registered, engine checked at call time) ───
270
+ // Per rule 155: unconditional registration — availability checked in execute().
271
+ const engineerTool = createEngineerTool(pipeline, cfg, engineSessions, () => samMemory, bridgeLoader);
272
+ const origEngineerExec = engineerTool.execute.bind(engineerTool);
273
+ engineerTool.execute = async function (_toolCallId, params) {
274
+ const v = await validateToolParams('sam_engineer', _toolCallId, params);
275
+ if (!v.ok)
276
+ return validationErrorResponse(v.message);
277
+ return origEngineerExec(_toolCallId, v.params);
278
+ };
279
+ registerTool(api, engineerTool);
280
+ const engineerStatusTool = createEngineerStatusTool(engineSessions);
281
+ const origEngStatusExec = engineerStatusTool.execute.bind(engineerStatusTool);
282
+ engineerStatusTool.execute = async function (_toolCallId, params) {
283
+ const v = await validateToolParams('sam_engineer_status', _toolCallId, params);
284
+ if (!v.ok)
285
+ return validationErrorResponse(v.message);
286
+ return origEngStatusExec(_toolCallId, v.params);
287
+ };
288
+ registerTool(api, engineerStatusTool);
289
+ const engineerDiffTool = createEngineerDiffTool(engineSessions);
290
+ const origEngDiffExec = engineerDiffTool.execute.bind(engineerDiffTool);
291
+ engineerDiffTool.execute = async function (_toolCallId, params) {
292
+ const v = await validateToolParams('sam_engineer_diff', _toolCallId, params);
293
+ if (!v.ok)
294
+ return validationErrorResponse(v.message);
295
+ return origEngDiffExec(_toolCallId, v.params);
296
+ };
297
+ registerTool(api, engineerDiffTool);
298
+ const engineerResumeTool = createEngineerResumeTool(pipeline, engineSessions);
299
+ const origEngResumeExec = engineerResumeTool.execute.bind(engineerResumeTool);
300
+ engineerResumeTool.execute = async function (_toolCallId, params) {
301
+ const v = await validateToolParams('sam_engineer_resume', _toolCallId, params);
302
+ if (!v.ok)
303
+ return validationErrorResponse(v.message);
304
+ return origEngResumeExec(_toolCallId, v.params);
305
+ };
306
+ registerTool(api, engineerResumeTool);
307
+ const engineerTerminateTool = createEngineerTerminateTool(pipeline, engineSessions, () => samMemory);
308
+ const origEngTermExec = engineerTerminateTool.execute.bind(engineerTerminateTool);
309
+ engineerTerminateTool.execute = async function (_toolCallId, params) {
310
+ const v = await validateToolParams('sam_engineer_terminate', _toolCallId, params);
311
+ if (!v.ok)
312
+ return validationErrorResponse(v.message);
313
+ return origEngTermExec(_toolCallId, v.params);
314
+ };
315
+ registerTool(api, engineerTerminateTool);
316
+ console.log(`[sam] Engine tools registered: sam_engineer, sam_engineer_status, sam_engineer_diff, sam_engineer_resume, sam_engineer_terminate (engine=${cfg.engineEnabled ? 'active' : 'inactive'})`);
243
317
  // ── Command: /sam ──────────────────────────────────────────
244
318
  api.registerCommand({
245
319
  name: 'sam',
@@ -250,14 +324,20 @@ export default function register(api) {
250
324
  text: '# Sam — Chief Engineer\n\n' +
251
325
  'Use Sam\'s tools for engineering pipeline management:\n\n' +
252
326
  '**Pipeline Management:**\n' +
253
- '- **sam_status** — Current state: active ERs, sandbox, fleet-bus\n' +
327
+ '- **sam_status** — Current state: active ERs, sandbox, fleet-bus, engine\n' +
254
328
  '- **sam_pipeline** — Full engineering pipeline view with filters\n' +
255
329
  '- **sam_request** — Create, update, or close Engineering Requests\n' +
256
330
  '- **sam_report** — Engineering reports (summary, detailed, debt)\n\n' +
257
- '**Fleet Communications (Phase 2):**\n' +
331
+ '**Autonomous Engineering Engine:**\n' +
332
+ '- **sam_engineer** — Start/continue an autonomous engineering session for an ER\n' +
333
+ '- **sam_engineer_status** — Session state, cost, files changed, Grillo verdicts\n' +
334
+ '- **sam_engineer_diff** — Git diff from the engine\'s worktree\n' +
335
+ '- **sam_engineer_resume** — Resume a paused session with optional new guidance\n' +
336
+ '- **sam_engineer_terminate** — Hard stop a session (commits in-flight work)\n\n' +
337
+ '**Fleet Communications:**\n' +
258
338
  '- **sam_fleet_task_status** — Report ER stage change to Jessie\n' +
259
339
  '- **sam_fleet_task_complete** — Signal ER completion to Jessie\n\n' +
260
- '**Sandbox (Phase 3):**\n' +
340
+ '**Sandbox:**\n' +
261
341
  '- **sam_execute** — Run code in Docker sandbox\n' +
262
342
  '- **sam_sandbox** — Manage sandbox lifecycle\n' +
263
343
  '- **sam_test** — Run test suites in sandbox\n' +
@@ -281,7 +361,7 @@ export default function register(api) {
281
361
  // ── Prompt Shield Integration (Behavioral Validation) ───────────
282
362
  const promptShieldMod = '@aiassesstech/prompt-shield';
283
363
  import(promptShieldMod)
284
- .then(({ createValidatedToolHandler, sam_execute: samExecuteSchema, SAM_EXECUTE_BUSINESS_RULES, sam_sandbox: samSandboxSchema, sam_status: samStatusSchema, sam_pipeline: samPipelineSchema, sam_request: samRequestSchema, sam_report: samReportSchema, sam_test: samTestSchema, sam_artifact: samArtifactSchema, sam_fleet_task_status: samFleetTaskStatusSchema, sam_fleet_task_complete: samFleetTaskCompleteSchema, }) => {
364
+ .then(({ createValidatedToolHandler, sam_execute: samExecuteSchema, SAM_EXECUTE_BUSINESS_RULES, sam_sandbox: samSandboxSchema, sam_status: samStatusSchema, sam_pipeline: samPipelineSchema, sam_request: samRequestSchema, sam_report: samReportSchema, sam_test: samTestSchema, sam_artifact: samArtifactSchema, sam_fleet_task_status: samFleetTaskStatusSchema, sam_fleet_task_complete: samFleetTaskCompleteSchema, sam_engineer: samEngineerSchema, SAM_ENGINEER_BUSINESS_RULES, sam_engineer_status: samEngineerStatusSchema, sam_engineer_diff: samEngineerDiffSchema, sam_engineer_resume: samEngineerResumeSchema, sam_engineer_terminate: samEngineerTerminateSchema, }) => {
285
365
  validatedToolFactory = createValidatedToolHandler;
286
366
  validationSchemas = {
287
367
  sam_execute: samExecuteSchema,
@@ -294,11 +374,17 @@ export default function register(api) {
294
374
  sam_artifact: samArtifactSchema,
295
375
  sam_fleet_task_status: samFleetTaskStatusSchema,
296
376
  sam_fleet_task_complete: samFleetTaskCompleteSchema,
377
+ sam_engineer: samEngineerSchema,
378
+ sam_engineer_status: samEngineerStatusSchema,
379
+ sam_engineer_diff: samEngineerDiffSchema,
380
+ sam_engineer_resume: samEngineerResumeSchema,
381
+ sam_engineer_terminate: samEngineerTerminateSchema,
297
382
  };
298
383
  validationBusinessRules = {
299
384
  sam_execute: SAM_EXECUTE_BUSINESS_RULES,
385
+ sam_engineer: SAM_ENGINEER_BUSINESS_RULES,
300
386
  };
301
- console.log('[sam] Behavioral validation active: 10 tools (sam_execute/sam_sandbox enforce, rest monitor)');
387
+ console.log('[sam] Behavioral validation active: 15 tools (sam_execute/sam_sandbox/sam_engineer enforce, rest monitor)');
302
388
  })
303
389
  .catch(() => {
304
390
  console.warn('[sam] Prompt shield unavailable — behavioral validation disabled');
@@ -326,6 +412,9 @@ export default function register(api) {
326
412
  'task/assign',
327
413
  'task/cancel',
328
414
  'task/priority_change',
415
+ 'task/budget-request',
416
+ 'task/escalation',
417
+ 'task/redirect',
329
418
  'veto/issue',
330
419
  'fleet/ping',
331
420
  'fleet/pong',
@@ -344,11 +433,20 @@ export default function register(api) {
344
433
  else if (method === 'task/priority_change') {
345
434
  await handleTaskPriorityChange(msg, pipeline, fleetContext);
346
435
  }
436
+ else if (method === 'task/budget-request') {
437
+ await handleBudgetRequest(msg, pipeline, fleetContext, engineSessions);
438
+ }
439
+ else if (method === 'task/escalation') {
440
+ await handleEscalation(msg, pipeline, fleetContext, engineSessions);
441
+ }
442
+ else if (method === 'task/redirect') {
443
+ await handleRedirect(msg, pipeline, fleetContext, engineSessions);
444
+ }
347
445
  else if (method === 'veto/issue') {
348
446
  await handleVetoIssue(msg, pipeline, samMemory);
349
447
  }
350
448
  else if (method === 'fleet/ping') {
351
- await handleFleetPing(msg, pipeline, cfg, fleetContext);
449
+ await handleFleetPing(msg, pipeline, cfg, fleetContext, engineSessions);
352
450
  }
353
451
  },
354
452
  });
@@ -368,6 +466,8 @@ export default function register(api) {
368
466
  'sam_status', 'sam_pipeline', 'sam_request', 'sam_report',
369
467
  'sam_execute', 'sam_sandbox', 'sam_test', 'sam_artifact',
370
468
  'sam_fleet_task_status', 'sam_fleet_task_complete',
469
+ 'sam_engineer', 'sam_engineer_status', 'sam_engineer_diff',
470
+ 'sam_engineer_resume', 'sam_engineer_terminate',
371
471
  ].join(', ');
372
472
  let capturedWorkspaceDir = null;
373
473
  api.registerHook("agent:bootstrap", async (event) => {
@@ -557,7 +657,7 @@ async function handleTaskPriorityChange(msg, pipeline, fleet) {
557
657
  console.error(`[sam] Failed to handle task/priority_change: ${err}`);
558
658
  }
559
659
  }
560
- async function handleFleetPing(msg, pipeline, cfg, fleet) {
660
+ async function handleFleetPing(msg, pipeline, cfg, fleet, engineSessions) {
561
661
  const summary = pipeline.getSummary();
562
662
  try {
563
663
  await fleet.fleetSend(fleet.bus, fleet.transport, {
@@ -566,11 +666,13 @@ async function handleFleetPing(msg, pipeline, cfg, fleet) {
566
666
  params: {
567
667
  agentId: 'sam',
568
668
  currentStatus: 'active',
569
- toolCount: 12,
669
+ toolCount: 15,
570
670
  pendingTasks: summary.active,
571
671
  activeERs: summary.active,
572
672
  blockedERs: summary.blocked,
573
673
  sandboxStatus: cfg.sandboxEnabled ? 'available' : 'unavailable',
674
+ engineStatus: cfg.engineEnabled ? 'enabled' : 'disabled',
675
+ activeEngineSessions: engineSessions?.activeCount() ?? 0,
574
676
  memoryUsageMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
575
677
  uptimeMs: process.uptime() * 1000,
576
678
  },
@@ -581,4 +683,130 @@ async function handleFleetPing(msg, pipeline, cfg, fleet) {
581
683
  console.error(`[sam] Failed to send fleet/pong: ${err}`);
582
684
  }
583
685
  }
686
+ // ── Engine-related Fleet Inbound Handlers ────────────────────────
687
+ async function handleBudgetRequest(msg, pipeline, fleet, engineSessions) {
688
+ const p = msg.params ?? {};
689
+ const erId = p.taskId ?? p.er_id;
690
+ if (!erId) {
691
+ console.warn('[sam] task/budget-request received without taskId — ignoring');
692
+ return;
693
+ }
694
+ const session = engineSessions.get(erId);
695
+ if (!session) {
696
+ await fleet.fleetSend(fleet.bus, fleet.transport, {
697
+ to: msg.from ?? 'jessie',
698
+ method: 'task/status',
699
+ params: {
700
+ taskId: erId,
701
+ agentId: 'sam',
702
+ status: 'no_session',
703
+ details: `No active engine session for ${erId}`,
704
+ },
705
+ correlationId: msg.id,
706
+ });
707
+ return;
708
+ }
709
+ try {
710
+ const usage = await session.getUsage();
711
+ await fleet.fleetSend(fleet.bus, fleet.transport, {
712
+ to: msg.from ?? 'jessie',
713
+ method: 'task/status',
714
+ params: {
715
+ taskId: erId,
716
+ agentId: 'sam',
717
+ status: 'budget_report',
718
+ usage: {
719
+ totalInputTokens: usage.totalInputTokens,
720
+ totalOutputTokens: usage.totalOutputTokens,
721
+ totalCostUsd: usage.totalCostUsdCents / 100,
722
+ turns: usage.turnCount,
723
+ },
724
+ },
725
+ correlationId: msg.id,
726
+ });
727
+ }
728
+ catch (err) {
729
+ console.error(`[sam] Failed to handle task/budget-request for ${erId}: ${err}`);
730
+ }
731
+ }
732
+ async function handleEscalation(msg, pipeline, fleet, engineSessions) {
733
+ const p = msg.params ?? {};
734
+ const erId = p.taskId ?? p.er_id;
735
+ const action = p.action ?? 'terminate';
736
+ const reason = p.reason ?? 'Escalation from fleet';
737
+ if (!erId) {
738
+ console.warn('[sam] task/escalation received without taskId — ignoring');
739
+ return;
740
+ }
741
+ const session = engineSessions.get(erId);
742
+ if (!session) {
743
+ console.warn(`[sam] task/escalation for ${erId} but no active session`);
744
+ return;
745
+ }
746
+ try {
747
+ if (action === 'terminate') {
748
+ await session.terminate();
749
+ engineSessions.delete(erId);
750
+ await pipeline.handleRequest({
751
+ action: 'update',
752
+ er_id: erId,
753
+ blocker: `ESCALATION TERMINATED: ${reason}`,
754
+ notes: `Engine terminated via fleet escalation from ${msg.from}: ${reason}`,
755
+ }).catch(() => { });
756
+ await fleet.fleetSend(fleet.bus, fleet.transport, {
757
+ to: msg.from ?? 'jessie',
758
+ method: 'task/complete',
759
+ params: {
760
+ taskId: erId,
761
+ success: false,
762
+ result: `Terminated via escalation: ${reason}`,
763
+ status: 'terminated',
764
+ },
765
+ correlationId: msg.id,
766
+ });
767
+ }
768
+ console.log(`[sam] Escalation handled for ${erId}: ${action} — ${reason}`);
769
+ }
770
+ catch (err) {
771
+ console.error(`[sam] Failed to handle task/escalation for ${erId}: ${err}`);
772
+ }
773
+ }
774
+ async function handleRedirect(msg, pipeline, fleet, engineSessions) {
775
+ const p = msg.params ?? {};
776
+ const erId = p.taskId ?? p.er_id;
777
+ const newGuidance = p.guidance ?? p.instructions ?? 'Redirect received — adjust approach.';
778
+ if (!erId) {
779
+ console.warn('[sam] task/redirect received without taskId — ignoring');
780
+ return;
781
+ }
782
+ const session = engineSessions.get(erId);
783
+ if (!session) {
784
+ console.warn(`[sam] task/redirect for ${erId} but no active session`);
785
+ return;
786
+ }
787
+ try {
788
+ const result = await session.sendTurn(newGuidance);
789
+ await pipeline.handleRequest({
790
+ action: 'update',
791
+ er_id: erId,
792
+ notes: `[redirect] from ${msg.from}: ${newGuidance.slice(0, 100)}`,
793
+ }).catch(() => { });
794
+ await fleet.fleetSend(fleet.bus, fleet.transport, {
795
+ to: msg.from ?? 'jessie',
796
+ method: 'task/status',
797
+ params: {
798
+ taskId: erId,
799
+ agentId: 'sam',
800
+ status: result.success ? 'completed' : 'in_progress',
801
+ details: `Redirect processed: ${result.iterations} iterations, ${result.toolCalls.length} tool calls`,
802
+ success: result.success,
803
+ },
804
+ correlationId: msg.id,
805
+ });
806
+ console.log(`[sam] Redirect processed for ${erId} from ${msg.from}`);
807
+ }
808
+ catch (err) {
809
+ console.error(`[sam] Failed to handle task/redirect for ${erId}: ${err}`);
810
+ }
811
+ }
584
812
  //# sourceMappingURL=plugin.js.map