shreni 0.1.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 (269) hide show
  1. package/ARCHITECTURE.md +260 -0
  2. package/LICENSE +201 -0
  3. package/README.md +519 -0
  4. package/TRADEMARK.md +97 -0
  5. package/dist/agents/parikshaka.d.ts +11 -0
  6. package/dist/agents/parikshaka.d.ts.map +1 -0
  7. package/dist/agents/parikshaka.js +80 -0
  8. package/dist/agents/parikshaka.js.map +1 -0
  9. package/dist/agents/providers/claude.d.ts +3 -0
  10. package/dist/agents/providers/claude.d.ts.map +1 -0
  11. package/dist/agents/providers/claude.js +100 -0
  12. package/dist/agents/providers/claude.js.map +1 -0
  13. package/dist/agents/providers/codex.d.ts +3 -0
  14. package/dist/agents/providers/codex.d.ts.map +1 -0
  15. package/dist/agents/providers/codex.js +123 -0
  16. package/dist/agents/providers/codex.js.map +1 -0
  17. package/dist/agents/providers/gemini.d.ts +3 -0
  18. package/dist/agents/providers/gemini.d.ts.map +1 -0
  19. package/dist/agents/providers/gemini.js +77 -0
  20. package/dist/agents/providers/gemini.js.map +1 -0
  21. package/dist/agents/providers/index.d.ts +6 -0
  22. package/dist/agents/providers/index.d.ts.map +1 -0
  23. package/dist/agents/providers/index.js +35 -0
  24. package/dist/agents/providers/index.js.map +1 -0
  25. package/dist/agents/providers/registry.d.ts +20 -0
  26. package/dist/agents/providers/registry.d.ts.map +1 -0
  27. package/dist/agents/providers/registry.js +91 -0
  28. package/dist/agents/providers/registry.js.map +1 -0
  29. package/dist/agents/providers/types.d.ts +42 -0
  30. package/dist/agents/providers/types.d.ts.map +1 -0
  31. package/dist/agents/providers/types.js +61 -0
  32. package/dist/agents/providers/types.js.map +1 -0
  33. package/dist/agents/runner.d.ts +6 -0
  34. package/dist/agents/runner.d.ts.map +1 -0
  35. package/dist/agents/runner.js +159 -0
  36. package/dist/agents/runner.js.map +1 -0
  37. package/dist/agents/silpi.d.ts +3 -0
  38. package/dist/agents/silpi.d.ts.map +1 -0
  39. package/dist/agents/silpi.js +101 -0
  40. package/dist/agents/silpi.js.map +1 -0
  41. package/dist/agents/viharapala.d.ts +5 -0
  42. package/dist/agents/viharapala.d.ts.map +1 -0
  43. package/dist/agents/viharapala.js +128 -0
  44. package/dist/agents/viharapala.js.map +1 -0
  45. package/dist/cli/agents.d.ts +14 -0
  46. package/dist/cli/agents.d.ts.map +1 -0
  47. package/dist/cli/agents.js +47 -0
  48. package/dist/cli/agents.js.map +1 -0
  49. package/dist/cli/detect-toolchain.d.ts +10 -0
  50. package/dist/cli/detect-toolchain.d.ts.map +1 -0
  51. package/dist/cli/detect-toolchain.js +77 -0
  52. package/dist/cli/detect-toolchain.js.map +1 -0
  53. package/dist/cli/index.d.ts +3 -0
  54. package/dist/cli/index.d.ts.map +1 -0
  55. package/dist/cli/index.js +342 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/cli/init-kshetra.d.ts +59 -0
  58. package/dist/cli/init-kshetra.d.ts.map +1 -0
  59. package/dist/cli/init-kshetra.js +531 -0
  60. package/dist/cli/init-kshetra.js.map +1 -0
  61. package/dist/cli/list.d.ts +11 -0
  62. package/dist/cli/list.d.ts.map +1 -0
  63. package/dist/cli/list.js +45 -0
  64. package/dist/cli/list.js.map +1 -0
  65. package/dist/cli/logs.d.ts +20 -0
  66. package/dist/cli/logs.d.ts.map +1 -0
  67. package/dist/cli/logs.js +144 -0
  68. package/dist/cli/logs.js.map +1 -0
  69. package/dist/cli/migrate.d.ts +8 -0
  70. package/dist/cli/migrate.d.ts.map +1 -0
  71. package/dist/cli/migrate.js +116 -0
  72. package/dist/cli/migrate.js.map +1 -0
  73. package/dist/cli/pause.d.ts +24 -0
  74. package/dist/cli/pause.d.ts.map +1 -0
  75. package/dist/cli/pause.js +41 -0
  76. package/dist/cli/pause.js.map +1 -0
  77. package/dist/cli/phalaka-autostart.d.ts +11 -0
  78. package/dist/cli/phalaka-autostart.d.ts.map +1 -0
  79. package/dist/cli/phalaka-autostart.js +28 -0
  80. package/dist/cli/phalaka-autostart.js.map +1 -0
  81. package/dist/cli/phalaka-server.d.ts +2 -0
  82. package/dist/cli/phalaka-server.d.ts.map +1 -0
  83. package/dist/cli/phalaka-server.js +20 -0
  84. package/dist/cli/phalaka-server.js.map +1 -0
  85. package/dist/cli/phalaka.d.ts +30 -0
  86. package/dist/cli/phalaka.d.ts.map +1 -0
  87. package/dist/cli/phalaka.js +60 -0
  88. package/dist/cli/phalaka.js.map +1 -0
  89. package/dist/cli/pid.d.ts +9 -0
  90. package/dist/cli/pid.d.ts.map +1 -0
  91. package/dist/cli/pid.js +66 -0
  92. package/dist/cli/pid.js.map +1 -0
  93. package/dist/cli/provider-preflight.d.ts +11 -0
  94. package/dist/cli/provider-preflight.d.ts.map +1 -0
  95. package/dist/cli/provider-preflight.js +70 -0
  96. package/dist/cli/provider-preflight.js.map +1 -0
  97. package/dist/cli/register.d.ts +8 -0
  98. package/dist/cli/register.d.ts.map +1 -0
  99. package/dist/cli/register.js +34 -0
  100. package/dist/cli/register.js.map +1 -0
  101. package/dist/cli/run.d.ts +3 -0
  102. package/dist/cli/run.d.ts.map +1 -0
  103. package/dist/cli/run.js +40 -0
  104. package/dist/cli/run.js.map +1 -0
  105. package/dist/cli/start.d.ts +11 -0
  106. package/dist/cli/start.d.ts.map +1 -0
  107. package/dist/cli/start.js +26 -0
  108. package/dist/cli/start.js.map +1 -0
  109. package/dist/cli/status.d.ts +39 -0
  110. package/dist/cli/status.d.ts.map +1 -0
  111. package/dist/cli/status.js +207 -0
  112. package/dist/cli/status.js.map +1 -0
  113. package/dist/cli/stop.d.ts +13 -0
  114. package/dist/cli/stop.d.ts.map +1 -0
  115. package/dist/cli/stop.js +18 -0
  116. package/dist/cli/stop.js.map +1 -0
  117. package/dist/cli/sync.d.ts +6 -0
  118. package/dist/cli/sync.d.ts.map +1 -0
  119. package/dist/cli/sync.js +31 -0
  120. package/dist/cli/sync.js.map +1 -0
  121. package/dist/cli/tail.d.ts +6 -0
  122. package/dist/cli/tail.d.ts.map +1 -0
  123. package/dist/cli/tail.js +170 -0
  124. package/dist/cli/tail.js.map +1 -0
  125. package/dist/cli/telemetry.d.ts +2 -0
  126. package/dist/cli/telemetry.d.ts.map +1 -0
  127. package/dist/cli/telemetry.js +42 -0
  128. package/dist/cli/telemetry.js.map +1 -0
  129. package/dist/cli/verify-hooks.d.ts +12 -0
  130. package/dist/cli/verify-hooks.d.ts.map +1 -0
  131. package/dist/cli/verify-hooks.js +38 -0
  132. package/dist/cli/verify-hooks.js.map +1 -0
  133. package/dist/cli/worker.d.ts +2 -0
  134. package/dist/cli/worker.d.ts.map +1 -0
  135. package/dist/cli/worker.js +211 -0
  136. package/dist/cli/worker.js.map +1 -0
  137. package/dist/kshetra/config.d.ts +64 -0
  138. package/dist/kshetra/config.d.ts.map +1 -0
  139. package/dist/kshetra/config.js +173 -0
  140. package/dist/kshetra/config.js.map +1 -0
  141. package/dist/kshetra/registry.d.ts +5 -0
  142. package/dist/kshetra/registry.d.ts.map +1 -0
  143. package/dist/kshetra/registry.js +69 -0
  144. package/dist/kshetra/registry.js.map +1 -0
  145. package/dist/kshetra/state.d.ts +57 -0
  146. package/dist/kshetra/state.d.ts.map +1 -0
  147. package/dist/kshetra/state.js +195 -0
  148. package/dist/kshetra/state.js.map +1 -0
  149. package/dist/kshetra/toolchain.d.ts +20 -0
  150. package/dist/kshetra/toolchain.d.ts.map +1 -0
  151. package/dist/kshetra/toolchain.js +146 -0
  152. package/dist/kshetra/toolchain.js.map +1 -0
  153. package/dist/phalaka/api.d.ts +123 -0
  154. package/dist/phalaka/api.d.ts.map +1 -0
  155. package/dist/phalaka/api.js +196 -0
  156. package/dist/phalaka/api.js.map +1 -0
  157. package/dist/phalaka/beads-read.d.ts +49 -0
  158. package/dist/phalaka/beads-read.d.ts.map +1 -0
  159. package/dist/phalaka/beads-read.js +174 -0
  160. package/dist/phalaka/beads-read.js.map +1 -0
  161. package/dist/phalaka/pid.d.ts +6 -0
  162. package/dist/phalaka/pid.d.ts.map +1 -0
  163. package/dist/phalaka/pid.js +48 -0
  164. package/dist/phalaka/pid.js.map +1 -0
  165. package/dist/phalaka/server.d.ts +10 -0
  166. package/dist/phalaka/server.d.ts.map +1 -0
  167. package/dist/phalaka/server.js +30 -0
  168. package/dist/phalaka/server.js.map +1 -0
  169. package/dist/phalaka/token.d.ts +5 -0
  170. package/dist/phalaka/token.d.ts.map +1 -0
  171. package/dist/phalaka/token.js +40 -0
  172. package/dist/phalaka/token.js.map +1 -0
  173. package/dist/phalaka/ui.d.ts +15 -0
  174. package/dist/phalaka/ui.d.ts.map +1 -0
  175. package/dist/phalaka/ui.js +233 -0
  176. package/dist/phalaka/ui.js.map +1 -0
  177. package/dist/sthapathi/activity-log.d.ts +68 -0
  178. package/dist/sthapathi/activity-log.d.ts.map +1 -0
  179. package/dist/sthapathi/activity-log.js +57 -0
  180. package/dist/sthapathi/activity-log.js.map +1 -0
  181. package/dist/sthapathi/beads.d.ts +27 -0
  182. package/dist/sthapathi/beads.d.ts.map +1 -0
  183. package/dist/sthapathi/beads.js +153 -0
  184. package/dist/sthapathi/beads.js.map +1 -0
  185. package/dist/sthapathi/branch.d.ts +5 -0
  186. package/dist/sthapathi/branch.d.ts.map +1 -0
  187. package/dist/sthapathi/branch.js +20 -0
  188. package/dist/sthapathi/branch.js.map +1 -0
  189. package/dist/sthapathi/dispatch.d.ts +14 -0
  190. package/dist/sthapathi/dispatch.d.ts.map +1 -0
  191. package/dist/sthapathi/dispatch.js +326 -0
  192. package/dist/sthapathi/dispatch.js.map +1 -0
  193. package/dist/sthapathi/errors.d.ts +27 -0
  194. package/dist/sthapathi/errors.d.ts.map +1 -0
  195. package/dist/sthapathi/errors.js +174 -0
  196. package/dist/sthapathi/errors.js.map +1 -0
  197. package/dist/sthapathi/gh.d.ts +19 -0
  198. package/dist/sthapathi/gh.d.ts.map +1 -0
  199. package/dist/sthapathi/gh.js +69 -0
  200. package/dist/sthapathi/gh.js.map +1 -0
  201. package/dist/sthapathi/git.d.ts +41 -0
  202. package/dist/sthapathi/git.d.ts.map +1 -0
  203. package/dist/sthapathi/git.js +199 -0
  204. package/dist/sthapathi/git.js.map +1 -0
  205. package/dist/sthapathi/guard.d.ts +24 -0
  206. package/dist/sthapathi/guard.d.ts.map +1 -0
  207. package/dist/sthapathi/guard.js +64 -0
  208. package/dist/sthapathi/guard.js.map +1 -0
  209. package/dist/sthapathi/health.d.ts +23 -0
  210. package/dist/sthapathi/health.d.ts.map +1 -0
  211. package/dist/sthapathi/health.js +142 -0
  212. package/dist/sthapathi/health.js.map +1 -0
  213. package/dist/sthapathi/index.d.ts +21 -0
  214. package/dist/sthapathi/index.d.ts.map +1 -0
  215. package/dist/sthapathi/index.js +88 -0
  216. package/dist/sthapathi/index.js.map +1 -0
  217. package/dist/sthapathi/lifecycle.d.ts +7 -0
  218. package/dist/sthapathi/lifecycle.d.ts.map +1 -0
  219. package/dist/sthapathi/lifecycle.js +43 -0
  220. package/dist/sthapathi/lifecycle.js.map +1 -0
  221. package/dist/sthapathi/lint.d.ts +8 -0
  222. package/dist/sthapathi/lint.d.ts.map +1 -0
  223. package/dist/sthapathi/lint.js +33 -0
  224. package/dist/sthapathi/lint.js.map +1 -0
  225. package/dist/sthapathi/merge.d.ts +18 -0
  226. package/dist/sthapathi/merge.d.ts.map +1 -0
  227. package/dist/sthapathi/merge.js +259 -0
  228. package/dist/sthapathi/merge.js.map +1 -0
  229. package/dist/sthapathi/notifications.d.ts +14 -0
  230. package/dist/sthapathi/notifications.d.ts.map +1 -0
  231. package/dist/sthapathi/notifications.js +57 -0
  232. package/dist/sthapathi/notifications.js.map +1 -0
  233. package/dist/sthapathi/parikshaka-dispatch.d.ts +12 -0
  234. package/dist/sthapathi/parikshaka-dispatch.d.ts.map +1 -0
  235. package/dist/sthapathi/parikshaka-dispatch.js +0 -0
  236. package/dist/sthapathi/parikshaka-dispatch.js.map +1 -0
  237. package/dist/sthapathi/pickup.d.ts +13 -0
  238. package/dist/sthapathi/pickup.d.ts.map +1 -0
  239. package/dist/sthapathi/pickup.js +144 -0
  240. package/dist/sthapathi/pickup.js.map +1 -0
  241. package/dist/sthapathi/recover.d.ts +16 -0
  242. package/dist/sthapathi/recover.d.ts.map +1 -0
  243. package/dist/sthapathi/recover.js +149 -0
  244. package/dist/sthapathi/recover.js.map +1 -0
  245. package/dist/sthapathi/retry.d.ts +11 -0
  246. package/dist/sthapathi/retry.d.ts.map +1 -0
  247. package/dist/sthapathi/retry.js +42 -0
  248. package/dist/sthapathi/retry.js.map +1 -0
  249. package/dist/sthapathi/self-heal.d.ts +19 -0
  250. package/dist/sthapathi/self-heal.d.ts.map +1 -0
  251. package/dist/sthapathi/self-heal.js +46 -0
  252. package/dist/sthapathi/self-heal.js.map +1 -0
  253. package/dist/sthapathi/types.d.ts +56 -0
  254. package/dist/sthapathi/types.d.ts.map +1 -0
  255. package/dist/sthapathi/types.js +4 -0
  256. package/dist/sthapathi/types.js.map +1 -0
  257. package/dist/sthapathi/watchdog.d.ts +27 -0
  258. package/dist/sthapathi/watchdog.d.ts.map +1 -0
  259. package/dist/sthapathi/watchdog.js +145 -0
  260. package/dist/sthapathi/watchdog.js.map +1 -0
  261. package/dist/telemetry/telemetry.d.ts +42 -0
  262. package/dist/telemetry/telemetry.d.ts.map +1 -0
  263. package/dist/telemetry/telemetry.js +189 -0
  264. package/dist/telemetry/telemetry.js.map +1 -0
  265. package/dist/test-setup.d.ts +2 -0
  266. package/dist/test-setup.d.ts.map +1 -0
  267. package/dist/test-setup.js +16 -0
  268. package/dist/test-setup.js.map +1 -0
  269. package/package.json +71 -0
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GhError = void 0;
4
+ exports.gh = gh;
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
+ class GhError extends Error {
9
+ code;
10
+ cause;
11
+ constructor(code, message, cause) {
12
+ super(message);
13
+ this.code = code;
14
+ this.cause = cause;
15
+ this.name = 'GhError';
16
+ }
17
+ }
18
+ exports.GhError = GhError;
19
+ async function run(args, cwd) {
20
+ try {
21
+ const { stdout } = await execFileAsync('gh', args, { cwd, maxBuffer: 4 * 1024 * 1024 });
22
+ return stdout.trim();
23
+ }
24
+ catch (err) {
25
+ const e = err;
26
+ throw new GhError('GH_ERROR', `gh ${args[0]} ${args[1] ?? ''} failed: ${e.stderr ?? e.message ?? String(err)}`, err);
27
+ }
28
+ }
29
+ // Thin wrapper over the `gh` CLI, scoped to one repo working dir. Used only by
30
+ // the PR merge-policy path (3r2); `gh` is already a Shreni prerequisite and is
31
+ // used at init-kshetra time to create the beads repo.
32
+ function gh(repoPath) {
33
+ return {
34
+ // Open a PR bead-branch → base. Idempotent: if a PR already exists for the
35
+ // head branch, return its URL instead of failing (a re-dispatched or
36
+ // recovered bead must not error on a PR that is already open).
37
+ async prCreate(opts) {
38
+ try {
39
+ const url = await run(['pr', 'create', '--base', opts.base, '--head', opts.head, '--title', opts.title, '--body', opts.body], repoPath);
40
+ // gh prints the PR URL as the last line of stdout.
41
+ return url.split('\n').filter(Boolean).pop() ?? url;
42
+ }
43
+ catch (err) {
44
+ const msg = err.message ?? '';
45
+ if (/already exists|a pull request for branch/i.test(msg)) {
46
+ const existing = await this.prView(opts.head);
47
+ if (existing)
48
+ return existing.url;
49
+ }
50
+ throw err;
51
+ }
52
+ },
53
+ // View the PR for a head branch. Returns null when there is no PR (or gh is
54
+ // unavailable/unauthenticated) — callers treat null as "nothing to reconcile".
55
+ async prView(head) {
56
+ try {
57
+ const raw = await run(['pr', 'view', head, '--json', 'state,url'], repoPath);
58
+ const parsed = JSON.parse(raw);
59
+ if (!parsed.state || !parsed.url)
60
+ return null;
61
+ return { state: parsed.state, url: parsed.url };
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=gh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh.js","sourceRoot":"","sources":["../../src/sthapathi/gh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { Task } from './types.js';
2
+ import type { KshetraConfig } from '../kshetra/config.js';
3
+ export declare class GitError extends Error {
4
+ readonly code: string;
5
+ readonly cause?: unknown | undefined;
6
+ constructor(code: string, message: string, cause?: unknown | undefined);
7
+ }
8
+ export declare function git(kshetraOrPath: KshetraConfig | string): {
9
+ checkout(ref: string): Promise<void>;
10
+ pull(...args: string[]): Promise<void>;
11
+ push(...args: string[]): Promise<void>;
12
+ fetch(...args: string[]): Promise<void>;
13
+ add(...args: string[]): Promise<void>;
14
+ commit(message: string, ...args: string[]): Promise<void>;
15
+ merge(...args: string[]): Promise<void>;
16
+ rebase(...args: string[]): Promise<void>;
17
+ createBranch(task: Task): Promise<string>;
18
+ headSha(ref?: string): Promise<string>;
19
+ currentBranch(): Promise<string>;
20
+ forceBranch(name: string, ref: string): Promise<void>;
21
+ branchExists(branch: string): Promise<boolean>;
22
+ resetHard(ref?: string): Promise<void>;
23
+ clean(): Promise<void>;
24
+ branches(prefix?: string): Promise<string[]>;
25
+ status(): Promise<{
26
+ modified: string[];
27
+ staged: string[];
28
+ untracked: string[];
29
+ }>;
30
+ revsBetween(from: string, to: string): Promise<string[]>;
31
+ mergeTree(branch: string, target: string): Promise<string[]>;
32
+ isAncestor(ancestor: string, descendant: string): Promise<boolean>;
33
+ diffMerged(branch: string): Promise<string>;
34
+ branchDiff(branchPrefix: string): Promise<string>;
35
+ commitFile(filePath: string, message: string): Promise<void>;
36
+ deleteBranch(branch: string, opts?: {
37
+ remote?: boolean;
38
+ force?: boolean;
39
+ }): Promise<void>;
40
+ };
41
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/sthapathi/git.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,MAAM;aAEZ,KAAK,CAAC,EAAE,OAAO;gBAFf,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAoBD,wBAAgB,GAAG,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM;kBAKjC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;kBAItB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;kBAIxB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;mBAIvB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;iBAI1B,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;oBAIrB,MAAM,WAAW,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;mBAY1C,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;oBAIvB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;uBAIrB,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;2BAMlB,OAAO,CAAC,MAAM,CAAC;qBAMrB,OAAO,CAAC,MAAM,CAAC;sBAOd,MAAM,OAAO,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;yBAIhC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;6BAUrB,OAAO,CAAC,IAAI,CAAC;aAO7B,OAAO,CAAC,IAAI,CAAC;sBAKJ,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAMlC,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;sBAsB9D,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;sBAMtC,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;yBA+BvC,MAAM,cAAc,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;uBAS/C,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;6BAQlB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;yBAQ5B,MAAM,WAAW,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;yBAMxD,MAAM,SACR;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC1C,OAAO,CAAC,IAAI,CAAC;EAUnB"}
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitError = void 0;
4
+ exports.git = git;
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
+ class GitError extends Error {
9
+ code;
10
+ cause;
11
+ constructor(code, message, cause) {
12
+ super(message);
13
+ this.code = code;
14
+ this.cause = cause;
15
+ this.name = 'GitError';
16
+ }
17
+ }
18
+ exports.GitError = GitError;
19
+ async function run(args, cwd) {
20
+ try {
21
+ const result = await execFileAsync('git', args, { cwd, maxBuffer: 10 * 1024 * 1024 });
22
+ // trimEnd only — leading whitespace in stdout is meaningful for git --porcelain format
23
+ return { stdout: result.stdout.trimEnd(), stderr: result.stderr.trim() };
24
+ }
25
+ catch (err) {
26
+ const e = err;
27
+ throw new GitError('GIT_ERROR', `git ${args[0]} failed: ${e.stderr ?? e.message ?? String(err)}`, err);
28
+ }
29
+ }
30
+ function git(kshetraOrPath) {
31
+ const repoPath = typeof kshetraOrPath === 'string' ? kshetraOrPath : kshetraOrPath.repo.path;
32
+ return {
33
+ async checkout(ref) {
34
+ await run(['checkout', ref], repoPath);
35
+ },
36
+ async pull(...args) {
37
+ await run(['pull', ...args], repoPath);
38
+ },
39
+ async push(...args) {
40
+ await run(['push', ...args], repoPath);
41
+ },
42
+ async fetch(...args) {
43
+ await run(['fetch', ...args], repoPath);
44
+ },
45
+ async add(...args) {
46
+ await run(['add', ...args], repoPath);
47
+ },
48
+ async commit(message, ...args) {
49
+ try {
50
+ await run(['commit', '-m', message, ...args], repoPath);
51
+ }
52
+ catch (err) {
53
+ // git exits 1 when nothing to commit; message appears in stdout, not stderr
54
+ const cause = err.cause;
55
+ const combined = `${err.message} ${cause?.stdout ?? ''}`;
56
+ if (combined.includes('nothing to commit') || combined.includes('nothing added'))
57
+ return;
58
+ throw err;
59
+ }
60
+ },
61
+ async merge(...args) {
62
+ await run(['merge', ...args], repoPath);
63
+ },
64
+ async rebase(...args) {
65
+ await run(['rebase', ...args], repoPath);
66
+ },
67
+ async createBranch(task) {
68
+ const branch = `bead-${task.id}/${task.slug}`;
69
+ await run(['checkout', '-b', branch], repoPath);
70
+ return branch;
71
+ },
72
+ async headSha(ref = 'HEAD') {
73
+ const { stdout } = await run(['rev-parse', ref], repoPath);
74
+ return stdout.trim();
75
+ },
76
+ // Current branch name, or 'HEAD' when detached.
77
+ async currentBranch() {
78
+ const { stdout } = await run(['rev-parse', '--abbrev-ref', 'HEAD'], repoPath);
79
+ return stdout.trim();
80
+ },
81
+ // Move a branch ref to point at <ref> without checking it out. Used to
82
+ // restore main / salvage stray commits during off-branch recovery.
83
+ async forceBranch(name, ref) {
84
+ await run(['branch', '-f', name, ref], repoPath);
85
+ },
86
+ async branchExists(branch) {
87
+ try {
88
+ await run(['rev-parse', '--verify', branch], repoPath);
89
+ return true;
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ },
95
+ // Discard tracked changes by moving the working tree to <ref> (default HEAD).
96
+ async resetHard(ref = 'HEAD') {
97
+ await run(['reset', '--hard', ref], repoPath);
98
+ },
99
+ // Remove untracked files and directories (respects .gitignore — ignored
100
+ // files like node_modules are left alone). Used by RECOVER to discard
101
+ // interrupted, uncommitted agent work.
102
+ async clean() {
103
+ await run(['clean', '-fd'], repoPath);
104
+ },
105
+ // Local branch names, optionally filtered to those starting with <prefix>.
106
+ async branches(prefix) {
107
+ const { stdout } = await run(['branch', '--format=%(refname:short)'], repoPath);
108
+ const all = stdout.split('\n').map(s => s.trim()).filter(Boolean);
109
+ return prefix ? all.filter(b => b.startsWith(prefix)) : all;
110
+ },
111
+ async status() {
112
+ const { stdout } = await run(['status', '--porcelain'], repoPath);
113
+ const modified = [];
114
+ const staged = [];
115
+ const untracked = [];
116
+ for (const line of stdout.split('\n').filter(Boolean)) {
117
+ const index = line[0];
118
+ const worktree = line[1];
119
+ const file = line.slice(3);
120
+ if (index === '?' && worktree === '?') {
121
+ untracked.push(file);
122
+ }
123
+ else {
124
+ if (index !== ' ' && index !== '?')
125
+ staged.push(file);
126
+ if (worktree !== ' ' && worktree !== '?')
127
+ modified.push(file);
128
+ }
129
+ }
130
+ return { modified, staged, untracked };
131
+ },
132
+ async revsBetween(from, to) {
133
+ const { stdout } = await run(['rev-list', `${from}..${to}`], repoPath);
134
+ return stdout.split('\n').filter(Boolean);
135
+ },
136
+ // Dry-run conflict check using merge-tree
137
+ async mergeTree(branch, target) {
138
+ try {
139
+ const { stdout } = await run(['merge-tree', '--write-tree', branch, target], repoPath);
140
+ // merge-tree exits 0 on clean merge, 1 on conflicts
141
+ // When conflicts exist they appear in stdout — parse conflicted paths
142
+ const conflictedFiles = [];
143
+ for (const line of stdout.split('\n')) {
144
+ if (line.startsWith('CONFLICT')) {
145
+ const match = line.match(/Merge conflict in (.+)/);
146
+ if (match)
147
+ conflictedFiles.push(match[1]);
148
+ }
149
+ }
150
+ return conflictedFiles;
151
+ }
152
+ catch (err) {
153
+ // Exit code 1 with conflict output — parse it
154
+ const e = err;
155
+ const output = e.message ?? '';
156
+ const conflictedFiles = [];
157
+ for (const line of output.split('\n')) {
158
+ if (line.includes('Merge conflict in')) {
159
+ const match = line.match(/Merge conflict in (.+)/);
160
+ if (match)
161
+ conflictedFiles.push(match[1].trim());
162
+ }
163
+ }
164
+ return conflictedFiles;
165
+ }
166
+ },
167
+ async isAncestor(ancestor, descendant) {
168
+ try {
169
+ await run(['merge-base', '--is-ancestor', ancestor, descendant], repoPath);
170
+ return true;
171
+ }
172
+ catch {
173
+ return false;
174
+ }
175
+ },
176
+ async diffMerged(branch) {
177
+ const { stdout } = await run(['diff', `main...${branch}`, '--stat'], repoPath);
178
+ return stdout;
179
+ },
180
+ async branchDiff(branchPrefix) {
181
+ const { stdout } = await run(['diff', `main...${branchPrefix}`, '--unified=3'], repoPath);
182
+ return stdout;
183
+ },
184
+ async commitFile(filePath, message) {
185
+ await run(['add', filePath], repoPath);
186
+ await this.commit(message);
187
+ },
188
+ async deleteBranch(branch, opts = {}) {
189
+ // -D (force) is required to remove a branch holding commits that were
190
+ // never merged — e.g. cleaning up after a failed cycle where the agent
191
+ // committed partial work we are discarding. -d alone refuses those.
192
+ await run(['branch', opts.force ? '-D' : '-d', branch], repoPath);
193
+ if (opts.remote) {
194
+ await run(['push', 'origin', '--delete', branch], repoPath);
195
+ }
196
+ },
197
+ };
198
+ }
199
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/sthapathi/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { KshetraConfig } from '../kshetra/config.js';
2
+ import type { Task } from './types.js';
3
+ export declare class OffBranchError extends Error {
4
+ readonly detail: {
5
+ branch: string;
6
+ expectedMain: string;
7
+ actualHead: string;
8
+ actualMain: string;
9
+ };
10
+ constructor(message: string, detail: {
11
+ branch: string;
12
+ expectedMain: string;
13
+ actualHead: string;
14
+ actualMain: string;
15
+ });
16
+ }
17
+ export interface BranchGuard {
18
+ branch: string;
19
+ mainSha: string;
20
+ }
21
+ export declare function captureGuard(kshetra: KshetraConfig, branch: string): Promise<BranchGuard>;
22
+ export declare function assertOnBranch(kshetra: KshetraConfig, guard: BranchGuard): Promise<void>;
23
+ export declare function recoverOffBranch(kshetra: KshetraConfig, task: Task, guard: BranchGuard): Promise<string | null>;
24
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/sthapathi/guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvC,qBAAa,cAAe,SAAQ,KAAK;aAGrB,MAAM,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB;gBAND,OAAO,EAAE,MAAM,EACC,MAAM,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB;CAKJ;AAKD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAI/F;AAID,wBAAsB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9F;AAMD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OffBranchError = void 0;
4
+ exports.captureGuard = captureGuard;
5
+ exports.assertOnBranch = assertOnBranch;
6
+ exports.recoverOffBranch = recoverOffBranch;
7
+ const git_js_1 = require("./git.js");
8
+ // Thrown when an agent run leaves the bead branch — HEAD moved off the branch,
9
+ // or main acquired commits outside the sanctioned squash-merge flow. Carries
10
+ // enough detail to flag the bead and (if recovered) point at the salvage ref.
11
+ class OffBranchError extends Error {
12
+ detail;
13
+ constructor(message, detail) {
14
+ super(message);
15
+ this.detail = detail;
16
+ this.name = 'OffBranchError';
17
+ }
18
+ }
19
+ exports.OffBranchError = OffBranchError;
20
+ async function captureGuard(kshetra, branch) {
21
+ const g = (0, git_js_1.git)(kshetra);
22
+ const mainSha = await g.headSha(kshetra.repo.mainBranch);
23
+ return { branch, mainSha };
24
+ }
25
+ // Assert the working state is still on the bead branch and main is unchanged.
26
+ // Throws OffBranchError otherwise — the caller recovers and flags.
27
+ async function assertOnBranch(kshetra, guard) {
28
+ const g = (0, git_js_1.git)(kshetra);
29
+ const [head, mainSha] = await Promise.all([
30
+ g.currentBranch(),
31
+ g.headSha(kshetra.repo.mainBranch),
32
+ ]);
33
+ const offBranch = head !== guard.branch;
34
+ const mainMoved = mainSha !== guard.mainSha;
35
+ if (!offBranch && !mainMoved)
36
+ return;
37
+ const reason = offBranch
38
+ ? `HEAD is on "${head}", expected bead branch "${guard.branch}"`
39
+ : `main moved from ${guard.mainSha.slice(0, 8)} to ${mainSha.slice(0, 8)} outside the squash-merge flow`;
40
+ throw new OffBranchError(reason, {
41
+ branch: guard.branch,
42
+ expectedMain: guard.mainSha,
43
+ actualHead: head,
44
+ actualMain: mainSha,
45
+ });
46
+ }
47
+ // Restore the sanctioned invariant after an off-branch violation WITHOUT losing
48
+ // the agent's commits: stray commits on main are preserved on a salvage branch,
49
+ // then main is reset to where origin left it. Returns the salvage ref name when
50
+ // main had diverged (so it can be named in the flag), else null.
51
+ async function recoverOffBranch(kshetra, task, guard) {
52
+ const g = (0, git_js_1.git)(kshetra);
53
+ const strayMain = await g.headSha(kshetra.repo.mainBranch);
54
+ // Get HEAD back onto the bead branch first — we can't move main while on it.
55
+ await g.checkout(guard.branch);
56
+ if (strayMain === guard.mainSha)
57
+ return null;
58
+ // Preserve the diverged commits before rewinding main.
59
+ const salvage = `shreni-salvage/${task.id}`;
60
+ await g.forceBranch(salvage, strayMain);
61
+ await g.forceBranch(kshetra.repo.mainBranch, guard.mainSha);
62
+ return salvage;
63
+ }
64
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/sthapathi/guard.ts"],"names":[],"mappings":";;;AA8BA,oCAIC;AAID,wCAoBC;AAMD,4CAkBC;AAhFD,qCAA+B;AAE/B,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,MAAa,cAAe,SAAQ,KAAK;IAGrB;IAFlB,YACE,OAAe,EACC,MAKf;QAED,KAAK,CAAC,OAAO,CAAC,CAAC;QAPC,WAAM,GAAN,MAAM,CAKrB;QAGD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAbD,wCAaC;AAUM,KAAK,UAAU,YAAY,CAAC,OAAsB,EAAE,MAAc;IACvE,MAAM,CAAC,GAAG,IAAA,YAAG,EAAC,OAAO,CAAC,CAAC;IACvB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,mEAAmE;AAC5D,KAAK,UAAU,cAAc,CAAC,OAAsB,EAAE,KAAkB;IAC7E,MAAM,CAAC,GAAG,IAAA,YAAG,EAAC,OAAO,CAAC,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,CAAC,CAAC,aAAa,EAAE;QACjB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;KACnC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC;IACxC,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC;IAC5C,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS;QAAE,OAAO;IAErC,MAAM,MAAM,GAAG,SAAS;QACtB,CAAC,CAAC,eAAe,IAAI,4BAA4B,KAAK,CAAC,MAAM,GAAG;QAChE,CAAC,CAAC,mBAAmB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,gCAAgC,CAAC;IAC3G,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE;QAC/B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,YAAY,EAAE,KAAK,CAAC,OAAO;QAC3B,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,OAAO;KACpB,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,iEAAiE;AAC1D,KAAK,UAAU,gBAAgB,CACpC,OAAsB,EACtB,IAAU,EACV,KAAkB;IAElB,MAAM,CAAC,GAAG,IAAA,YAAG,EAAC,OAAO,CAAC,CAAC;IACvB,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAE3D,6EAA6E;IAC7E,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/B,IAAI,SAAS,KAAK,KAAK,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE7C,uDAAuD;IACvD,MAAM,OAAO,GAAG,kBAAkB,IAAI,CAAC,EAAE,EAAE,CAAC;IAC5C,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACxC,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { KshetraConfig } from '../kshetra/config.js';
2
+ import type { Task } from './types.js';
3
+ export declare const HEALTH_BEAD_PREFIX = "[shreni-health]";
4
+ export declare const HEALTH_BEAD_TITLE = "[shreni-health] Restore green test suite";
5
+ export interface TestRunResult {
6
+ passed: boolean;
7
+ failCount: number;
8
+ raw: string;
9
+ }
10
+ export interface HealthStatus {
11
+ green: boolean;
12
+ failCount: number;
13
+ baseline: number;
14
+ sha: string;
15
+ }
16
+ export declare function parseFailCount(raw: string, pattern?: string): number;
17
+ export declare function runTestSuite(kshetra: KshetraConfig): Promise<TestRunResult>;
18
+ export declare function invalidateHealth(kshetra: KshetraConfig): void;
19
+ export declare function checkHealth(kshetra: KshetraConfig): Promise<HealthStatus>;
20
+ export declare function measureHealth(kshetra: KshetraConfig): Promise<HealthStatus>;
21
+ export declare function isHealthBead(task: Task): boolean;
22
+ export declare function ensureHealthBead(kshetra: KshetraConfig, failCount: number): Promise<boolean>;
23
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/sthapathi/health.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWvC,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AACpD,eAAO,MAAM,iBAAiB,6CAAmD,CAAC;AAElF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAGhB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAaD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAepE;AAMD,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBjF;AAMD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAE7D;AAYD,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAW/E;AAID,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAOjF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAEhD;AAID,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAalB"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HEALTH_BEAD_TITLE = exports.HEALTH_BEAD_PREFIX = void 0;
4
+ exports.parseFailCount = parseFailCount;
5
+ exports.runTestSuite = runTestSuite;
6
+ exports.invalidateHealth = invalidateHealth;
7
+ exports.checkHealth = checkHealth;
8
+ exports.measureHealth = measureHealth;
9
+ exports.isHealthBead = isHealthBead;
10
+ exports.ensureHealthBead = ensureHealthBead;
11
+ const child_process_1 = require("child_process");
12
+ const util_1 = require("util");
13
+ const git_js_1 = require("./git.js");
14
+ const beads_js_1 = require("./beads.js");
15
+ const state_js_1 = require("../kshetra/state.js");
16
+ const toolchain_js_1 = require("../kshetra/toolchain.js");
17
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
18
+ // Beads with a title beginning with this marker are "restore the suite" repair
19
+ // tasks. They are EXEMPT from the green-suite precondition (they are the thing
20
+ // that makes it green) and are gated on "failures must decrease" instead.
21
+ exports.HEALTH_BEAD_PREFIX = '[shreni-health]';
22
+ exports.HEALTH_BEAD_TITLE = `${exports.HEALTH_BEAD_PREFIX} Restore green test suite`;
23
+ // Parse a failing-test count from common runner summaries, best-effort across
24
+ // ecosystems. The exit code is the primary pass/fail signal (see runTestSuite);
25
+ // this count only refines the "within baseline" comparison. The generic
26
+ // `N failed` pattern covers vitest/jest/pytest/cargo; an optional
27
+ // stack.failCountPattern override wins for a non-standard summary.
28
+ // vitest: "Tests 2 failed | 30 passed (32)"
29
+ // jest: "Tests: 2 failed, 30 passed, 32 total"
30
+ // pytest: "=== 2 failed, 30 passed in 1.2s ==="
31
+ // cargo: "test result: FAILED. 30 passed; 2 failed;"
32
+ // Returns -1 when no count can be found (a red suite with an unknown count is
33
+ // still treated as "not green").
34
+ function parseFailCount(raw, pattern) {
35
+ const patterns = [];
36
+ if (pattern) {
37
+ try {
38
+ patterns.push(new RegExp(pattern, 'i'));
39
+ }
40
+ catch {
41
+ // A malformed override falls through to the built-in patterns.
42
+ }
43
+ }
44
+ patterns.push(/Tests:?\s+(\d+)\s+failed/i, /(\d+)\s+failed/i);
45
+ for (const re of patterns) {
46
+ const m = raw.match(re);
47
+ if (m && m[1] !== undefined)
48
+ return Number(m[1]);
49
+ }
50
+ return -1;
51
+ }
52
+ // Run the full configured test suite in the Kshetra repo. Resolves (never
53
+ // rejects) with the exit-code-derived pass/fail and a best-effort fail count.
54
+ // An empty test command means the Kshetra has no test gate — that is a visible,
55
+ // logged decision (not a silent pass), reported as green with a note.
56
+ async function runTestSuite(kshetra) {
57
+ const [cmd, ...args] = (0, toolchain_js_1.splitCommand)((0, toolchain_js_1.resolveTestCommand)(kshetra));
58
+ if (!cmd) {
59
+ console.warn(`[health] ${kshetra.id}: no test command configured — test gate skipped`);
60
+ return { passed: true, failCount: 0, raw: '(no test command configured — test gate skipped)' };
61
+ }
62
+ try {
63
+ const { stdout, stderr } = await execFileAsync(cmd, args, {
64
+ cwd: kshetra.repo.path,
65
+ maxBuffer: 32 * 1024 * 1024,
66
+ });
67
+ const raw = stdout + stderr;
68
+ return { passed: true, failCount: 0, raw };
69
+ }
70
+ catch (err) {
71
+ const e = err;
72
+ const raw = (e.stdout ?? '') + (e.stderr ?? '') + (e.message ?? '');
73
+ return { passed: false, failCount: parseFailCount(raw, kshetra.stack.failCountPattern), raw };
74
+ }
75
+ }
76
+ // sha-keyed cache so we don't re-run the suite on every 30s poll. main only
77
+ // moves through squashMergeAndClose, so a stable HEAD means a stable verdict.
78
+ const cache = new Map();
79
+ function invalidateHealth(kshetra) {
80
+ cache.delete(kshetra.repo.path);
81
+ }
82
+ function computeStatus(result, baseline, sha) {
83
+ // "green enough" = no failures beyond the accepted baseline. An unknown count
84
+ // (-1) on a red suite is never green.
85
+ const green = result.passed || (result.failCount >= 0 && result.failCount <= baseline);
86
+ const failCount = result.passed ? 0 : result.failCount;
87
+ return { green, failCount, baseline, sha };
88
+ }
89
+ // Check whether the current tree's base (HEAD) is green, modulo the accepted
90
+ // baseline of known-failing tests. Cached by HEAD sha.
91
+ async function checkHealth(kshetra) {
92
+ const sha = await (0, git_js_1.git)(kshetra).headSha();
93
+ const baseline = (0, state_js_1.getHealthBaseline)(kshetra);
94
+ const cached = cache.get(kshetra.repo.path);
95
+ if (cached && cached.sha === sha && cached.status.baseline === baseline) {
96
+ return cached.status;
97
+ }
98
+ const result = await runTestSuite(kshetra);
99
+ const status = computeStatus(result, baseline, sha);
100
+ cache.set(kshetra.repo.path, { sha, status });
101
+ return status;
102
+ }
103
+ // Like checkHealth but always re-runs — used after Silpi mutates the tree
104
+ // during a repair loop, where the verdict must reflect the new code.
105
+ async function measureHealth(kshetra) {
106
+ const sha = await (0, git_js_1.git)(kshetra).headSha();
107
+ const baseline = (0, state_js_1.getHealthBaseline)(kshetra);
108
+ const result = await runTestSuite(kshetra);
109
+ const status = computeStatus(result, baseline, sha);
110
+ cache.set(kshetra.repo.path, { sha, status });
111
+ return status;
112
+ }
113
+ function isHealthBead(task) {
114
+ return task.title.startsWith(exports.HEALTH_BEAD_PREFIX);
115
+ }
116
+ // Ensure a single open repair bead exists. Returns true if one was created.
117
+ // Idempotent: if a health bead is already open/ready, does nothing.
118
+ async function ensureHealthBead(kshetra, failCount) {
119
+ const bdClient = (0, beads_js_1.bd)(kshetra);
120
+ for (const status of ['open', 'in_progress', 'blocked']) {
121
+ const raw = await bdClient.list({ status });
122
+ if (rawHasHealthBead(raw))
123
+ return false;
124
+ }
125
+ const countLabel = failCount >= 0 ? `${failCount}` : 'an unknown number of';
126
+ await bdClient.create(`${exports.HEALTH_BEAD_TITLE} (${countLabel} failing)`, 0, 'bug');
127
+ return true;
128
+ }
129
+ function rawHasHealthBead(raw) {
130
+ let parsed;
131
+ try {
132
+ parsed = JSON.parse(raw);
133
+ }
134
+ catch {
135
+ return false;
136
+ }
137
+ if (!Array.isArray(parsed))
138
+ return false;
139
+ return parsed.some(item => typeof item.title === 'string' &&
140
+ item.title.startsWith(exports.HEALTH_BEAD_PREFIX));
141
+ }
142
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/sthapathi/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { KshetraConfig } from '../kshetra/config.js';
2
+ import type { Task } from './types.js';
3
+ import { type Phase } from './lifecycle.js';
4
+ export type { Phase };
5
+ export interface SchedulerHooks {
6
+ selectNext(kshetra: KshetraConfig): Promise<Task | null>;
7
+ prepareTask(task: Task, kshetra: KshetraConfig): Promise<Task | null>;
8
+ runTask(task: Task, kshetra: KshetraConfig): Promise<void>;
9
+ }
10
+ export interface Scheduler {
11
+ runCycle(kshetra: KshetraConfig, hooks: SchedulerHooks): Promise<void>;
12
+ scheduleLoop(kshetra: KshetraConfig, hooks: SchedulerHooks, intervalMs?: number): () => void;
13
+ start(kshetras: KshetraConfig[], hooks: SchedulerHooks, intervalMs?: number): () => void;
14
+ getActive(kshetraId: string): Task | undefined;
15
+ getPhase(kshetraId: string): Phase;
16
+ }
17
+ export declare const DEFAULT_INTERVAL_MS = 30000;
18
+ export declare function createScheduler(opts?: {
19
+ onPhase?: (kshetraId: string, phase: Phase) => void;
20
+ }): Scheduler;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sthapathi/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAM3D,YAAY,EAAE,KAAK,EAAE,CAAC;AAEtB,MAAM,WAAW,cAAc;IAE7B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAGzD,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAEtE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC7F,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IACzF,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;CACpC;AAED,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,wBAAgB,eAAe,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAO,GAAG,SAAS,CA4F7G"}