@a5c-ai/babysitter-sdk 0.0.187-staging.38eafc19 → 0.0.187-staging.457841d2

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.
@@ -126,22 +126,22 @@ async function resolveEffect(action, harnessName, options, piSession, discovered
126
126
  if (piSession) {
127
127
  const bashCommand = [command, ...shellArgs.map(harnessUtils_1.shellQuoteArg)].join(" ");
128
128
  const bashResult = await piSession.executeBash(bashCommand);
129
+ const ok = bashResult.exitCode === 0;
129
130
  return {
130
- status: bashResult.exitCode === 0 ? "ok" : "error",
131
- value: bashResult.exitCode === 0 ? bashResult.output : undefined,
132
- error: bashResult.exitCode === 0
133
- ? undefined
134
- : new Error(`Shell command exited with code ${bashResult.exitCode ?? "null"}: ${bashResult.output}`),
131
+ status: "ok",
132
+ value: ok
133
+ ? bashResult.output
134
+ : { success: false, exitCode: bashResult.exitCode ?? 1, stdout: bashResult.output, stderr: "", error: `Shell command exited with code ${bashResult.exitCode ?? "null"}: ${bashResult.output}` },
135
135
  stdout: bashResult.output,
136
136
  };
137
137
  }
138
138
  const shellResult = await (0, harnessPhase1_1.execShellEffect)(command, shellArgs, cwd);
139
+ const shellOk = shellResult.exitCode === 0;
139
140
  return {
140
- status: shellResult.exitCode === 0 ? "ok" : "error",
141
- value: shellResult.exitCode === 0 ? shellResult.stdout : undefined,
142
- error: shellResult.exitCode === 0
143
- ? undefined
144
- : new Error(`Shell command exited with code ${shellResult.exitCode}: ${shellResult.stderr}`),
141
+ status: "ok",
142
+ value: shellOk
143
+ ? shellResult.stdout
144
+ : { success: false, exitCode: shellResult.exitCode, stdout: shellResult.stdout, stderr: shellResult.stderr, error: `Shell command exited with code ${shellResult.exitCode}: ${shellResult.stderr}` },
145
145
  stdout: shellResult.stdout,
146
146
  stderr: shellResult.stderr,
147
147
  };
@@ -3,6 +3,15 @@
3
3
  * Executes shell hooks from Node.js
4
4
  */
5
5
  import type { HookDispatcherOptions, HookResult } from "./types";
6
+ export interface DiscoveredHook {
7
+ path: string;
8
+ name: string;
9
+ location: "per-repo" | "per-user";
10
+ }
11
+ /**
12
+ * Discover hook scripts for a given hook type from project and user directories.
13
+ */
14
+ export declare function discoverHooks(hookType: string, cwd: string, homeDir?: string): Promise<DiscoveredHook[]>;
6
15
  /**
7
16
  * Find `plugins/babysitter/hooks/hook-dispatcher.sh` by walking up from cwd.
8
17
  * This allows running from nested projects/fixtures inside a mono-repo.
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/hooks/dispatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,qBAAqB,EACrB,UAAU,EAEX,MAAM,SAAS,CAAC;AAIjB;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAetE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAoHrB"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/hooks/dispatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EACV,qBAAqB,EACrB,UAAU,EAEX,MAAM,SAAS,CAAC;AAMjB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC;CACnC;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAqB,GAC7B,OAAO,CAAC,cAAc,EAAE,CAAC,CAmC3B;AAkED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAetE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAyHrB"}
@@ -37,13 +37,102 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  };
38
38
  })();
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.discoverHooks = discoverHooks;
40
41
  exports.findHookDispatcherPath = findHookDispatcherPath;
41
42
  exports.callHook = callHook;
42
43
  const node_child_process_1 = require("node:child_process");
43
44
  const node_fs_1 = require("node:fs");
45
+ const os = __importStar(require("node:os"));
44
46
  const path = __importStar(require("node:path"));
45
47
  const defaults_1 = require("../config/defaults");
46
48
  const harness_1 = require("../harness");
49
+ const HOOK_SCRIPT_EXTENSIONS = new Set([".sh", ".js", ".ts", ".py", ".bash"]);
50
+ /**
51
+ * Discover hook scripts for a given hook type from project and user directories.
52
+ */
53
+ async function discoverHooks(hookType, cwd, homeDir = os.homedir()) {
54
+ const projectHookDir = path.join(cwd, ".a5c", "hooks", hookType);
55
+ const userHookDir = path.join(homeDir, ".a5c", "hooks", hookType);
56
+ async function readHooksFromDir(dir, location) {
57
+ try {
58
+ const entries = await node_fs_1.promises.readdir(dir, { withFileTypes: true });
59
+ return entries
60
+ .filter((entry) => {
61
+ if (!entry.isFile())
62
+ return false;
63
+ const ext = path.extname(entry.name);
64
+ return HOOK_SCRIPT_EXTENSIONS.has(ext);
65
+ })
66
+ .map((entry) => ({
67
+ path: path.join(dir, entry.name),
68
+ name: entry.name,
69
+ location,
70
+ }));
71
+ }
72
+ catch (err) {
73
+ if (err.code === "ENOENT") {
74
+ return [];
75
+ }
76
+ throw err;
77
+ }
78
+ }
79
+ const [projectHooks, userHooks] = await Promise.all([
80
+ readHooksFromDir(projectHookDir, "per-repo"),
81
+ readHooksFromDir(userHookDir, "per-user"),
82
+ ]);
83
+ return [...projectHooks, ...userHooks];
84
+ }
85
+ /**
86
+ * Execute discovered hook scripts sequentially, passing payload as stdin JSON.
87
+ * @internal
88
+ */
89
+ async function executeDiscoveredHooks(hooks, payload, hookType, cwd, timeout) {
90
+ const payloadJson = JSON.stringify(payload);
91
+ const executedHooks = [];
92
+ for (const hook of hooks) {
93
+ const result = await new Promise((resolve) => {
94
+ const child = (0, node_child_process_1.spawn)("bash", [hook.path], {
95
+ cwd,
96
+ stdio: ["pipe", "pipe", "pipe"],
97
+ timeout,
98
+ });
99
+ child.stdin.write(payloadJson);
100
+ child.stdin.end();
101
+ let timedOut = false;
102
+ const timeoutHandle = setTimeout(() => {
103
+ timedOut = true;
104
+ child.kill("SIGTERM");
105
+ }, timeout);
106
+ child.on("error", () => {
107
+ clearTimeout(timeoutHandle);
108
+ resolve({ success: false, exitCode: null });
109
+ });
110
+ child.on("close", (exitCode) => {
111
+ clearTimeout(timeoutHandle);
112
+ if (timedOut) {
113
+ resolve({ success: false, exitCode: null });
114
+ }
115
+ else {
116
+ resolve({ success: exitCode === 0, exitCode });
117
+ }
118
+ });
119
+ });
120
+ executedHooks.push({
121
+ hookPath: hook.path,
122
+ hookName: hook.name,
123
+ hookLocation: hook.location,
124
+ status: result.success ? "success" : "failed",
125
+ exitCode: result.exitCode ?? undefined,
126
+ });
127
+ }
128
+ const allSucceeded = executedHooks.every((h) => h.status === "success");
129
+ return {
130
+ hookType,
131
+ success: allSucceeded,
132
+ error: allSucceeded ? undefined : `One or more discovered hooks failed for ${hookType}`,
133
+ executedHooks,
134
+ };
135
+ }
47
136
  /**
48
137
  * Find `plugins/babysitter/hooks/hook-dispatcher.sh` by walking up from cwd.
49
138
  * This allows running from nested projects/fixtures inside a mono-repo.
@@ -78,6 +167,11 @@ async function callHook(options) {
78
167
  const { hookType, payload, cwd = process.cwd(), timeout = defaults_1.DEFAULTS.hookTimeout, throwOnFailure = false, } = options;
79
168
  const dispatcherPath = findHookDispatcherPath(cwd);
80
169
  if (!dispatcherPath) {
170
+ // Fall back to filesystem-discovered hooks
171
+ const discoveredHooks = await discoverHooks(hookType, cwd);
172
+ if (discoveredHooks.length > 0) {
173
+ return executeDiscoveredHooks(discoveredHooks, payload, hookType, cwd, timeout);
174
+ }
81
175
  return {
82
176
  hookType,
83
177
  success: false,
@@ -2,7 +2,8 @@
2
2
  * Hook System API
3
3
  * Public interface for calling hooks from process files
4
4
  */
5
- export { callHook, } from "./dispatcher";
5
+ export { callHook, discoverHooks, } from "./dispatcher";
6
+ export type { DiscoveredHook } from "./dispatcher";
6
7
  export type { HookType, HookResult, HookExecutionResult, HookPayload, HookDispatcherOptions, OnRunStartPayload, OnRunCompletePayload, OnRunFailPayload, OnTaskStartPayload, OnTaskCompletePayload, OnStepDispatchPayload, OnIterationStartPayload, OnIterationEndPayload, OnBreakpointPayload, PreCommitPayload, PreBranchPayload, PostPlanningPayload, OnScorePayload, } from "./types";
7
8
  /**
8
9
  * Helper function to create hook payloads with proper typing
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC9D,OAAO,EAAE,CAAC,GACT,CAAC,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAK3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,QAAQ,EACR,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC9D,OAAO,EAAE,CAAC,GACT,CAAC,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAK3B"}
@@ -4,10 +4,11 @@
4
4
  * Public interface for calling hooks from process files
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.callHook = void 0;
7
+ exports.discoverHooks = exports.callHook = void 0;
8
8
  exports.createHookPayload = createHookPayload;
9
9
  var dispatcher_1 = require("./dispatcher");
10
10
  Object.defineProperty(exports, "callHook", { enumerable: true, get: function () { return dispatcher_1.callHook; } });
11
+ Object.defineProperty(exports, "discoverHooks", { enumerable: true, get: function () { return dispatcher_1.discoverHooks; } });
11
12
  /**
12
13
  * Helper function to create hook payloads with proper typing
13
14
  */
@@ -6,7 +6,9 @@ Before calling `run:create`, verify and document in your working notes:
6
6
  2. The process structure follows library style/composition patterns rather than
7
7
  a one-off minimal flow.
8
8
  3. Quality gates exist (verification/refinement loops, integration checks,
9
- and/or breakpoints appropriate for the task).
9
+ and/or breakpoints appropriate for the task). Objectively verifiable checks
10
+ (compilation, linting, tests, grep, dependencies) use `kind: 'shell'` with
11
+ `expectedExitCode`, not `kind: 'agent'`.
10
12
  4. Any scope reduction, simplification, or recovery tradeoff is explicitly
