]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(sandcastle): organize constants by domain with coherent naming
authorJérôme Benoit <jerome.benoit@sap.com>
Thu, 7 May 2026 06:49:45 +0000 (08:49 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Thu, 7 May 2026 06:49:57 +0000 (08:49 +0200)
.sandcastle/constants.ts
.sandcastle/finalizer.ts
.sandcastle/main.ts
.sandcastle/refinement-loop.ts
.sandcastle/task-source.ts

index bd6a96358a905eb5f0d1995d12251906d19ee266..eb64759705a044adde6e20da986eb599efb76aa9 100644 (file)
@@ -1,17 +1,31 @@
 import { execFileSync } from 'node:child_process'
 import { existsSync } from 'node:fs'
 
-export const AGENT_IDLE_TIMEOUT_S = 300
+// ── Agent ────────────────────────────────────────────────────────────────────
 
 export const AGENT_ACTOR_MODEL = 'github-copilot/claude-sonnet-4.6'
 
 export const AGENT_CRITIC_MODEL = 'github-copilot/gpt-5.4'
 
-export const BRANCH_PREFIX = 'agent/issue'
+export const AGENT_IDLE_TIMEOUT_S = 300
 
-export const COMPLETION_SIGNAL = '<promise>COMPLETE</promise>'
+export const AGENT_ITERATION_BUDGET = 50
 
-export const CONTEXT_HASH_RADIUS = 3
+export const AGENT_MAX_CRITIC_ROUNDS = 10
+
+export const AGENT_PLANNER_MODEL = 'github-copilot/claude-opus-4.6'
+
+export const AGENT_TASK_TIMEOUT_MS = 6_000_000
+
+// ── Git ──────────────────────────────────────────────────────────────────────
+
+export const GIT_BRANCH_PREFIX = 'agent/issue'
+
+export const GIT_PUSH_TIMEOUT_MS = 60_000
+
+export const GIT_TIMEOUT_MS = 30_000
+
+// ── Docker ───────────────────────────────────────────────────────────────────
 
 export const DOCKER_IMAGE = 'sandcastle-sandbox'
 
@@ -41,35 +55,33 @@ function resolvePnpmStorePath (): string | undefined {
   }
 }
 
-export const GIT_TIMEOUT_MS = 30_000
-
-export const GRACE_TIMEOUT_MS = 30_000
+// ── GitHub ───────────────────────────────────────────────────────────────────
 
-export const HASH_PREFIX_LENGTH = 16
+export const GITHUB_ISSUE_LABEL = 'sandcastle'
 
-export const ITERATION_BUDGET_PER_ROUND = 50
+export const GITHUB_MAX_ISSUES_FETCH = 50
 
-export const ISSUE_LABEL = 'sandcastle'
+export const GITHUB_MAX_PRS_FETCH = 200
 
-export const MAX_ISSUES_FETCH = 50
+// ── Validation ───────────────────────────────────────────────────────────────
 
-export const MAX_PRS_FETCH = 200
+export const VALIDATION_COMMAND =
+  'pnpm format && pnpm typecheck && pnpm lint && pnpm build && pnpm test'
 
-export const MAX_PARALLEL = 5
+export const VALIDATION_TIMEOUT_MS = 300_000
 
-export const MAX_STDERR_CHARS = 500
+// ── Limits & Protocol ────────────────────────────────────────────────────────
 
-export const MAX_CRITIC_ROUNDS = 10
+export const COMPLETION_SIGNAL = '<promise>COMPLETE</promise>'
 
-export const MAX_TITLE_LENGTH = 200
+export const CONTEXT_HASH_RADIUS = 3
 
-export const AGENT_PLANNER_MODEL = 'github-copilot/claude-opus-4.6'
+export const GRACE_TIMEOUT_MS = 30_000
 
-export const PUSH_TIMEOUT_MS = 60_000
+export const HASH_PREFIX_LENGTH = 16
 
-export const TASK_TIMEOUT_MS = 100 * 60 * 1000
+export const MAX_PARALLEL = 5
 
-export const VALIDATION_COMMAND =
-  'pnpm format && pnpm typecheck && pnpm lint && pnpm build && pnpm test'
+export const MAX_STDERR_CHARS = 500
 
