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.
- package/ARCHITECTURE.md +260 -0
- package/LICENSE +201 -0
- package/README.md +519 -0
- package/TRADEMARK.md +97 -0
- package/dist/agents/parikshaka.d.ts +11 -0
- package/dist/agents/parikshaka.d.ts.map +1 -0
- package/dist/agents/parikshaka.js +80 -0
- package/dist/agents/parikshaka.js.map +1 -0
- package/dist/agents/providers/claude.d.ts +3 -0
- package/dist/agents/providers/claude.d.ts.map +1 -0
- package/dist/agents/providers/claude.js +100 -0
- package/dist/agents/providers/claude.js.map +1 -0
- package/dist/agents/providers/codex.d.ts +3 -0
- package/dist/agents/providers/codex.d.ts.map +1 -0
- package/dist/agents/providers/codex.js +123 -0
- package/dist/agents/providers/codex.js.map +1 -0
- package/dist/agents/providers/gemini.d.ts +3 -0
- package/dist/agents/providers/gemini.d.ts.map +1 -0
- package/dist/agents/providers/gemini.js +77 -0
- package/dist/agents/providers/gemini.js.map +1 -0
- package/dist/agents/providers/index.d.ts +6 -0
- package/dist/agents/providers/index.d.ts.map +1 -0
- package/dist/agents/providers/index.js +35 -0
- package/dist/agents/providers/index.js.map +1 -0
- package/dist/agents/providers/registry.d.ts +20 -0
- package/dist/agents/providers/registry.d.ts.map +1 -0
- package/dist/agents/providers/registry.js +91 -0
- package/dist/agents/providers/registry.js.map +1 -0
- package/dist/agents/providers/types.d.ts +42 -0
- package/dist/agents/providers/types.d.ts.map +1 -0
- package/dist/agents/providers/types.js +61 -0
- package/dist/agents/providers/types.js.map +1 -0
- package/dist/agents/runner.d.ts +6 -0
- package/dist/agents/runner.d.ts.map +1 -0
- package/dist/agents/runner.js +159 -0
- package/dist/agents/runner.js.map +1 -0
- package/dist/agents/silpi.d.ts +3 -0
- package/dist/agents/silpi.d.ts.map +1 -0
- package/dist/agents/silpi.js +101 -0
- package/dist/agents/silpi.js.map +1 -0
- package/dist/agents/viharapala.d.ts +5 -0
- package/dist/agents/viharapala.d.ts.map +1 -0
- package/dist/agents/viharapala.js +128 -0
- package/dist/agents/viharapala.js.map +1 -0
- package/dist/cli/agents.d.ts +14 -0
- package/dist/cli/agents.d.ts.map +1 -0
- package/dist/cli/agents.js +47 -0
- package/dist/cli/agents.js.map +1 -0
- package/dist/cli/detect-toolchain.d.ts +10 -0
- package/dist/cli/detect-toolchain.d.ts.map +1 -0
- package/dist/cli/detect-toolchain.js +77 -0
- package/dist/cli/detect-toolchain.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +342 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-kshetra.d.ts +59 -0
- package/dist/cli/init-kshetra.d.ts.map +1 -0
- package/dist/cli/init-kshetra.js +531 -0
- package/dist/cli/init-kshetra.js.map +1 -0
- package/dist/cli/list.d.ts +11 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +45 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/logs.d.ts +20 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +144 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/migrate.d.ts +8 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +116 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/pause.d.ts +24 -0
- package/dist/cli/pause.d.ts.map +1 -0
- package/dist/cli/pause.js +41 -0
- package/dist/cli/pause.js.map +1 -0
- package/dist/cli/phalaka-autostart.d.ts +11 -0
- package/dist/cli/phalaka-autostart.d.ts.map +1 -0
- package/dist/cli/phalaka-autostart.js +28 -0
- package/dist/cli/phalaka-autostart.js.map +1 -0
- package/dist/cli/phalaka-server.d.ts +2 -0
- package/dist/cli/phalaka-server.d.ts.map +1 -0
- package/dist/cli/phalaka-server.js +20 -0
- package/dist/cli/phalaka-server.js.map +1 -0
- package/dist/cli/phalaka.d.ts +30 -0
- package/dist/cli/phalaka.d.ts.map +1 -0
- package/dist/cli/phalaka.js +60 -0
- package/dist/cli/phalaka.js.map +1 -0
- package/dist/cli/pid.d.ts +9 -0
- package/dist/cli/pid.d.ts.map +1 -0
- package/dist/cli/pid.js +66 -0
- package/dist/cli/pid.js.map +1 -0
- package/dist/cli/provider-preflight.d.ts +11 -0
- package/dist/cli/provider-preflight.d.ts.map +1 -0
- package/dist/cli/provider-preflight.js +70 -0
- package/dist/cli/provider-preflight.js.map +1 -0
- package/dist/cli/register.d.ts +8 -0
- package/dist/cli/register.d.ts.map +1 -0
- package/dist/cli/register.js +34 -0
- package/dist/cli/register.js.map +1 -0
- package/dist/cli/run.d.ts +3 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +40 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/start.d.ts +11 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +26 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/status.d.ts +39 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +207 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/stop.d.ts +13 -0
- package/dist/cli/stop.d.ts.map +1 -0
- package/dist/cli/stop.js +18 -0
- package/dist/cli/stop.js.map +1 -0
- package/dist/cli/sync.d.ts +6 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +31 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/tail.d.ts +6 -0
- package/dist/cli/tail.d.ts.map +1 -0
- package/dist/cli/tail.js +170 -0
- package/dist/cli/tail.js.map +1 -0
- package/dist/cli/telemetry.d.ts +2 -0
- package/dist/cli/telemetry.d.ts.map +1 -0
- package/dist/cli/telemetry.js +42 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/verify-hooks.d.ts +12 -0
- package/dist/cli/verify-hooks.d.ts.map +1 -0
- package/dist/cli/verify-hooks.js +38 -0
- package/dist/cli/verify-hooks.js.map +1 -0
- package/dist/cli/worker.d.ts +2 -0
- package/dist/cli/worker.d.ts.map +1 -0
- package/dist/cli/worker.js +211 -0
- package/dist/cli/worker.js.map +1 -0
- package/dist/kshetra/config.d.ts +64 -0
- package/dist/kshetra/config.d.ts.map +1 -0
- package/dist/kshetra/config.js +173 -0
- package/dist/kshetra/config.js.map +1 -0
- package/dist/kshetra/registry.d.ts +5 -0
- package/dist/kshetra/registry.d.ts.map +1 -0
- package/dist/kshetra/registry.js +69 -0
- package/dist/kshetra/registry.js.map +1 -0
- package/dist/kshetra/state.d.ts +57 -0
- package/dist/kshetra/state.d.ts.map +1 -0
- package/dist/kshetra/state.js +195 -0
- package/dist/kshetra/state.js.map +1 -0
- package/dist/kshetra/toolchain.d.ts +20 -0
- package/dist/kshetra/toolchain.d.ts.map +1 -0
- package/dist/kshetra/toolchain.js +146 -0
- package/dist/kshetra/toolchain.js.map +1 -0
- package/dist/phalaka/api.d.ts +123 -0
- package/dist/phalaka/api.d.ts.map +1 -0
- package/dist/phalaka/api.js +196 -0
- package/dist/phalaka/api.js.map +1 -0
- package/dist/phalaka/beads-read.d.ts +49 -0
- package/dist/phalaka/beads-read.d.ts.map +1 -0
- package/dist/phalaka/beads-read.js +174 -0
- package/dist/phalaka/beads-read.js.map +1 -0
- package/dist/phalaka/pid.d.ts +6 -0
- package/dist/phalaka/pid.d.ts.map +1 -0
- package/dist/phalaka/pid.js +48 -0
- package/dist/phalaka/pid.js.map +1 -0
- package/dist/phalaka/server.d.ts +10 -0
- package/dist/phalaka/server.d.ts.map +1 -0
- package/dist/phalaka/server.js +30 -0
- package/dist/phalaka/server.js.map +1 -0
- package/dist/phalaka/token.d.ts +5 -0
- package/dist/phalaka/token.d.ts.map +1 -0
- package/dist/phalaka/token.js +40 -0
- package/dist/phalaka/token.js.map +1 -0
- package/dist/phalaka/ui.d.ts +15 -0
- package/dist/phalaka/ui.d.ts.map +1 -0
- package/dist/phalaka/ui.js +233 -0
- package/dist/phalaka/ui.js.map +1 -0
- package/dist/sthapathi/activity-log.d.ts +68 -0
- package/dist/sthapathi/activity-log.d.ts.map +1 -0
- package/dist/sthapathi/activity-log.js +57 -0
- package/dist/sthapathi/activity-log.js.map +1 -0
- package/dist/sthapathi/beads.d.ts +27 -0
- package/dist/sthapathi/beads.d.ts.map +1 -0
- package/dist/sthapathi/beads.js +153 -0
- package/dist/sthapathi/beads.js.map +1 -0
- package/dist/sthapathi/branch.d.ts +5 -0
- package/dist/sthapathi/branch.d.ts.map +1 -0
- package/dist/sthapathi/branch.js +20 -0
- package/dist/sthapathi/branch.js.map +1 -0
- package/dist/sthapathi/dispatch.d.ts +14 -0
- package/dist/sthapathi/dispatch.d.ts.map +1 -0
- package/dist/sthapathi/dispatch.js +326 -0
- package/dist/sthapathi/dispatch.js.map +1 -0
- package/dist/sthapathi/errors.d.ts +27 -0
- package/dist/sthapathi/errors.d.ts.map +1 -0
- package/dist/sthapathi/errors.js +174 -0
- package/dist/sthapathi/errors.js.map +1 -0
- package/dist/sthapathi/gh.d.ts +19 -0
- package/dist/sthapathi/gh.d.ts.map +1 -0
- package/dist/sthapathi/gh.js +69 -0
- package/dist/sthapathi/gh.js.map +1 -0
- package/dist/sthapathi/git.d.ts +41 -0
- package/dist/sthapathi/git.d.ts.map +1 -0
- package/dist/sthapathi/git.js +199 -0
- package/dist/sthapathi/git.js.map +1 -0
- package/dist/sthapathi/guard.d.ts +24 -0
- package/dist/sthapathi/guard.d.ts.map +1 -0
- package/dist/sthapathi/guard.js +64 -0
- package/dist/sthapathi/guard.js.map +1 -0
- package/dist/sthapathi/health.d.ts +23 -0
- package/dist/sthapathi/health.d.ts.map +1 -0
- package/dist/sthapathi/health.js +142 -0
- package/dist/sthapathi/health.js.map +1 -0
- package/dist/sthapathi/index.d.ts +21 -0
- package/dist/sthapathi/index.d.ts.map +1 -0
- package/dist/sthapathi/index.js +88 -0
- package/dist/sthapathi/index.js.map +1 -0
- package/dist/sthapathi/lifecycle.d.ts +7 -0
- package/dist/sthapathi/lifecycle.d.ts.map +1 -0
- package/dist/sthapathi/lifecycle.js +43 -0
- package/dist/sthapathi/lifecycle.js.map +1 -0
- package/dist/sthapathi/lint.d.ts +8 -0
- package/dist/sthapathi/lint.d.ts.map +1 -0
- package/dist/sthapathi/lint.js +33 -0
- package/dist/sthapathi/lint.js.map +1 -0
- package/dist/sthapathi/merge.d.ts +18 -0
- package/dist/sthapathi/merge.d.ts.map +1 -0
- package/dist/sthapathi/merge.js +259 -0
- package/dist/sthapathi/merge.js.map +1 -0
- package/dist/sthapathi/notifications.d.ts +14 -0
- package/dist/sthapathi/notifications.d.ts.map +1 -0
- package/dist/sthapathi/notifications.js +57 -0
- package/dist/sthapathi/notifications.js.map +1 -0
- package/dist/sthapathi/parikshaka-dispatch.d.ts +12 -0
- package/dist/sthapathi/parikshaka-dispatch.d.ts.map +1 -0
- package/dist/sthapathi/parikshaka-dispatch.js +0 -0
- package/dist/sthapathi/parikshaka-dispatch.js.map +1 -0
- package/dist/sthapathi/pickup.d.ts +13 -0
- package/dist/sthapathi/pickup.d.ts.map +1 -0
- package/dist/sthapathi/pickup.js +144 -0
- package/dist/sthapathi/pickup.js.map +1 -0
- package/dist/sthapathi/recover.d.ts +16 -0
- package/dist/sthapathi/recover.d.ts.map +1 -0
- package/dist/sthapathi/recover.js +149 -0
- package/dist/sthapathi/recover.js.map +1 -0
- package/dist/sthapathi/retry.d.ts +11 -0
- package/dist/sthapathi/retry.d.ts.map +1 -0
- package/dist/sthapathi/retry.js +42 -0
- package/dist/sthapathi/retry.js.map +1 -0
- package/dist/sthapathi/self-heal.d.ts +19 -0
- package/dist/sthapathi/self-heal.d.ts.map +1 -0
- package/dist/sthapathi/self-heal.js +46 -0
- package/dist/sthapathi/self-heal.js.map +1 -0
- package/dist/sthapathi/types.d.ts +56 -0
- package/dist/sthapathi/types.d.ts.map +1 -0
- package/dist/sthapathi/types.js +4 -0
- package/dist/sthapathi/types.js.map +1 -0
- package/dist/sthapathi/watchdog.d.ts +27 -0
- package/dist/sthapathi/watchdog.d.ts.map +1 -0
- package/dist/sthapathi/watchdog.js +145 -0
- package/dist/sthapathi/watchdog.js.map +1 -0
- package/dist/telemetry/telemetry.d.ts +42 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -0
- package/dist/telemetry/telemetry.js +189 -0
- package/dist/telemetry/telemetry.js.map +1 -0
- package/dist/test-setup.d.ts +2 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +16 -0
- package/dist/test-setup.js.map +1 -0
- 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"}
|