agent-bober 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/.claude-plugin/plugin.json +9 -0
- package/LICENSE +21 -0
- package/README.md +495 -0
- package/agents/bober-evaluator.md +323 -0
- package/agents/bober-generator.md +245 -0
- package/agents/bober-planner.md +248 -0
- package/dist/cli/commands/eval.d.ts +6 -0
- package/dist/cli/commands/eval.d.ts.map +1 -0
- package/dist/cli/commands/eval.js +129 -0
- package/dist/cli/commands/eval.js.map +1 -0
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +547 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +5 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +87 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/run.d.ts +5 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +120 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/sprint.d.ts +6 -0
- package/dist/cli/commands/sprint.d.ts.map +1 -0
- package/dist/cli/commands/sprint.js +206 -0
- package/dist/cli/commands/sprint.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 +124 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/defaults.d.ts +15 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +226 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +8 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +18 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +904 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +181 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/contracts/eval-result.d.ts +205 -0
- package/dist/contracts/eval-result.d.ts.map +1 -0
- package/dist/contracts/eval-result.js +87 -0
- package/dist/contracts/eval-result.js.map +1 -0
- package/dist/contracts/index.d.ts +4 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +16 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/spec.d.ts +101 -0
- package/dist/contracts/spec.d.ts.map +1 -0
- package/dist/contracts/spec.js +51 -0
- package/dist/contracts/spec.js.map +1 -0
- package/dist/contracts/sprint-contract.d.ts +141 -0
- package/dist/contracts/sprint-contract.d.ts.map +1 -0
- package/dist/contracts/sprint-contract.js +80 -0
- package/dist/contracts/sprint-contract.js.map +1 -0
- package/dist/evaluators/builtin/api-check.d.ts +13 -0
- package/dist/evaluators/builtin/api-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/api-check.js +152 -0
- package/dist/evaluators/builtin/api-check.js.map +1 -0
- package/dist/evaluators/builtin/build-check.d.ts +17 -0
- package/dist/evaluators/builtin/build-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/build-check.js +155 -0
- package/dist/evaluators/builtin/build-check.js.map +1 -0
- package/dist/evaluators/builtin/command-runner.d.ts +26 -0
- package/dist/evaluators/builtin/command-runner.d.ts.map +1 -0
- package/dist/evaluators/builtin/command-runner.js +114 -0
- package/dist/evaluators/builtin/command-runner.js.map +1 -0
- package/dist/evaluators/builtin/lint.d.ts +17 -0
- package/dist/evaluators/builtin/lint.d.ts.map +1 -0
- package/dist/evaluators/builtin/lint.js +264 -0
- package/dist/evaluators/builtin/lint.js.map +1 -0
- package/dist/evaluators/builtin/playwright.d.ts +16 -0
- package/dist/evaluators/builtin/playwright.d.ts.map +1 -0
- package/dist/evaluators/builtin/playwright.js +238 -0
- package/dist/evaluators/builtin/playwright.js.map +1 -0
- package/dist/evaluators/builtin/typescript-check.d.ts +12 -0
- package/dist/evaluators/builtin/typescript-check.d.ts.map +1 -0
- package/dist/evaluators/builtin/typescript-check.js +155 -0
- package/dist/evaluators/builtin/typescript-check.js.map +1 -0
- package/dist/evaluators/builtin/unit-test.d.ts +18 -0
- package/dist/evaluators/builtin/unit-test.d.ts.map +1 -0
- package/dist/evaluators/builtin/unit-test.js +279 -0
- package/dist/evaluators/builtin/unit-test.js.map +1 -0
- package/dist/evaluators/index.d.ts +11 -0
- package/dist/evaluators/index.d.ts.map +1 -0
- package/dist/evaluators/index.js +13 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/plugin-interface.d.ts +50 -0
- package/dist/evaluators/plugin-interface.d.ts.map +1 -0
- package/dist/evaluators/plugin-interface.js +2 -0
- package/dist/evaluators/plugin-interface.js.map +1 -0
- package/dist/evaluators/plugin-loader.d.ts +18 -0
- package/dist/evaluators/plugin-loader.d.ts.map +1 -0
- package/dist/evaluators/plugin-loader.js +107 -0
- package/dist/evaluators/plugin-loader.js.map +1 -0
- package/dist/evaluators/registry.d.ts +78 -0
- package/dist/evaluators/registry.d.ts.map +1 -0
- package/dist/evaluators/registry.js +238 -0
- package/dist/evaluators/registry.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator/context-handoff.d.ts +543 -0
- package/dist/orchestrator/context-handoff.d.ts.map +1 -0
- package/dist/orchestrator/context-handoff.js +133 -0
- package/dist/orchestrator/context-handoff.js.map +1 -0
- package/dist/orchestrator/evaluator-agent.d.ts +15 -0
- package/dist/orchestrator/evaluator-agent.d.ts.map +1 -0
- package/dist/orchestrator/evaluator-agent.js +233 -0
- package/dist/orchestrator/evaluator-agent.js.map +1 -0
- package/dist/orchestrator/generator-agent.d.ts +16 -0
- package/dist/orchestrator/generator-agent.d.ts.map +1 -0
- package/dist/orchestrator/generator-agent.js +147 -0
- package/dist/orchestrator/generator-agent.js.map +1 -0
- package/dist/orchestrator/pipeline.d.ts +24 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -0
- package/dist/orchestrator/pipeline.js +290 -0
- package/dist/orchestrator/pipeline.js.map +1 -0
- package/dist/orchestrator/planner-agent.d.ts +10 -0
- package/dist/orchestrator/planner-agent.d.ts.map +1 -0
- package/dist/orchestrator/planner-agent.js +187 -0
- package/dist/orchestrator/planner-agent.js.map +1 -0
- package/dist/state/helpers.d.ts +5 -0
- package/dist/state/helpers.d.ts.map +1 -0
- package/dist/state/helpers.js +8 -0
- package/dist/state/helpers.js.map +1 -0
- package/dist/state/history.d.ts +39 -0
- package/dist/state/history.d.ts.map +1 -0
- package/dist/state/history.js +162 -0
- package/dist/state/history.js.map +1 -0
- package/dist/state/index.d.ts +8 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +22 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/plan-state.d.ts +21 -0
- package/dist/state/plan-state.d.ts.map +1 -0
- package/dist/state/plan-state.js +108 -0
- package/dist/state/plan-state.js.map +1 -0
- package/dist/state/sprint-state.d.ts +20 -0
- package/dist/state/sprint-state.d.ts.map +1 -0
- package/dist/state/sprint-state.js +98 -0
- package/dist/state/sprint-state.js.map +1 -0
- package/dist/utils/fs.d.ts +31 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +67 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/git.d.ts +35 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +84 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +73 -0
- package/dist/utils/logger.js.map +1 -0
- package/hooks/hooks.json +10 -0
- package/package.json +67 -0
- package/scripts/detect-stack.sh +287 -0
- package/scripts/init-project.sh +206 -0
- package/scripts/run-eval.sh +175 -0
- package/skills/bober.anchor/SKILL.md +365 -0
- package/skills/bober.anchor/references/anchor-guide.md +567 -0
- package/skills/bober.brownfield/SKILL.md +422 -0
- package/skills/bober.brownfield/references/codebase-analysis.md +304 -0
- package/skills/bober.eval/SKILL.md +235 -0
- package/skills/bober.eval/references/eval-strategies.md +407 -0
- package/skills/bober.eval/references/feedback-format.md +182 -0
- package/skills/bober.plan/SKILL.md +244 -0
- package/skills/bober.plan/references/clarification-guide.md +124 -0
- package/skills/bober.plan/references/spec-schema.md +253 -0
- package/skills/bober.react/SKILL.md +330 -0
- package/skills/bober.react/references/react-scaffold.md +344 -0
- package/skills/bober.run/SKILL.md +303 -0
- package/skills/bober.solidity/SKILL.md +416 -0
- package/skills/bober.solidity/references/solidity-guide.md +487 -0
- package/skills/bober.sprint/SKILL.md +280 -0
- package/skills/bober.sprint/references/contract-schema.md +251 -0
- package/templates/base/CLAUDE.md +20 -0
- package/templates/base/bober.config.json +35 -0
- package/templates/brownfield/CLAUDE.md +34 -0
- package/templates/brownfield/bober.config.json +37 -0
- package/templates/presets/anchor/CLAUDE.md +163 -0
- package/templates/presets/anchor/bober.config.json +9 -0
- package/templates/presets/api-node/CLAUDE.md +153 -0
- package/templates/presets/api-node/bober.config.json +10 -0
- package/templates/presets/nextjs/CLAUDE.md +82 -0
- package/templates/presets/nextjs/bober.config.json +14 -0
- package/templates/presets/python-api/CLAUDE.md +202 -0
- package/templates/presets/python-api/bober.config.json +9 -0
- package/templates/presets/react-vite/CLAUDE.md +71 -0
- package/templates/presets/react-vite/bober.config.json +53 -0
- package/templates/presets/react-vite/scaffold/package.json +45 -0
- package/templates/presets/react-vite/scaffold/server/index.ts +38 -0
- package/templates/presets/react-vite/scaffold/server/tsconfig.json +24 -0
- package/templates/presets/react-vite/scaffold/src/App.tsx +37 -0
- package/templates/presets/react-vite/scaffold/src/index.html +12 -0
- package/templates/presets/react-vite/scaffold/src/main.tsx +12 -0
- package/templates/presets/react-vite/scaffold/tsconfig.json +27 -0
- package/templates/presets/react-vite/scaffold/vite.config.ts +34 -0
- package/templates/presets/solidity/CLAUDE.md +106 -0
- package/templates/presets/solidity/bober.config.json +9 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ── Enums ───────────────────────────────────────────────────────────
|
|
3
|
+
export const PrioritySchema = z.enum(["must", "should", "could"]);
|
|
4
|
+
// ── Feature Spec ────────────────────────────────────────────────────
|
|
5
|
+
export const FeatureSpecSchema = z.object({
|
|
6
|
+
id: z.string().min(1),
|
|
7
|
+
title: z.string().min(1),
|
|
8
|
+
description: z.string().min(1),
|
|
9
|
+
priority: PrioritySchema,
|
|
10
|
+
estimatedSprints: z.number().int().min(1),
|
|
11
|
+
acceptanceCriteria: z.array(z.string().min(1)),
|
|
12
|
+
});
|
|
13
|
+
// ── Plan Spec ───────────────────────────────────────────────────────
|
|
14
|
+
export const PlanSpecSchema = z.object({
|
|
15
|
+
id: z.string().min(1),
|
|
16
|
+
title: z.string().min(1),
|
|
17
|
+
description: z.string().min(1),
|
|
18
|
+
projectType: z.string().min(1),
|
|
19
|
+
techStack: z.array(z.string()),
|
|
20
|
+
features: z.array(FeatureSpecSchema),
|
|
21
|
+
nonFunctional: z.array(z.string()),
|
|
22
|
+
constraints: z.array(z.string()),
|
|
23
|
+
createdAt: z.string().datetime(),
|
|
24
|
+
updatedAt: z.string().datetime(),
|
|
25
|
+
});
|
|
26
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
27
|
+
let specCounter = 0;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new plan specification with sensible defaults.
|
|
30
|
+
*/
|
|
31
|
+
export function createSpec(title, description, features) {
|
|
32
|
+
specCounter++;
|
|
33
|
+
const now = new Date().toISOString();
|
|
34
|
+
const id = `spec-${Date.now()}-${specCounter}`;
|
|
35
|
+
return {
|
|
36
|
+
id,
|
|
37
|
+
title,
|
|
38
|
+
description,
|
|
39
|
+
projectType: "greenfield",
|
|
40
|
+
techStack: [],
|
|
41
|
+
features: features.map((f, idx) => ({
|
|
42
|
+
...f,
|
|
43
|
+
id: `feature-${idx + 1}`,
|
|
44
|
+
})),
|
|
45
|
+
nonFunctional: [],
|
|
46
|
+
constraints: [],
|
|
47
|
+
createdAt: now,
|
|
48
|
+
updatedAt: now,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/contracts/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,uEAAuE;AAEvE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAGlE,uEAAuE;AAEvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,QAAQ,EAAE,cAAc;IACxB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC/C,CAAC,CAAC;AAGH,uEAAuE;AAEvE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACpC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH,uEAAuE;AAEvE,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,WAAmB,EACnB,QAAmC;IAEnC,WAAW,EAAE,CAAC;IACd,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,EAAE,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,EAAE,CAAC;IAE/C,OAAO;QACL,EAAE;QACF,KAAK;QACL,WAAW;QACX,WAAW,EAAE,YAAY;QACzB,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAClC,GAAG,CAAC;YACJ,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,EAAE;SACzB,CAAC,CAAC;QACH,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ContractStatusSchema: z.ZodEnum<["proposed", "negotiating", "agreed", "in-progress", "evaluating", "passed", "failed", "needs-rework"]>;
|
|
3
|
+
export type ContractStatus = z.infer<typeof ContractStatusSchema>;
|
|
4
|
+
export declare const FileActionSchema: z.ZodEnum<["create", "modify", "delete"]>;
|
|
5
|
+
export type FileAction = z.infer<typeof FileActionSchema>;
|
|
6
|
+
export declare const SuccessCriterionSchema: z.ZodObject<{
|
|
7
|
+
id: z.ZodString;
|
|
8
|
+
description: z.ZodString;
|
|
9
|
+
verificationMethod: z.ZodString;
|
|
10
|
+
passed: z.ZodBoolean;
|
|
11
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
description: string;
|
|
14
|
+
id: string;
|
|
15
|
+
verificationMethod: string;
|
|
16
|
+
passed: boolean;
|
|
17
|
+
notes?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
description: string;
|
|
20
|
+
id: string;
|
|
21
|
+
verificationMethod: string;
|
|
22
|
+
passed: boolean;
|
|
23
|
+
notes?: string | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
export type SuccessCriterion = z.infer<typeof SuccessCriterionSchema>;
|
|
26
|
+
export declare const FileChangeSchema: z.ZodObject<{
|
|
27
|
+
path: z.ZodString;
|
|
28
|
+
action: z.ZodEnum<["create", "modify", "delete"]>;
|
|
29
|
+
description: z.ZodString;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
description: string;
|
|
32
|
+
path: string;
|
|
33
|
+
action: "create" | "modify" | "delete";
|
|
34
|
+
}, {
|
|
35
|
+
description: string;
|
|
36
|
+
path: string;
|
|
37
|
+
action: "create" | "modify" | "delete";
|
|
38
|
+
}>;
|
|
39
|
+
export type FileChange = z.infer<typeof FileChangeSchema>;
|
|
40
|
+
export declare const SprintContractSchema: z.ZodObject<{
|
|
41
|
+
id: z.ZodString;
|
|
42
|
+
feature: z.ZodString;
|
|
43
|
+
description: z.ZodString;
|
|
44
|
+
successCriteria: z.ZodArray<z.ZodObject<{
|
|
45
|
+
id: z.ZodString;
|
|
46
|
+
description: z.ZodString;
|
|
47
|
+
verificationMethod: z.ZodString;
|
|
48
|
+
passed: z.ZodBoolean;
|
|
49
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
description: string;
|
|
52
|
+
id: string;
|
|
53
|
+
verificationMethod: string;
|
|
54
|
+
passed: boolean;
|
|
55
|
+
notes?: string | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
description: string;
|
|
58
|
+
id: string;
|
|
59
|
+
verificationMethod: string;
|
|
60
|
+
passed: boolean;
|
|
61
|
+
notes?: string | undefined;
|
|
62
|
+
}>, "many">;
|
|
63
|
+
expectedChanges: z.ZodArray<z.ZodObject<{
|
|
64
|
+
path: z.ZodString;
|
|
65
|
+
action: z.ZodEnum<["create", "modify", "delete"]>;
|
|
66
|
+
description: z.ZodString;
|
|
67
|
+
}, "strip", z.ZodTypeAny, {
|
|
68
|
+
description: string;
|
|
69
|
+
path: string;
|
|
70
|
+
action: "create" | "modify" | "delete";
|
|
71
|
+
}, {
|
|
72
|
+
description: string;
|
|
73
|
+
path: string;
|
|
74
|
+
action: "create" | "modify" | "delete";
|
|
75
|
+
}>, "many">;
|
|
76
|
+
dependsOn: z.ZodArray<z.ZodString, "many">;
|
|
77
|
+
status: z.ZodEnum<["proposed", "negotiating", "agreed", "in-progress", "evaluating", "passed", "failed", "needs-rework"]>;
|
|
78
|
+
evalResults: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
|
|
79
|
+
generatorNotes: z.ZodOptional<z.ZodString>;
|
|
80
|
+
evaluatorFeedback: z.ZodOptional<z.ZodString>;
|
|
81
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
82
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
83
|
+
}, "strip", z.ZodTypeAny, {
|
|
84
|
+
description: string;
|
|
85
|
+
status: "passed" | "proposed" | "negotiating" | "agreed" | "in-progress" | "evaluating" | "failed" | "needs-rework";
|
|
86
|
+
id: string;
|
|
87
|
+
feature: string;
|
|
88
|
+
successCriteria: {
|
|
89
|
+
description: string;
|
|
90
|
+
id: string;
|
|
91
|
+
verificationMethod: string;
|
|
92
|
+
passed: boolean;
|
|
93
|
+
notes?: string | undefined;
|
|
94
|
+
}[];
|
|
95
|
+
expectedChanges: {
|
|
96
|
+
description: string;
|
|
97
|
+
path: string;
|
|
98
|
+
action: "create" | "modify" | "delete";
|
|
99
|
+
}[];
|
|
100
|
+
dependsOn: string[];
|
|
101
|
+
evalResults?: unknown[] | undefined;
|
|
102
|
+
generatorNotes?: string | undefined;
|
|
103
|
+
evaluatorFeedback?: string | undefined;
|
|
104
|
+
startedAt?: string | undefined;
|
|
105
|
+
completedAt?: string | undefined;
|
|
106
|
+
}, {
|
|
107
|
+
description: string;
|
|
108
|
+
status: "passed" | "proposed" | "negotiating" | "agreed" | "in-progress" | "evaluating" | "failed" | "needs-rework";
|
|
109
|
+
id: string;
|
|
110
|
+
feature: string;
|
|
111
|
+
successCriteria: {
|
|
112
|
+
description: string;
|
|
113
|
+
id: string;
|
|
114
|
+
verificationMethod: string;
|
|
115
|
+
passed: boolean;
|
|
116
|
+
notes?: string | undefined;
|
|
117
|
+
}[];
|
|
118
|
+
expectedChanges: {
|
|
119
|
+
description: string;
|
|
120
|
+
path: string;
|
|
121
|
+
action: "create" | "modify" | "delete";
|
|
122
|
+
}[];
|
|
123
|
+
dependsOn: string[];
|
|
124
|
+
evalResults?: unknown[] | undefined;
|
|
125
|
+
generatorNotes?: string | undefined;
|
|
126
|
+
evaluatorFeedback?: string | undefined;
|
|
127
|
+
startedAt?: string | undefined;
|
|
128
|
+
completedAt?: string | undefined;
|
|
129
|
+
}>;
|
|
130
|
+
export type SprintContract = z.infer<typeof SprintContractSchema>;
|
|
131
|
+
/**
|
|
132
|
+
* Create a new sprint contract in "proposed" status.
|
|
133
|
+
*/
|
|
134
|
+
export declare function createContract(feature: string, description: string, criteria: Omit<SuccessCriterion, "passed">[]): SprintContract;
|
|
135
|
+
/**
|
|
136
|
+
* Return a new contract with an updated status.
|
|
137
|
+
* Automatically sets `startedAt` when moving to "in-progress"
|
|
138
|
+
* and `completedAt` when moving to a terminal status.
|
|
139
|
+
*/
|
|
140
|
+
export declare function updateContractStatus(contract: SprintContract, status: ContractStatus): SprintContract;
|
|
141
|
+
//# sourceMappingURL=sprint-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprint-contract.d.ts","sourceRoot":"","sources":["../../src/contracts/sprint-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,oBAAoB,mHAS/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,gBAAgB,2CAAyC,CAAC;AACvE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;EAMjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAMlE;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,EAAE,GAC3C,cAAc,CAgBhB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,cAAc,GACrB,cAAc,CAgBhB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ── Enums ───────────────────────────────────────────────────────────
|
|
3
|
+
export const ContractStatusSchema = z.enum([
|
|
4
|
+
"proposed",
|
|
5
|
+
"negotiating",
|
|
6
|
+
"agreed",
|
|
7
|
+
"in-progress",
|
|
8
|
+
"evaluating",
|
|
9
|
+
"passed",
|
|
10
|
+
"failed",
|
|
11
|
+
"needs-rework",
|
|
12
|
+
]);
|
|
13
|
+
export const FileActionSchema = z.enum(["create", "modify", "delete"]);
|
|
14
|
+
// ── Sub-types ───────────────────────────────────────────────────────
|
|
15
|
+
export const SuccessCriterionSchema = z.object({
|
|
16
|
+
id: z.string().min(1),
|
|
17
|
+
description: z.string().min(1),
|
|
18
|
+
verificationMethod: z.string().min(1),
|
|
19
|
+
passed: z.boolean(),
|
|
20
|
+
notes: z.string().optional(),
|
|
21
|
+
});
|
|
22
|
+
export const FileChangeSchema = z.object({
|
|
23
|
+
path: z.string().min(1),
|
|
24
|
+
action: FileActionSchema,
|
|
25
|
+
description: z.string().min(1),
|
|
26
|
+
});
|
|
27
|
+
// ── Sprint Contract ─────────────────────────────────────────────────
|
|
28
|
+
export const SprintContractSchema = z.object({
|
|
29
|
+
id: z.string().min(1),
|
|
30
|
+
feature: z.string().min(1),
|
|
31
|
+
description: z.string().min(1),
|
|
32
|
+
successCriteria: z.array(SuccessCriterionSchema),
|
|
33
|
+
expectedChanges: z.array(FileChangeSchema),
|
|
34
|
+
dependsOn: z.array(z.string()),
|
|
35
|
+
status: ContractStatusSchema,
|
|
36
|
+
evalResults: z.array(z.unknown()).optional(),
|
|
37
|
+
generatorNotes: z.string().optional(),
|
|
38
|
+
evaluatorFeedback: z.string().optional(),
|
|
39
|
+
startedAt: z.string().datetime().optional(),
|
|
40
|
+
completedAt: z.string().datetime().optional(),
|
|
41
|
+
});
|
|
42
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
43
|
+
let contractCounter = 0;
|
|
44
|
+
/**
|
|
45
|
+
* Create a new sprint contract in "proposed" status.
|
|
46
|
+
*/
|
|
47
|
+
export function createContract(feature, description, criteria) {
|
|
48
|
+
contractCounter++;
|
|
49
|
+
const id = `sprint-${Date.now()}-${contractCounter}`;
|
|
50
|
+
return {
|
|
51
|
+
id,
|
|
52
|
+
feature,
|
|
53
|
+
description,
|
|
54
|
+
successCriteria: criteria.map((c) => ({
|
|
55
|
+
...c,
|
|
56
|
+
passed: false,
|
|
57
|
+
})),
|
|
58
|
+
expectedChanges: [],
|
|
59
|
+
dependsOn: [],
|
|
60
|
+
status: "proposed",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Return a new contract with an updated status.
|
|
65
|
+
* Automatically sets `startedAt` when moving to "in-progress"
|
|
66
|
+
* and `completedAt` when moving to a terminal status.
|
|
67
|
+
*/
|
|
68
|
+
export function updateContractStatus(contract, status) {
|
|
69
|
+
const now = new Date().toISOString();
|
|
70
|
+
const updates = { status };
|
|
71
|
+
if (status === "in-progress" && !contract.startedAt) {
|
|
72
|
+
updates.startedAt = now;
|
|
73
|
+
}
|
|
74
|
+
if ((status === "passed" || status === "failed") &&
|
|
75
|
+
!contract.completedAt) {
|
|
76
|
+
updates.completedAt = now;
|
|
77
|
+
}
|
|
78
|
+
return { ...contract, ...updates };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=sprint-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprint-contract.js","sourceRoot":"","sources":["../../src/contracts/sprint-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EvaluatorPlugin, EvalContext, EvalResult, BoberConfig } from "../plugin-interface.js";
|
|
2
|
+
export declare class ApiCheckEvaluator implements EvaluatorPlugin {
|
|
3
|
+
readonly name = "API Check";
|
|
4
|
+
readonly description = "Verifies API endpoints respond with expected status codes and shapes.";
|
|
5
|
+
canRun(_projectRoot: string, _config: BoberConfig): Promise<boolean>;
|
|
6
|
+
evaluate(context: EvalContext): Promise<EvalResult>;
|
|
7
|
+
private buildFeedback;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Factory function for the registry.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createApiCheckEvaluator(): EvaluatorPlugin;
|
|
13
|
+
//# sourceMappingURL=api-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-check.d.ts","sourceRoot":"","sources":["../../../src/evaluators/builtin/api-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,UAAU,EAEV,WAAW,EAEZ,MAAM,wBAAwB,CAAC;AA+EhC,qBAAa,iBAAkB,YAAW,eAAe;IACvD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,2EAA2E;IAEzF,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAOpE,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAkFzD,OAAO,CAAC,aAAa;CAUtB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,eAAe,CAEzD"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// ── Helpers ────────────────────────────────────────────────────────
|
|
2
|
+
/**
|
|
3
|
+
* Infer API endpoints from the sprint contract description and
|
|
4
|
+
* expected changes. This is a best-effort heuristic.
|
|
5
|
+
*/
|
|
6
|
+
function inferEndpointsFromContract(contract) {
|
|
7
|
+
const endpoints = [];
|
|
8
|
+
// Look for REST-like patterns in the contract text.
|
|
9
|
+
const allText = [
|
|
10
|
+
contract.description,
|
|
11
|
+
...contract.successCriteria.map((c) => c.description),
|
|
12
|
+
...contract.expectedChanges.map((c) => c.description),
|
|
13
|
+
].join("\n");
|
|
14
|
+
// Match patterns like "GET /api/users", "POST /api/items"
|
|
15
|
+
const httpPattern = /\b(GET|POST|PUT|PATCH|DELETE)\s+(\/\S+)/gi;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = httpPattern.exec(allText)) !== null) {
|
|
18
|
+
const method = match[1].toUpperCase();
|
|
19
|
+
const path = match[2];
|
|
20
|
+
// Default expected status based on method.
|
|
21
|
+
const expectedStatus = method === "POST" ? 201 : 200;
|
|
22
|
+
endpoints.push({ method, path, expectedStatus });
|
|
23
|
+
}
|
|
24
|
+
return endpoints;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Make an HTTP request and return status + response body text.
|
|
28
|
+
* Uses built-in fetch (available in Node 18+).
|
|
29
|
+
*/
|
|
30
|
+
async function makeRequest(baseUrl, spec, timeout) {
|
|
31
|
+
const url = new URL(spec.path, baseUrl).toString();
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
method: spec.method,
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
...spec.headers,
|
|
40
|
+
},
|
|
41
|
+
body: spec.body ? JSON.stringify(spec.body) : undefined,
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
});
|
|
44
|
+
const body = await response.text();
|
|
45
|
+
return { status: response.status, body, ok: response.ok };
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ── Evaluator ──────────────────────────────────────────────────────
|
|
52
|
+
const DEFAULT_PER_REQUEST_TIMEOUT_MS = 10_000;
|
|
53
|
+
export class ApiCheckEvaluator {
|
|
54
|
+
name = "API Check";
|
|
55
|
+
description = "Verifies API endpoints respond with expected status codes and shapes.";
|
|
56
|
+
async canRun(_projectRoot, _config) {
|
|
57
|
+
// API check can run if the strategy config includes endpoints
|
|
58
|
+
// or the contract mentions API paths. We return true optimistically
|
|
59
|
+
// and let evaluate() handle the specifics.
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
async evaluate(context) {
|
|
63
|
+
const { strategy, contract } = context;
|
|
64
|
+
const timestamp = new Date().toISOString();
|
|
65
|
+
const perRequestTimeout = strategy.config?.timeout ?? DEFAULT_PER_REQUEST_TIMEOUT_MS;
|
|
66
|
+
const baseUrl = strategy.config?.baseUrl ?? "http://localhost:3000";
|
|
67
|
+
// Collect endpoints from config or infer from contract.
|
|
68
|
+
const configEndpoints = strategy.config?.endpoints ?? [];
|
|
69
|
+
const inferredEndpoints = configEndpoints.length === 0 ? inferEndpointsFromContract(contract) : [];
|
|
70
|
+
const endpoints = [...configEndpoints, ...inferredEndpoints];
|
|
71
|
+
if (endpoints.length === 0) {
|
|
72
|
+
return {
|
|
73
|
+
evaluator: this.name,
|
|
74
|
+
passed: true,
|
|
75
|
+
score: 100,
|
|
76
|
+
details: [
|
|
77
|
+
{
|
|
78
|
+
criterion: "API endpoint detection",
|
|
79
|
+
passed: true,
|
|
80
|
+
message: "No API endpoints to check (none configured or inferred).",
|
|
81
|
+
severity: "info",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
summary: "No API endpoints to verify.",
|
|
85
|
+
feedback: "No API endpoints were found in the strategy config or sprint contract.",
|
|
86
|
+
timestamp,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const details = [];
|
|
90
|
+
let passedCount = 0;
|
|
91
|
+
for (const endpoint of endpoints) {
|
|
92
|
+
try {
|
|
93
|
+
const result = await makeRequest(baseUrl, endpoint, perRequestTimeout);
|
|
94
|
+
const statusMatches = result.status === endpoint.expectedStatus;
|
|
95
|
+
if (statusMatches) {
|
|
96
|
+
passedCount++;
|
|
97
|
+
details.push({
|
|
98
|
+
criterion: `${endpoint.method} ${endpoint.path}`,
|
|
99
|
+
passed: true,
|
|
100
|
+
message: `Status ${result.status} (expected ${endpoint.expectedStatus})`,
|
|
101
|
+
severity: "info",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
details.push({
|
|
106
|
+
criterion: `${endpoint.method} ${endpoint.path}`,
|
|
107
|
+
passed: false,
|
|
108
|
+
message: `Status ${result.status}, expected ${endpoint.expectedStatus}. Body: ${result.body.slice(0, 200)}`,
|
|
109
|
+
severity: "error",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
details.push({
|
|
115
|
+
criterion: `${endpoint.method} ${endpoint.path}`,
|
|
116
|
+
passed: false,
|
|
117
|
+
message: `Request failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
118
|
+
severity: "error",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const total = endpoints.length;
|
|
123
|
+
const allPassed = passedCount === total;
|
|
124
|
+
const score = total === 0 ? 100 : Math.round((passedCount / total) * 100);
|
|
125
|
+
return {
|
|
126
|
+
evaluator: this.name,
|
|
127
|
+
passed: allPassed,
|
|
128
|
+
score,
|
|
129
|
+
details,
|
|
130
|
+
summary: `API Check: ${passedCount}/${total} endpoints passed.`,
|
|
131
|
+
feedback: this.buildFeedback(allPassed, details),
|
|
132
|
+
timestamp,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
buildFeedback(allPassed, details) {
|
|
136
|
+
if (allPassed)
|
|
137
|
+
return "All API endpoints responded as expected.";
|
|
138
|
+
const failures = details.filter((d) => !d.passed);
|
|
139
|
+
const lines = ["The following API endpoints did not respond as expected:", ""];
|
|
140
|
+
for (const f of failures) {
|
|
141
|
+
lines.push(` ${f.criterion}: ${f.message}`);
|
|
142
|
+
}
|
|
143
|
+
return lines.join("\n");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Factory function for the registry.
|
|
148
|
+
*/
|
|
149
|
+
export function createApiCheckEvaluator() {
|
|
150
|
+
return new ApiCheckEvaluator();
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=api-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-check.js","sourceRoot":"","sources":["../../../src/evaluators/builtin/api-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EvaluatorPlugin, EvalContext, EvalResult, BoberConfig } from "../plugin-interface.js";
|
|
2
|
+
export declare class BuildCheckEvaluator implements EvaluatorPlugin {
|
|
3
|
+
readonly name = "Build Check";
|
|
4
|
+
readonly description = "Runs the project build command and checks for success.";
|
|
5
|
+
canRun(projectRoot: string, config: BoberConfig): Promise<boolean>;
|
|
6
|
+
evaluate(context: EvalContext): Promise<EvalResult>;
|
|
7
|
+
/**
|
|
8
|
+
* Attempt to parse common error patterns from build output.
|
|
9
|
+
*/
|
|
10
|
+
private extractBuildErrors;
|
|
11
|
+
private buildFeedback;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Factory function for the registry.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBuildCheckEvaluator(): EvaluatorPlugin;
|
|
17
|
+
//# sourceMappingURL=build-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-check.d.ts","sourceRoot":"","sources":["../../../src/evaluators/builtin/build-check.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,UAAU,EAEV,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAyBhC,qBAAa,mBAAoB,YAAW,eAAe;IACzD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,4DAA4D;IAE1E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAMlE,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA4FzD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgC1B,OAAO,CAAC,aAAa;CAOtB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,eAAe,CAE3D"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { execa } from "execa";
|
|
4
|
+
async function detectBuildCommand(projectRoot) {
|
|
5
|
+
try {
|
|
6
|
+
const raw = await readFile(join(projectRoot, "package.json"), "utf-8");
|
|
7
|
+
const pkg = JSON.parse(raw);
|
|
8
|
+
if (pkg.scripts?.build) {
|
|
9
|
+
return "npm run build";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// no package.json or unparseable
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
// ── Evaluator ──────────────────────────────────────────────────────
|
|
18
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
19
|
+
export class BuildCheckEvaluator {
|
|
20
|
+
name = "Build Check";
|
|
21
|
+
description = "Runs the project build command and checks for success.";
|
|
22
|
+
async canRun(projectRoot, config) {
|
|
23
|
+
if (config.commands.build)
|
|
24
|
+
return true;
|
|
25
|
+
const detected = await detectBuildCommand(projectRoot);
|
|
26
|
+
return detected !== null;
|
|
27
|
+
}
|
|
28
|
+
async evaluate(context) {
|
|
29
|
+
const { projectRoot, config, strategy } = context;
|
|
30
|
+
const timestamp = new Date().toISOString();
|
|
31
|
+
const timeout = strategy.config?.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
32
|
+
const command = config.commands.build ?? (await detectBuildCommand(projectRoot));
|
|
33
|
+
if (!command) {
|
|
34
|
+
return {
|
|
35
|
+
evaluator: this.name,
|
|
36
|
+
passed: false,
|
|
37
|
+
score: 0,
|
|
38
|
+
details: [
|
|
39
|
+
{
|
|
40
|
+
criterion: "Build command detection",
|
|
41
|
+
passed: false,
|
|
42
|
+
message: "No build command found in config or package.json.",
|
|
43
|
+
severity: "error",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
summary: "No build command available.",
|
|
47
|
+
feedback: "Configure a build command in bober config (commands.build) or add a 'build' script to package.json.",
|
|
48
|
+
timestamp,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const [cmd, ...args] = command.split(/\s+/);
|
|
52
|
+
try {
|
|
53
|
+
const result = await execa(cmd, args, {
|
|
54
|
+
cwd: projectRoot,
|
|
55
|
+
timeout,
|
|
56
|
+
reject: false,
|
|
57
|
+
all: true,
|
|
58
|
+
});
|
|
59
|
+
const allOutput = result.all ?? result.stdout ?? "";
|
|
60
|
+
if (result.exitCode === 0) {
|
|
61
|
+
return {
|
|
62
|
+
evaluator: this.name,
|
|
63
|
+
passed: true,
|
|
64
|
+
score: 100,
|
|
65
|
+
details: [],
|
|
66
|
+
summary: "Build succeeded.",
|
|
67
|
+
feedback: "The project builds successfully. No changes needed.",
|
|
68
|
+
timestamp,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Build failed — extract useful error information.
|
|
72
|
+
const details = this.extractBuildErrors(allOutput);
|
|
73
|
+
if (details.length === 0) {
|
|
74
|
+
details.push({
|
|
75
|
+
criterion: "Build execution",
|
|
76
|
+
passed: false,
|
|
77
|
+
message: allOutput.slice(0, 2000) || `Build exited with code ${result.exitCode}`,
|
|
78
|
+
severity: "error",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
evaluator: this.name,
|
|
83
|
+
passed: false,
|
|
84
|
+
score: 0,
|
|
85
|
+
details,
|
|
86
|
+
summary: `Build failed with exit code ${result.exitCode}.`,
|
|
87
|
+
feedback: this.buildFeedback(allOutput),
|
|
88
|
+
timestamp,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return {
|
|
93
|
+
evaluator: this.name,
|
|
94
|
+
passed: false,
|
|
95
|
+
score: 0,
|
|
96
|
+
details: [
|
|
97
|
+
{
|
|
98
|
+
criterion: "Build execution",
|
|
99
|
+
passed: false,
|
|
100
|
+
message: err instanceof Error ? err.message : String(err),
|
|
101
|
+
severity: "error",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
summary: "Build command failed to execute.",
|
|
105
|
+
feedback: `The build command could not be run: ${err instanceof Error ? err.message : String(err)}`,
|
|
106
|
+
timestamp,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Attempt to parse common error patterns from build output.
|
|
112
|
+
*/
|
|
113
|
+
extractBuildErrors(output) {
|
|
114
|
+
const details = [];
|
|
115
|
+
// Try to find TypeScript-style errors: file(line,col): error TS1234: ...
|
|
116
|
+
const tsPattern = /^(.+?)\((\d+),(\d+)\):\s+error\s+\S+:\s+(.+)$/gm;
|
|
117
|
+
let match;
|
|
118
|
+
while ((match = tsPattern.exec(output)) !== null) {
|
|
119
|
+
details.push({
|
|
120
|
+
criterion: "Build error",
|
|
121
|
+
passed: false,
|
|
122
|
+
message: match[4],
|
|
123
|
+
file: match[1],
|
|
124
|
+
line: parseInt(match[2], 10),
|
|
125
|
+
severity: "error",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// Try webpack/vite style: ERROR in ./src/foo.ts
|
|
129
|
+
const bundlerPattern = /^ERROR\s+in\s+(\S+)/gm;
|
|
130
|
+
while ((match = bundlerPattern.exec(output)) !== null) {
|
|
131
|
+
details.push({
|
|
132
|
+
criterion: "Build error",
|
|
133
|
+
passed: false,
|
|
134
|
+
message: `Build error in ${match[1]}`,
|
|
135
|
+
file: match[1],
|
|
136
|
+
severity: "error",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return details;
|
|
140
|
+
}
|
|
141
|
+
buildFeedback(output) {
|
|
142
|
+
const lines = ["The build failed. Here is the relevant output:", ""];
|
|
143
|
+
// Show the last 2000 chars which typically contain the actual errors.
|
|
144
|
+
const tail = output.length > 2000 ? output.slice(-2000) : output;
|
|
145
|
+
lines.push(tail);
|
|
146
|
+
return lines.join("\n");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Factory function for the registry.
|
|
151
|
+
*/
|
|
152
|
+
export function createBuildCheckEvaluator() {
|
|
153
|
+
return new BuildCheckEvaluator();
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=build-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-check.js","sourceRoot":"","sources":["../../../src/evaluators/builtin/build-check.ts"],"names":[],"mappings":"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"}
|