11
13
  approved by the user before execution.
12
14
 
@@ -55,7 +55,14 @@ After the process is created and before creating the run:
55
55
  - wrong: skipping repo/process-library research before writing the process
56
56
  - wrong: bypassing the orchestration model with helper scripts or inline logic
57
57
  - wrong: using `kind: 'node'` in generated tasks
58
- - correct: use `agent` or `skill` tasks for reasoning work, with `shell` only
59
- for existing CLIs, tests, linters, git, or builds
58
+ - wrong: using `kind: 'agent'` for deterministic verification (compilation,
59
+ linting, test execution, grep checks, dependency validation) -- these MUST
60
+ use `kind: 'shell'` with `expectedExitCode` for binary pass/fail enforcement
61
+ - correct: use `agent` or `skill` tasks for reasoning work (planning, code
62
+ review, architecture assessment, subjective evaluation)
63
+ - correct: use `shell` tasks for all objectively verifiable checks (tsc, eslint,
64
+ vitest, grep, dependency imports, runtime smoke tests)
60
65
  - correct: include verification loops, refinement loops, quality gates, and
61
66
  breakpoints where appropriate
67
+ - correct: pair shell verification gates with agent analysis tasks (shell runs
68
+ the check, agent interprets failures and suggests fixes)
@@ -75,8 +75,11 @@ specified:
75
75
  - Integrate/link the main pages (or entry points) with functionality created