-export const VALIDATION_TIMEOUT_MS = 300_000
+export const MAX_TITLE_CHARS = 200
index a583110717e9ab156e9e0944fd8683d328d04103..7ff3f89d2dd4039bf81a51b91b9f83221cc60601 100644 (file)
@@ -3,9 +3,9 @@ import crypto from 'node:crypto'
 import type { LoopResult, TaskSpec } from './types.js'
 
 import {
+  GIT_PUSH_TIMEOUT_MS,
   GIT_TIMEOUT_MS,
   MAX_STDERR_CHARS,
-  PUSH_TIMEOUT_MS,
   VALIDATION_COMMAND,
   VALIDATION_TIMEOUT_MS,
 } from './constants.js'
@@ -124,7 +124,7 @@ export async function pushBranch (
     try {
       await execFileAsync('git', ['push', '--force-with-lease', 'origin', 'HEAD'], {
         cwd,
-        timeout: PUSH_TIMEOUT_MS,
+        timeout: GIT_PUSH_TIMEOUT_MS,
       })
       return true
     } catch (pushErr: unknown) {
@@ -136,7 +136,7 @@ export async function pushBranch (
           ['push', 'origin', `HEAD:refs/heads/rescue/${spec.branch}-${suffix}`],
           {
             cwd,
-            timeout: PUSH_TIMEOUT_MS,
+            timeout: GIT_PUSH_TIMEOUT_MS,
           }
         )
         console.warn(
@@ -153,7 +153,7 @@ export async function pushBranch (
     try {
       await execFileAsync('git', ['push', '-u', 'origin', 'HEAD'], {
         cwd,
-        timeout: PUSH_TIMEOUT_MS,
+        timeout: GIT_PUSH_TIMEOUT_MS,
       })
       return true
     } catch (pushErr: unknown) {
index e42ea879ac14e5c597c8794670b38a4fe5b4a8a0..0e76bb220006c3384a07a7daf573794fc822b83b 100644 (file)
@@ -5,23 +5,23 @@ import type { TaskSpec } from './types.js'
 
 import { ConcurrencyPool } from './concurrency-pool.js'
 import {
-  BRANCH_PREFIX,
+  AGENT_ITERATION_BUDGET,
+  AGENT_MAX_CRITIC_ROUNDS,
+  AGENT_TASK_TIMEOUT_MS,
   DOCKER_IMAGE,
   DOCKER_MOUNTS,
-  ISSUE_LABEL,
-  ITERATION_BUDGET_PER_ROUND,
-  MAX_CRITIC_ROUNDS,
+  GIT_BRANCH_PREFIX,
+  GITHUB_ISSUE_LABEL,
   MAX_PARALLEL,
-  TASK_TIMEOUT_MS,
 } from './constants.js'
 import { runRefinementLoop } from './refinement-loop.js'
 import { implementStrategy } from './strategies/implement/strategy.js'
 import { GithubIssueSource } from './task-source.js'
 
 const source = new GithubIssueSource({
-  branchPrefix: BRANCH_PREFIX,
+  branchPrefix: GIT_BRANCH_PREFIX,
   dockerImage: DOCKER_IMAGE,
-  label: ISSUE_LABEL,
+  label: GITHUB_ISSUE_LABEL,
 })
 
 let tasks: TaskSpec[]
@@ -43,8 +43,8 @@ if (tasks.length === 0) {
       pool.run(async () => {
         const ac = new AbortController()
         const timer = setTimeout(() => {
-          ac.abort(new Error(`Task #${spec.id} timed out after ${String(TASK_TIMEOUT_MS)}ms`))
-        }, TASK_TIMEOUT_MS)
+          ac.abort(new Error(`Task #${spec.id} timed out after ${String(AGENT_TASK_TIMEOUT_MS)}ms`))
+        }, AGENT_TASK_TIMEOUT_MS)
         timer.unref()
 
         try {
@@ -58,8 +58,8 @@ if (tasks.length === 0) {
           })
 
           const loopResult = await runRefinementLoop(spec, sandbox, implementStrategy, {
-            iterationBudget: ITERATION_BUDGET_PER_ROUND,
-            maxRounds: MAX_CRITIC_ROUNDS,
+            iterationBudget: AGENT_ITERATION_BUDGET,
+            maxRounds: AGENT_MAX_CRITIC_ROUNDS,
             postLoopValidationRetry: true,
             signal: ac.signal,
           })
index 9983e51836a141c61e6adff15494e9d75e9e1e39..3245633780328c3f5b182c753abb1c31d216c1d1 100644 (file)
@@ -16,11 +16,11 @@ import {
   AGENT_ACTOR_MODEL,
   AGENT_CRITIC_MODEL,
   AGENT_IDLE_TIMEOUT_S,
+  AGENT_ITERATION_BUDGET,
+  AGENT_MAX_CRITIC_ROUNDS,
   COMPLETION_SIGNAL,
   CONTEXT_HASH_RADIUS,
   HASH_PREFIX_LENGTH,
-  ITERATION_BUDGET_PER_ROUND,
-  MAX_CRITIC_ROUNDS,
 } from './constants.js'
 import { runValidation } from './finalizer.js'
 import { parseFindingsSafe } from './types.js'
@@ -568,8 +568,8 @@ async function resetToBestState (
  */
 function resolveLoopOptions (opts: RefinementLoopOptions | undefined): ResolvedLoopOptions {
   return {
-    budget: opts?.iterationBudget ?? ITERATION_BUDGET_PER_ROUND,
-    maxRounds: opts?.maxRounds ?? MAX_CRITIC_ROUNDS,
+    budget: opts?.iterationBudget ?? AGENT_ITERATION_BUDGET,
+    maxRounds: opts?.maxRounds ?? AGENT_MAX_CRITIC_ROUNDS,
     onRoundComplete: opts?.onRoundComplete ?? (() => undefined),
   }
 }
index 7e71897ce3c20c6be64ae39669412edb90802226..7bf6e812937b522e43cd45d44e0404a94020703a 100644 (file)
@@ -10,10 +10,10 @@ import {
   COMPLETION_SIGNAL,
   DOCKER_MOUNTS,
   GIT_TIMEOUT_MS,
-  MAX_ISSUES_FETCH,
-  MAX_PRS_FETCH,
-  MAX_TITLE_LENGTH,
-  TASK_TIMEOUT_MS,
+  GITHUB_MAX_ISSUES_FETCH,
+  GITHUB_MAX_PRS_FETCH,
+  AGENT_TASK_TIMEOUT_MS,
+  MAX_TITLE_CHARS,
 } from './constants.js'
 import { execFileAsync, toErrorMessage } from './utils.js'
 
@@ -107,7 +107,7 @@ export class GithubIssueSource implements TaskSource {
           },
           promptFile: './.sandcastle/plan-prompt.md',
           sandbox: docker({ imageName: this.dockerImage, mounts: [...DOCKER_MOUNTS] }),
-          signal: AbortSignal.timeout(TASK_TIMEOUT_MS),
+          signal: AbortSignal.timeout(AGENT_TASK_TIMEOUT_MS),
         })
       } catch (err: unknown) {
         console.error(`Planner timed out or failed: ${toErrorMessage(err)}`)
@@ -166,7 +166,7 @@ export class GithubIssueSource implements TaskSource {
           '--json',
           'number,title,labels,body',
           '--limit',
-          String(MAX_ISSUES_FETCH),
+          String(GITHUB_MAX_ISSUES_FETCH),
           '--label',
           this.label,
         ],
@@ -210,7 +210,7 @@ export class GithubIssueSource implements TaskSource {
           '--json',
           'headRefName',
           '--limit',
-          String(MAX_PRS_FETCH),
+          String(GITHUB_MAX_PRS_FETCH),
         ],
         { encoding: 'utf-8', maxBuffer: 8 * 1024 * 1024, timeout: GIT_TIMEOUT_MS }
       )
@@ -249,7 +249,7 @@ export class GithubIssueSource implements TaskSource {
           if (typeof item.id !== 'string' || !/^\d+$/.test(item.id)) return false
           if (typeof item.branch !== 'string' || !this.branchPattern.test(item.branch)) return false
           if (typeof item.title !== 'string') return false
-          if (item.title.length > MAX_TITLE_LENGTH) return false
+          if (item.title.length > MAX_TITLE_CHARS) return false
           // eslint-disable-next-line no-control-regex
           if (/[\x00-\x1f]/.test(item.title)) return false
           return true