76
76
  for every phase of the development process
77
77
  - Quality gated iterative and convergent development/refinement loops
78
- - Test driven -- where quality gates can use executable tools, scripts, and
79
- tests to verify accuracy and completeness
78
+ - Test driven -- where quality gates use `kind: 'shell'` tasks with
79
+ `expectedExitCode` for deterministic verification (compilation, linting,
80
+ test suites, grep checks, dependency availability, runtime smoke tests).
81
+ Reserve `kind: 'agent'` for subjective assessment only (code review,
82
+ architecture evaluation, UX quality)
80
83
  - Integration phases for each new functionality in every milestone
81
84
  - Where relevant -- beautiful and polished UX with pixel-perfect verification
82
85
  - Accurate and complete implementation of the user request
@@ -37,6 +37,53 @@ export const agentTask = defineTask('agent-scorer', (args, taskCtx) => ({
37
37
  }));
38
38
  ```
39
39
 
40
+ ### Shell Verification Task Example
41
+
42
+ Use shell tasks for all deterministic verification gates. Shell tasks produce
43
+ binary pass/fail results via exit codes that cannot be bypassed by agent
44
+ reasoning.
45
+
46
+ ```javascript
47
+ // Grep-based integration check
48
+ export const grepCheckTask = defineTask('grep-integration-check', (args, taskCtx) => ({
49
+ kind: 'shell',
50
+ title: 'Verify integration points exist',
51
+ shell: {
52
+ command: `cd ${args.projectDir || '.'} && grep -q "${args.pattern}" ${args.file}`,
53
+ expectedExitCode: 0,
54
+ timeout: 10000
55
+ },
56
+ io: {
57
+ inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
58
+ outputJsonPath: `tasks/${taskCtx.effectId}/output.json`
59
+ }
60
+ }));
61
+
62
+ // Multi-check verification gate
63
+ export const verificationGateTask = defineTask('verification-gate', (args, taskCtx) => ({
64
+ kind: 'shell',
65
+ title: 'Deterministic verification gate',
66
+ shell: {
67
+ command: [
68
+ `cd ${args.projectDir || '.'}`,
69
+ 'npx tsc --noEmit',
70
+ 'npx eslint src/ --max-warnings=0',
71
+ 'npx vitest run --reporter=verbose'
72
+ ].join(' && '),
73
+ expectedExitCode: 0,
74
+ timeout: 300000
75
+ },
76
+ io: {
77
+ inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
78
+ outputJsonPath: `tasks/${taskCtx.effectId}/output.json`
79
+ }
80
+ }));
81
+ ```
82
+
83
+ Use `library/processes/shared/deterministic-quality-gate.js` for composable
84
+ preset gates (createGrepCheck, createCompilationGate, createTestSuiteGate,
85
+ createRuntimeSmokeTest).
86
+
40
87
  ### Skill Task Example
41
88
 
42
89
  Important: Check which skills are actually available before assigning the skill
@@ -10,12 +10,54 @@ build tools), `breakpoint` (human approval), and `sleep` (time gates).
10
10
  | Kind | Description | Executor | When to use |
11
11
  |------|-------------|----------|-------------|
12
12
  | ~~`node`~~ | ~~Node.js script~~ | ~~Local node process~~ | **NEVER -- forbidden. Convert to `agent` or `skill`.** |
13
- | `shell` | Shell command | Local shell process | Only for running existing CLI tools, test suites, git, linters, builds. The orchestrating agent must execute it intentionally and post the result |
14
- | `agent` | LLM agent | Agent runtime | **Default for all tasks** -- planning, implementation, analysis, verification, scoring, debugging, code writing, research |
13
+ | `shell` | Shell command | Local shell process | **Deterministic verification** (compilation, linting, tests, grep, dependency checks, smoke tests) AND running existing CLI tools, git, builds. The orchestrating agent must execute it intentionally and post the result |
14
+ | `agent` | LLM agent | Agent runtime | **Default for reasoning tasks** -- planning, implementation, analysis, scoring, debugging, code writing, research. Also for **subjective verification** (code review, architecture assessment, UX evaluation) |
15
15
  | `skill` | {{skillSystemLabel}} | Skill system | When a matching installed skill exists (preferred over agent when available) |
16
16
  | `breakpoint` | Human approval | UI/CLI | Decision gates requiring user input |
17
17
  | `sleep` | Time gate | Scheduler | Time-based pauses |
18
18
 
19
+ ### Shell vs Agent for Verification Tasks
20
+
21
+ **CRITICAL:** Verification tasks that produce deterministic, binary pass/fail
22
+ results MUST use `kind: 'shell'` with `expectedExitCode`, NOT `kind: 'agent'`.
23
+ Agent-interpreted verification creates soft gates where an LLM subjectively
24
+ assesses pass/fail -- this is unreliable for objectively testable checks.
25
+
26
+ | Verification type | Correct kind | Why |
27
+ |-------------------|-------------|-----|
28
+ | Compilation (tsc, gcc) | `shell` | Exit code is deterministic pass/fail |
29
+ | Linting (eslint, ruff) | `shell` | Exit code is deterministic pass/fail |
30
+ | Test suites (vitest, jest) | `shell` | Exit code is deterministic pass/fail |
31
+ | Grep/pattern checks | `shell` | Pattern exists or it doesn't |
32
+ | Dependency availability | `shell` | `node -e "require('pkg')"` succeeds or fails |
33
+ | Runtime smoke tests | `shell` | Start, curl, check status code, stop |
34
+ | Code review / design quality | `agent` | Requires subjective judgment |
35
+ | Architecture assessment | `agent` | Requires reasoning about tradeoffs |
36
+ | UX evaluation | `agent` | Subjective quality assessment |
37
+
38
+ **Anti-pattern (wrong):**
39
+ ```javascript
40
+ // BAD: agent-interpreted verification -- the agent can say "looks good" without running anything
41
+ const verifyTask = defineTask('verify-compilation', (args, taskCtx) => ({
42
+ kind: 'agent',
43
+ title: 'Verify TypeScript compiles',
44
+ agent: { prompt: { instructions: ['Run tsc and check it passes'] } }
45
+ }));
46
+ ```
47
+
48
+ **Correct pattern:**
49
+ ```javascript
50
+ // GOOD: deterministic shell gate -- exit code cannot be negotiated
51
+ const verifyTask = defineTask('verify-compilation', (args, taskCtx) => ({
52
+ kind: 'shell',
53
+ title: 'TypeScript compilation check',
54
+ shell: { command: 'npx tsc --noEmit', expectedExitCode: 0, timeout: 120000 }
55
+ }));
56
+ ```
57
+
58
+ Use `library/processes/shared/deterministic-quality-gate.js` for composable
59
+ preset gates (grep checks, compilation, test suites, runtime smoke tests).
60
+
19
61
  ### Effect Execution Hints
20
62
 
21
63
  Tasks can include an `execution` field to express preferences about how the effect should be executed:
@@ -1 +1 @@
1
- {"version":3,"file":"breakpoint.d.ts","sourceRoot":"","sources":["../../../src/runtime/intrinsics/breakpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAmC,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC1H,OAAO,EAAoB,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAkChE,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAChD,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,oBAAoB,EAC7B,OAAO,CAAC,EAAE,iBAAiB,GAAG,wBAAwB,GACrD,OAAO,CAAC,gBAAgB,CAAC,CA+B3B"}
1
+ {"version":3,"file":"breakpoint.d.ts","sourceRoot":"","sources":["../../../src/runtime/intrinsics/breakpoint.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAmC,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC1H,OAAO,EAAoB,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAkChE,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAChD,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,oBAAoB,EAC7B,OAAO,CAAC,EAAE,iBAAiB,GAAG,wBAAwB,GACrD,OAAO,CAAC,gBAAgB,CAAC,CAiD3B"}
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.runBreakpointIntrinsic = runBreakpointIntrinsic;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
4
9
  const task_1 = require("./task");
5
10
  const journal_1 = require("../../storage/journal");
6
11
  const BREAKPOINT_TASK_ID = "__sdk.breakpoint";
@@ -28,10 +33,24 @@ function runBreakpointIntrinsic(payload, context, options) {
28
33
  const ctx = context;
29
34
  if (ctx.nonInteractive) {
30
35
  const bpLabel = options?.label ?? "unnamed";
36
+ let logSeq;
37
+ if (ctx.logSeq !== undefined && ctx.recordedLogSeqs !== undefined) {
38
+ logSeq = ++ctx.logSeq;
39
+ if (ctx.recordedLogSeqs.has(logSeq)) {
40
+ return Promise.resolve({ approved: true, response: "Auto-approved (non-interactive mode)" });
41
+ }
42
+ ctx.recordedLogSeqs.add(logSeq);
43
+ void node_fs_1.promises.appendFile(node_path_1.default.join(context.runDir, "state", "logSeqs.txt"), `${logSeq}\n`).catch(() => {
44
+ // Never let logging break orchestration.
45
+ });
46
+ }
47
+ else {
48
+ logSeq = -1;
49
+ }
31
50
  void (0, journal_1.appendEvent)({
32
51
  runDir: context.runDir,
33
52
  eventType: "PROCESS_LOG",
34
- event: { logSeq: -1, label: "breakpoint:skipped", message: `Breakpoint '${bpLabel}' auto-approved (non-interactive mode)` },
53
+ event: { logSeq, label: "breakpoint:skipped", message: `Breakpoint '${bpLabel}' auto-approved (non-interactive mode)` },
35
54
  }).catch(() => {
36
55
  // Never let logging break orchestration.
37
56
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a5c-ai/babysitter-sdk",
3
- "version": "0.0.187-staging.38eafc19",
3
+ "version": "0.0.187-staging.457841d2",
4
4
  "description": "Storage and run-registry primitives for event-sourced babysitter workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "commonjs",