xcoder-dna 0.0.0-stage → 1.3.1
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/LICENSE +21 -0
- package/README.md +87 -2
- package/dist/agents/ai-chat-debate.d.ts +36 -0
- package/dist/agents/ai-chat-debate.js +300 -0
- package/dist/agents/ai-chat-report-writer.d.ts +7 -0
- package/dist/agents/ai-chat-report-writer.js +100 -0
- package/dist/agents/duplicate-detector.d.ts +41 -0
- package/dist/agents/duplicate-detector.js +65 -0
- package/dist/agents/genesis-agent.d.ts +61 -0
- package/dist/agents/genesis-agent.js +340 -0
- package/dist/agents/samurai-agent.d.ts +53 -0
- package/dist/agents/samurai-agent.js +279 -0
- package/dist/agents/sub-agent.d.ts +56 -0
- package/dist/agents/sub-agent.js +353 -0
- package/dist/backlog/backlog-requirement-validator.d.ts +10 -0
- package/dist/backlog/backlog-requirement-validator.js +60 -0
- package/dist/backlog/backlog-store.d.ts +29 -0
- package/dist/backlog/backlog-store.js +148 -0
- package/dist/backlog/po-agent.d.ts +16 -0
- package/dist/backlog/po-agent.js +121 -0
- package/dist/backlog/types.d.ts +25 -0
- package/dist/backlog/types.js +4 -0
- package/dist/bench/run.d.ts +11 -0
- package/dist/bench/run.js +185 -0
- package/dist/bench/types.d.ts +50 -0
- package/dist/bench/types.js +1 -0
- package/dist/cli/swarm.d.ts +10 -0
- package/dist/cli/swarm.js +100 -0
- package/dist/cli/task.d.ts +14 -0
- package/dist/cli/task.js +121 -0
- package/dist/cli/wbc-arg.d.ts +6 -0
- package/dist/cli/wbc-arg.js +40 -0
- package/dist/cli/wbc.d.ts +45 -0
- package/dist/cli/wbc.js +98 -0
- package/dist/commands/license.d.ts +9 -0
- package/dist/commands/license.js +140 -0
- package/dist/commands/release.d.ts +44 -0
- package/dist/commands/release.js +180 -0
- package/dist/commands/test.d.ts +50 -0
- package/dist/commands/test.js +385 -0
- package/dist/config/loadConfig.d.ts +82 -0
- package/dist/config/loadConfig.js +240 -0
- package/dist/config/secure-mode.d.ts +29 -0
- package/dist/config/secure-mode.js +63 -0
- package/dist/config/user-config.d.ts +39 -0
- package/dist/config/user-config.js +202 -0
- package/dist/engine/reasoning-engine.d.ts +21 -0
- package/dist/engine/reasoning-engine.js +59 -0
- package/dist/events/bus.d.ts +22 -0
- package/dist/events/bus.js +18 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +77 -0
- package/dist/indexing/ignoreRules.d.ts +1 -0
- package/dist/indexing/ignoreRules.js +53 -0
- package/dist/instance-swarm/instance-swarm-orchestrator.d.ts +57 -0
- package/dist/instance-swarm/instance-swarm-orchestrator.js +204 -0
- package/dist/instance-swarm/protocol-name-resolver.d.ts +23 -0
- package/dist/instance-swarm/protocol-name-resolver.js +64 -0
- package/dist/license/gate.d.ts +31 -0
- package/dist/license/gate.js +188 -0
- package/dist/license/http-client.d.ts +43 -0
- package/dist/license/http-client.js +195 -0
- package/dist/license/manager.d.ts +39 -0
- package/dist/license/manager.js +175 -0
- package/dist/license/receipt.d.ts +27 -0
- package/dist/license/receipt.js +108 -0
- package/dist/license/state-codec.d.ts +72 -0
- package/dist/license/state-codec.js +218 -0
- package/dist/license/state-paths.d.ts +17 -0
- package/dist/license/state-paths.js +64 -0
- package/dist/license/store.d.ts +44 -0
- package/dist/license/store.js +223 -0
- package/dist/license/trust-anchor.d.ts +24 -0
- package/dist/license/trust-anchor.js +74 -0
- package/dist/license/types.d.ts +34 -0
- package/dist/license/types.js +19 -0
- package/dist/llm/budget.d.ts +23 -0
- package/dist/llm/budget.js +58 -0
- package/dist/llm/client.d.ts +53 -0
- package/dist/llm/client.js +122 -0
- package/dist/llm/factory.d.ts +14 -0
- package/dist/llm/factory.js +32 -0
- package/dist/orchestrator/defect-logger.d.ts +31 -0
- package/dist/orchestrator/defect-logger.js +101 -0
- package/dist/orchestrator/defect-manager.d.ts +118 -0
- package/dist/orchestrator/defect-manager.js +338 -0
- package/dist/orchestrator/defect-migration.d.ts +14 -0
- package/dist/orchestrator/defect-migration.js +174 -0
- package/dist/orchestrator/defect-store.d.ts +48 -0
- package/dist/orchestrator/defect-store.js +76 -0
- package/dist/orchestrator/healing.d.ts +14 -0
- package/dist/orchestrator/healing.js +11 -0
- package/dist/orchestrator/interactive-steering.d.ts +64 -0
- package/dist/orchestrator/interactive-steering.js +107 -0
- package/dist/orchestrator/interrupt-handler.d.ts +30 -0
- package/dist/orchestrator/interrupt-handler.js +70 -0
- package/dist/orchestrator/lesson-manager.d.ts +25 -0
- package/dist/orchestrator/lesson-manager.js +122 -0
- package/dist/orchestrator/progress-summary.d.ts +15 -0
- package/dist/orchestrator/progress-summary.js +106 -0
- package/dist/orchestrator/reasoning-score.d.ts +49 -0
- package/dist/orchestrator/reasoning-score.js +117 -0
- package/dist/orchestrator/swarm.d.ts +36 -0
- package/dist/orchestrator/swarm.js +77 -0
- package/dist/orchestrator/task-factory.d.ts +15 -0
- package/dist/orchestrator/task-factory.js +176 -0
- package/dist/orchestrator/validation-gate.d.ts +23 -0
- package/dist/orchestrator/validation-gate.js +155 -0
- package/dist/protocol/react-contract.d.ts +136 -0
- package/dist/protocol/react-contract.js +698 -0
- package/dist/protocol/wks-protocol-manager.d.ts +22 -0
- package/dist/protocol/wks-protocol-manager.js +72 -0
- package/dist/sdlc-runtime/conversation-runner.d.ts +8 -0
- package/dist/sdlc-runtime/conversation-runner.js +64 -0
- package/dist/sdlc-runtime/dag-utils.d.ts +15 -0
- package/dist/sdlc-runtime/dag-utils.js +67 -0
- package/dist/sdlc-runtime/defect-integration.d.ts +7 -0
- package/dist/sdlc-runtime/defect-integration.js +99 -0
- package/dist/sdlc-runtime/execution-loop.d.ts +38 -0
- package/dist/sdlc-runtime/execution-loop.js +274 -0
- package/dist/sdlc-runtime/lesson-recorder.d.ts +9 -0
- package/dist/sdlc-runtime/lesson-recorder.js +27 -0
- package/dist/sdlc-runtime/plan-initializer.d.ts +47 -0
- package/dist/sdlc-runtime/plan-initializer.js +135 -0
- package/dist/sdlc-runtime/progress-persister.d.ts +10 -0
- package/dist/sdlc-runtime/progress-persister.js +34 -0
- package/dist/sdlc-runtime/protocol-loader.d.ts +10 -0
- package/dist/sdlc-runtime/protocol-loader.js +21 -0
- package/dist/sdlc-runtime/reporting.d.ts +24 -0
- package/dist/sdlc-runtime/reporting.js +68 -0
- package/dist/sdlc-runtime/sdlc-orchestrator.d.ts +59 -0
- package/dist/sdlc-runtime/sdlc-orchestrator.js +170 -0
- package/dist/sdlc-runtime/sdlc-skill.d.ts +44 -0
- package/dist/sdlc-runtime/sdlc-skill.js +148 -0
- package/dist/sdlc-runtime/steering-handler.d.ts +14 -0
- package/dist/sdlc-runtime/steering-handler.js +51 -0
- package/dist/sdlc-runtime/trace-recorder.d.ts +10 -0
- package/dist/sdlc-runtime/trace-recorder.js +7 -0
- package/dist/security/index.d.ts +16 -0
- package/dist/security/index.js +12 -0
- package/dist/security/input-screen.d.ts +30 -0
- package/dist/security/input-screen.js +75 -0
- package/dist/security/tool-call-guard.d.ts +16 -0
- package/dist/security/tool-call-guard.js +163 -0
- package/dist/security/untrusted-content.d.ts +34 -0
- package/dist/security/untrusted-content.js +63 -0
- package/dist/skills/advanced-dfir/SKILL.md +85 -0
- package/dist/skills/advanced-pentest-lab/SKILL.md +88 -0
- package/dist/skills/analyst/SKILL.md +55 -0
- package/dist/skills/architect/SKILL.md +54 -0
- package/dist/skills/aws/SKILL.md +92 -0
- package/dist/skills/azure/SKILL.md +90 -0
- package/dist/skills/bylaw-context.d.ts +45 -0
- package/dist/skills/bylaw-context.js +61 -0
- package/dist/skills/bylaw-review.d.ts +20 -0
- package/dist/skills/bylaw-review.js +101 -0
- package/dist/skills/conversation/SKILL.md +29 -0
- package/dist/skills/design-patterns/SKILL.md +190 -0
- package/dist/skills/devops/SKILL.md +55 -0
- package/dist/skills/directives.d.ts +20 -0
- package/dist/skills/directives.js +313 -0
- package/dist/skills/docker/SKILL.md +76 -0
- package/dist/skills/docker-expert/SKILL.md +56 -0
- package/dist/skills/enterprise-systems-analyst/SKILL.md +83 -0
- package/dist/skills/enterprise-systems-analyst/references/crm.md +41 -0
- package/dist/skills/enterprise-systems-analyst/references/erp.md +40 -0
- package/dist/skills/enterprise-systems-analyst/references/financial-systems.md +35 -0
- package/dist/skills/enterprise-systems-analyst/references/hcm.md +38 -0
- package/dist/skills/enterprise-systems-analyst/references/mrp.md +37 -0
- package/dist/skills/enterprise-systems-analyst/references/scm.md +32 -0
- package/dist/skills/ethical-hacking-methodology/SKILL.md +119 -0
- package/dist/skills/externalSkillLoader.d.ts +25 -0
- package/dist/skills/externalSkillLoader.js +65 -0
- package/dist/skills/externalSkillRegistry.d.ts +33 -0
- package/dist/skills/externalSkillRegistry.js +94 -0
- package/dist/skills/filesystem-management/SKILL.md +61 -0
- package/dist/skills/first-run-seed.d.ts +26 -0
- package/dist/skills/first-run-seed.js +75 -0
- package/dist/skills/git-vcs/SKILL.md +84 -0
- package/dist/skills/kafka/SKILL.md +89 -0
- package/dist/skills/kubernetes/SKILL.md +93 -0
- package/dist/skills/kubernetes-expert/SKILL.md +54 -0
- package/dist/skills/openshift/SKILL.md +93 -0
- package/dist/skills/pentester/SKILL.md +59 -0
- package/dist/skills/performance-tester/SKILL.md +57 -0
- package/dist/skills/playwright-ui-tester/SKILL.md +67 -0
- package/dist/skills/programmer/SKILL.md +58 -0
- package/dist/skills/project-scaffolding/SKILL.md +133 -0
- package/dist/skills/qa-engineer/SKILL.md +91 -0
- package/dist/skills/rca/SKILL.md +58 -0
- package/dist/skills/redhat/SKILL.md +92 -0
- package/dist/skills/rosa/SKILL.md +80 -0
- package/dist/skills/scrum-framework/SKILL.md +74 -0
- package/dist/skills/scrum-framework/references/artifacts_and_quality.md +79 -0
- package/dist/skills/scrum-framework/references/roles_and_events.md +105 -0
- package/dist/skills/scrum-master-agent/SKILL.md +74 -0
- package/dist/skills/scrum-master-agent/references/behaviors.md +56 -0
- package/dist/skills/sdlc-skill.d.ts +1 -0
- package/dist/skills/sdlc-skill.js +4 -0
- package/dist/skills/secops/SKILL.md +52 -0
- package/dist/skills/secure-architect.bylaws.d.ts +68 -0
- package/dist/skills/secure-architect.bylaws.js +525 -0
- package/dist/skills/seed-skills.d.ts +48 -0
- package/dist/skills/seed-skills.js +213 -0
- package/dist/skills/skill-authoring/SKILL.md +123 -0
- package/dist/skills/skill-header.d.ts +51 -0
- package/dist/skills/skill-header.js +163 -0
- package/dist/skills/skill-path-guard.d.ts +41 -0
- package/dist/skills/skill-path-guard.js +95 -0
- package/dist/skills/skillRouter.d.ts +51 -0
- package/dist/skills/skillRouter.js +90 -0
- package/dist/skills/skills-root.d.ts +64 -0
- package/dist/skills/skills-root.js +168 -0
- package/dist/skills/software-architect/SKILL.md +77 -0
- package/dist/skills/software-engineer/SKILL.md +74 -0
- package/dist/skills/solid-principles/SKILL.md +94 -0
- package/dist/skills/task-planning/SKILL.md +115 -0
- package/dist/skills/tester/SKILL.md +54 -0
- package/dist/skills/ubuntu/SKILL.md +87 -0
- package/dist/skills/ui-ux-design/SKILL.md +114 -0
- package/dist/skills/workspace-context/SKILL.md +103 -0
- package/dist/sprint/controller.d.ts +37 -0
- package/dist/sprint/controller.js +220 -0
- package/dist/sprint/dag-builder.d.ts +14 -0
- package/dist/sprint/dag-builder.js +105 -0
- package/dist/sprint/reporter.d.ts +11 -0
- package/dist/sprint/reporter.js +97 -0
- package/dist/sprint/state-store.d.ts +10 -0
- package/dist/sprint/state-store.js +71 -0
- package/dist/sprint/types.d.ts +24 -0
- package/dist/sprint/types.js +4 -0
- package/dist/store/file-version-store.d.ts +24 -0
- package/dist/store/file-version-store.js +73 -0
- package/dist/store/task-store.d.ts +90 -0
- package/dist/store/task-store.js +166 -0
- package/dist/task-ingest/architect-detailer.d.ts +43 -0
- package/dist/task-ingest/architect-detailer.js +141 -0
- package/dist/task-ingest/detail-schema.d.ts +9 -0
- package/dist/task-ingest/detail-schema.js +195 -0
- package/dist/task-ingest/detailed-run.d.ts +36 -0
- package/dist/task-ingest/detailed-run.js +108 -0
- package/dist/task-ingest/extract-id.d.ts +9 -0
- package/dist/task-ingest/extract-id.js +24 -0
- package/dist/task-ingest/index.d.ts +23 -0
- package/dist/task-ingest/index.js +14 -0
- package/dist/task-ingest/ingest.d.ts +45 -0
- package/dist/task-ingest/ingest.js +163 -0
- package/dist/task-ingest/list-ingested.d.ts +13 -0
- package/dist/task-ingest/list-ingested.js +30 -0
- package/dist/task-ingest/pending-filter.d.ts +30 -0
- package/dist/task-ingest/pending-filter.js +59 -0
- package/dist/task-ingest/scanner.d.ts +56 -0
- package/dist/task-ingest/scanner.js +216 -0
- package/dist/task-ingest/source-reader.d.ts +25 -0
- package/dist/task-ingest/source-reader.js +93 -0
- package/dist/task-ingest/spec-builder.d.ts +34 -0
- package/dist/task-ingest/spec-builder.js +89 -0
- package/dist/task-ingest/wbs-extract.d.ts +50 -0
- package/dist/task-ingest/wbs-extract.js +226 -0
- package/dist/task-ingest/wbs-parser.d.ts +36 -0
- package/dist/task-ingest/wbs-parser.js +170 -0
- package/dist/tools/apiTestTool.d.ts +37 -0
- package/dist/tools/apiTestTool.js +128 -0
- package/dist/tools/ast-tools.d.ts +183 -0
- package/dist/tools/ast-tools.js +853 -0
- package/dist/tools/browse-tool.d.ts +105 -0
- package/dist/tools/browse-tool.js +394 -0
- package/dist/tools/credential.d.ts +17 -0
- package/dist/tools/credential.js +32 -0
- package/dist/tools/dependency-graph.d.ts +23 -0
- package/dist/tools/dependency-graph.js +164 -0
- package/dist/tools/edit-tool.d.ts +34 -0
- package/dist/tools/edit-tool.js +95 -0
- package/dist/tools/file-header-manager.d.ts +27 -0
- package/dist/tools/file-header-manager.js +153 -0
- package/dist/tools/fs-tools.d.ts +154 -0
- package/dist/tools/fs-tools.js +337 -0
- package/dist/tools/git-tools.d.ts +79 -0
- package/dist/tools/git-tools.js +348 -0
- package/dist/tools/github-tool.d.ts +48 -0
- package/dist/tools/github-tool.js +147 -0
- package/dist/tools/globTool.d.ts +20 -0
- package/dist/tools/globTool.js +34 -0
- package/dist/tools/grepTool.d.ts +19 -0
- package/dist/tools/grepTool.js +44 -0
- package/dist/tools/index-freshness.d.ts +58 -0
- package/dist/tools/index-freshness.js +190 -0
- package/dist/tools/index-glob.d.ts +48 -0
- package/dist/tools/index-glob.js +175 -0
- package/dist/tools/load-skill-tool.d.ts +15 -0
- package/dist/tools/load-skill-tool.js +114 -0
- package/dist/tools/patch-tools.d.ts +58 -0
- package/dist/tools/patch-tools.js +153 -0
- package/dist/tools/playwright-tool.d.ts +66 -0
- package/dist/tools/playwright-tool.js +121 -0
- package/dist/tools/project-detect.d.ts +20 -0
- package/dist/tools/project-detect.js +87 -0
- package/dist/tools/prompt-guidance.d.ts +22 -0
- package/dist/tools/prompt-guidance.js +23 -0
- package/dist/tools/scheduleTool.d.ts +19 -0
- package/dist/tools/scheduleTool.js +181 -0
- package/dist/tools/search-tools.d.ts +27 -0
- package/dist/tools/search-tools.js +78 -0
- package/dist/tools/sed-tool.d.ts +66 -0
- package/dist/tools/sed-tool.js +402 -0
- package/dist/tools/shell-result.d.ts +11 -0
- package/dist/tools/shell-result.js +1 -0
- package/dist/tools/shell-tool.d.ts +45 -0
- package/dist/tools/shell-tool.js +141 -0
- package/dist/tools/siteCrawlerTool.d.ts +32 -0
- package/dist/tools/siteCrawlerTool.js +205 -0
- package/dist/tools/tool-registry.d.ts +67 -0
- package/dist/tools/tool-registry.js +596 -0
- package/dist/tools/validate-tool.d.ts +23 -0
- package/dist/tools/validate-tool.js +201 -0
- package/dist/tools/workspace-index.d.ts +46 -0
- package/dist/tools/workspace-index.js +173 -0
- package/dist/types.d.ts +222 -0
- package/dist/types.js +7 -0
- package/dist/updater/index.d.ts +14 -0
- package/dist/updater/index.js +120 -0
- package/dist/util/banner.d.ts +25 -0
- package/dist/util/banner.js +140 -0
- package/dist/util/command-suggester.d.ts +6 -0
- package/dist/util/command-suggester.js +25 -0
- package/dist/util/confirm-interrupt.d.ts +10 -0
- package/dist/util/confirm-interrupt.js +31 -0
- package/dist/util/continue-trigger.d.ts +11 -0
- package/dist/util/continue-trigger.js +20 -0
- package/dist/util/env-info.d.ts +18 -0
- package/dist/util/env-info.js +37 -0
- package/dist/util/file-access-log.d.ts +35 -0
- package/dist/util/file-access-log.js +140 -0
- package/dist/util/footer-manager.d.ts +124 -0
- package/dist/util/footer-manager.js +195 -0
- package/dist/util/footer-renderer.d.ts +67 -0
- package/dist/util/footer-renderer.js +319 -0
- package/dist/util/footer-state.d.ts +34 -0
- package/dist/util/footer-state.js +18 -0
- package/dist/util/footer-text.d.ts +51 -0
- package/dist/util/footer-text.js +74 -0
- package/dist/util/ids.d.ts +1 -0
- package/dist/util/ids.js +4 -0
- package/dist/util/levenshtein.d.ts +6 -0
- package/dist/util/levenshtein.js +34 -0
- package/dist/util/logger.d.ts +10 -0
- package/dist/util/logger.js +41 -0
- package/dist/util/logs.d.ts +26 -0
- package/dist/util/logs.js +88 -0
- package/dist/util/output-handler.d.ts +89 -0
- package/dist/util/output-handler.js +193 -0
- package/dist/util/output-interceptor.d.ts +18 -0
- package/dist/util/output-interceptor.js +49 -0
- package/dist/util/output-paths.d.ts +43 -0
- package/dist/util/output-paths.js +121 -0
- package/dist/util/package-json.d.ts +6 -0
- package/dist/util/package-json.js +36 -0
- package/dist/util/process-kill.d.ts +27 -0
- package/dist/util/process-kill.js +148 -0
- package/dist/util/protocol-error-logger.d.ts +33 -0
- package/dist/util/protocol-error-logger.js +73 -0
- package/dist/util/redact.d.ts +25 -0
- package/dist/util/redact.js +103 -0
- package/dist/util/scroll-region-guard.d.ts +33 -0
- package/dist/util/scroll-region-guard.js +63 -0
- package/dist/util/spinner.d.ts +15 -0
- package/dist/util/spinner.js +49 -0
- package/dist/util/terminal-output.d.ts +34 -0
- package/dist/util/terminal-output.js +1 -0
- package/dist/util/terminal-silent.d.ts +6 -0
- package/dist/util/terminal-silent.js +20 -0
- package/dist/util/terminal.d.ts +56 -0
- package/dist/util/terminal.js +124 -0
- package/dist/util/text-sanitize.d.ts +8 -0
- package/dist/util/text-sanitize.js +45 -0
- package/dist/util/thinking-spinner.d.ts +27 -0
- package/dist/util/thinking-spinner.js +189 -0
- package/dist/util/tool-error-logger.d.ts +33 -0
- package/dist/util/tool-error-logger.js +77 -0
- package/dist/util/tty.d.ts +13 -0
- package/dist/util/tty.js +16 -0
- package/dist/util/xcoder-paths.d.ts +56 -0
- package/dist/util/xcoder-paths.js +63 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +4 -0
- package/dist/worker-agent/to-subtask-node.d.ts +35 -0
- package/dist/worker-agent/to-subtask-node.js +41 -0
- package/dist/worker-agent/worker-orchestrator.d.ts +104 -0
- package/dist/worker-agent/worker-orchestrator.js +201 -0
- package/package.json +38 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// xcoder:version 1 | xcoder:task task-e6370a | xcoder:updated 2026-08-12T16:18:11.500Z | xcoder:subtask code-st-cd4444
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import { upsertEntry } from "./workspace-index.js";
|
|
6
|
+
import { getCommentSyntax, injectVersionHeader, } from "./file-header-manager.js";
|
|
7
|
+
import { incrementFileVersion } from "../store/file-version-store.js";
|
|
8
|
+
export class WorkspaceEscapeError extends Error {
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Every path a tool touches is resolved and pinned inside the workspace root.
|
|
12
|
+
* No `..` escapes — the same 8-line guard every other path-taking tool uses.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveInWorkspace(root, relPath) {
|
|
15
|
+
const full = path.resolve(root, relPath);
|
|
16
|
+
const normalizedRoot = path.resolve(root) + path.sep;
|
|
17
|
+
if (full + path.sep !== normalizedRoot && !full.startsWith(normalizedRoot)) {
|
|
18
|
+
throw new WorkspaceEscapeError(`path "${relPath}" resolves outside the workspace root — refusing.`);
|
|
19
|
+
}
|
|
20
|
+
return full;
|
|
21
|
+
}
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Staleness helpers (AC-11 / AC-19)
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Full-file sha1, byte-for-byte identical to the one `workspace-index.ts`
|
|
27
|
+
* stores per entry — so a sha1 taken here is directly comparable with the
|
|
28
|
+
* index's value and with the `readSha1` returned by range reads.
|
|
29
|
+
*/
|
|
30
|
+
export async function hashFile(fullPath) {
|
|
31
|
+
const buf = await fs.readFile(fullPath);
|
|
32
|
+
return crypto.createHash("sha1").update(buf).digest("hex");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The reusable staleness core behind every stale-enforced write tool.
|
|
36
|
+
* Compares the file's CURRENT sha1 against the sha1 the caller observed
|
|
37
|
+
* earlier (via read_file's `readSha1`). A mismatch means the file changed
|
|
38
|
+
* under the caller — the write MUST NOT proceed.
|
|
39
|
+
*/
|
|
40
|
+
export async function assertFileUnchanged(fullPath, expectedSha1) {
|
|
41
|
+
const actualSha1 = await hashFile(fullPath);
|
|
42
|
+
if (actualSha1 !== expectedSha1)
|
|
43
|
+
return { ok: false, actualSha1 };
|
|
44
|
+
return { ok: true };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Replace lines [startLine..endLine] (1-indexed, inclusive) with newContent.
|
|
48
|
+
*
|
|
49
|
+
* Staleness contract: `expectedSha1` is REQUIRED. It must come from the
|
|
50
|
+
* `readSha1` field of a prior read_file range call. The file is hashed
|
|
51
|
+
* immediately before any mutation; a mismatch returns `stale` and performs
|
|
52
|
+
* ZERO writes — never a blind line splice onto a file that changed under
|
|
53
|
+
* the agent.
|
|
54
|
+
*/
|
|
55
|
+
export async function linePatchTool(root, input, ctx) {
|
|
56
|
+
if (typeof input.expectedSha1 !== "string" || input.expectedSha1 === "") {
|
|
57
|
+
return {
|
|
58
|
+
ok: false,
|
|
59
|
+
code: "stale_field_missing",
|
|
60
|
+
error: `line_patch requires "expectedSha1" — the file may have changed since you last read it. ` +
|
|
61
|
+
`Re-read the file with read_file (a range read includes "readSha1") and pass that sha1 here.`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
let full;
|
|
65
|
+
try {
|
|
66
|
+
full = resolveInWorkspace(root, input.path);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
return { ok: false, error: e.message, code: "workspace_escape" };
|
|
70
|
+
}
|
|
71
|
+
let content;
|
|
72
|
+
try {
|
|
73
|
+
content = await fs.readFile(full, "utf8");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {
|
|
77
|
+
ok: false,
|
|
78
|
+
code: "file_not_found",
|
|
79
|
+
error: `"${input.path}" doesn't exist or can't be read. Use write_file to create a new file instead of line_patch.`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Range validation BEFORE any mutation.
|
|
83
|
+
const lines = content.split("\n");
|
|
84
|
+
const start = Number(input.startLine);
|
|
85
|
+
const end = Number(input.endLine);
|
|
86
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || start < 1 || end < start) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
code: "invalid_range",
|
|
90
|
+
error: `invalid line range [${String(input.startLine)}..${String(input.endLine)}] — startLine must be >= 1 and endLine must be >= startLine.`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (end > lines.length) {
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
code: "invalid_range",
|
|
97
|
+
error: `endLine ${end} exceeds the file's ${lines.length} lines. Re-read the file to confirm its current size.`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Staleness check: hash immediately before any write.
|
|
101
|
+
let checked;
|
|
102
|
+
try {
|
|
103
|
+
checked = await assertFileUnchanged(full, input.expectedSha1);
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
return { ok: false, error: e.message, code: "io_error" };
|
|
107
|
+
}
|
|
108
|
+
if (!checked.ok) {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
code: "stale",
|
|
112
|
+
error: `the file changed since you read it (expected sha1 ${input.expectedSha1.slice(0, 12)}, ` +
|
|
113
|
+
`actual ${checked.actualSha1.slice(0, 12)}). Re-read the file and retry with the fresh readSha1 — no changes were written.`,
|
|
114
|
+
actualSha1: checked.actualSha1,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// Line splice: replace [start..end] (1-indexed, inclusive) with newContent.
|
|
118
|
+
const before = lines.slice(0, start - 1);
|
|
119
|
+
const after = lines.slice(end);
|
|
120
|
+
const replacement = input.newContent.split("\n");
|
|
121
|
+
const nextLines = [...before, ...replacement, ...after];
|
|
122
|
+
let next = nextLines.join("\n");
|
|
123
|
+
// Header injection (when context is available and file type supports it).
|
|
124
|
+
if (ctx) {
|
|
125
|
+
const syntax = getCommentSyntax(input.path);
|
|
126
|
+
if (syntax) {
|
|
127
|
+
try {
|
|
128
|
+
const meta = await incrementFileVersion(root, input.path, ctx.taskId, ctx.subtaskId);
|
|
129
|
+
const injected = injectVersionHeader(next, syntax, meta);
|
|
130
|
+
next = injected.content;
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
return { ok: false, error: e.message, code: "io_error" };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
await fs.writeFile(full, next, "utf8");
|
|
139
|
+
await upsertEntry(root, path.relative(root, full));
|
|
140
|
+
const sha1After = await hashFile(full);
|
|
141
|
+
return {
|
|
142
|
+
ok: true,
|
|
143
|
+
relPath: path.relative(root, full).split(path.sep).join("/"),
|
|
144
|
+
replacedLines: [start, end],
|
|
145
|
+
newContentChars: input.newContent.length,
|
|
146
|
+
linesAfter: next.split("\n").length,
|
|
147
|
+
sha1After,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
return { ok: false, error: e.message, code: "io_error" };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative test steps only — the model describes *what* to do, this
|
|
3
|
+
* module is the only thing that ever touches a browser or an HTTP client.
|
|
4
|
+
* That split is what keeps a resolved credential out of the model's
|
|
5
|
+
* context: the model hands us a `credentialRef` (an env var name); we
|
|
6
|
+
* resolve it here, use it, and never put the resolved value in the
|
|
7
|
+
* returned result.
|
|
8
|
+
*/
|
|
9
|
+
export type UiStep = {
|
|
10
|
+
op: "goto";
|
|
11
|
+
url: string;
|
|
12
|
+
} | {
|
|
13
|
+
op: "fill";
|
|
14
|
+
selector: string;
|
|
15
|
+
value: string;
|
|
16
|
+
} | {
|
|
17
|
+
op: "click";
|
|
18
|
+
selector: string;
|
|
19
|
+
} | {
|
|
20
|
+
op: "expect_text";
|
|
21
|
+
selector: string;
|
|
22
|
+
text: string;
|
|
23
|
+
} | {
|
|
24
|
+
op: "expect_url";
|
|
25
|
+
contains: string;
|
|
26
|
+
} | {
|
|
27
|
+
op: "login_with_credential";
|
|
28
|
+
usernameSelector: string;
|
|
29
|
+
passwordSelector: string;
|
|
30
|
+
submitSelector: string;
|
|
31
|
+
usernameValue: string;
|
|
32
|
+
};
|
|
33
|
+
export interface UiTestInput {
|
|
34
|
+
kind: "ui";
|
|
35
|
+
url: string;
|
|
36
|
+
credentialRef?: string;
|
|
37
|
+
steps: UiStep[];
|
|
38
|
+
}
|
|
39
|
+
export interface ApiTestInput {
|
|
40
|
+
kind: "api";
|
|
41
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
42
|
+
url: string;
|
|
43
|
+
credentialRef?: string;
|
|
44
|
+
headers?: Record<string, string>;
|
|
45
|
+
body?: unknown;
|
|
46
|
+
expectStatus?: number;
|
|
47
|
+
expectBodyContains?: string;
|
|
48
|
+
}
|
|
49
|
+
export type PlaywrightToolInput = UiTestInput | ApiTestInput;
|
|
50
|
+
export interface PlaywrightToolResult {
|
|
51
|
+
ok: boolean;
|
|
52
|
+
detail: string;
|
|
53
|
+
steps: {
|
|
54
|
+
op: string;
|
|
55
|
+
ok: boolean;
|
|
56
|
+
note: string;
|
|
57
|
+
}[];
|
|
58
|
+
}
|
|
59
|
+
export declare function runApiTest(input: ApiTestInput): Promise<PlaywrightToolResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Requires the optional `playwright` dependency (`npm install`, then
|
|
62
|
+
* `npx playwright install chromium` once). Imported dynamically so the
|
|
63
|
+
* rest of Xcoder SDLC works without it if a task never needs a UI test.
|
|
64
|
+
*/
|
|
65
|
+
export declare function runUiTest(input: UiTestInput): Promise<PlaywrightToolResult>;
|
|
66
|
+
export declare function runPlaywrightTool(input: PlaywrightToolInput): Promise<PlaywrightToolResult>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { resolveCredential, redact } from "./credential.js";
|
|
2
|
+
export async function runApiTest(input) {
|
|
3
|
+
const headers = { ...(input.headers ?? {}) };
|
|
4
|
+
if (input.credentialRef) {
|
|
5
|
+
headers["Authorization"] = `Bearer ${resolveCredential(input.credentialRef)}`;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetch(input.url, {
|
|
9
|
+
method: input.method,
|
|
10
|
+
headers,
|
|
11
|
+
body: input.body !== undefined ? JSON.stringify(input.body) : undefined,
|
|
12
|
+
});
|
|
13
|
+
const text = await res.text();
|
|
14
|
+
const statusOk = input.expectStatus === undefined || res.status === input.expectStatus;
|
|
15
|
+
const bodyOk = !input.expectBodyContains || text.includes(input.expectBodyContains);
|
|
16
|
+
const ok = statusOk && bodyOk;
|
|
17
|
+
const detail = redact(`${input.method} ${input.url} → ${res.status}` +
|
|
18
|
+
(input.expectStatus !== undefined ? ` (expected ${input.expectStatus})` : "") +
|
|
19
|
+
(input.expectBodyContains ? `, body ${bodyOk ? "contains" : "MISSING"} expected substring` : ""), input.credentialRef);
|
|
20
|
+
return {
|
|
21
|
+
ok,
|
|
22
|
+
detail,
|
|
23
|
+
steps: [{ op: "http_request", ok, note: detail }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
detail: redact(`request failed: ${e.message}`, input.credentialRef),
|
|
30
|
+
steps: [{ op: "http_request", ok: false, note: e.message }],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Requires the optional `playwright` dependency (`npm install`, then
|
|
36
|
+
* `npx playwright install chromium` once). Imported dynamically so the
|
|
37
|
+
* rest of Xcoder SDLC works without it if a task never needs a UI test.
|
|
38
|
+
*/
|
|
39
|
+
export async function runUiTest(input) {
|
|
40
|
+
let chromium;
|
|
41
|
+
try {
|
|
42
|
+
({ chromium } = await import("playwright"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
detail: "the `playwright` package isn't installed. Run `npm install` (it's an " +
|
|
48
|
+
"optionalDependency) then `npx playwright install chromium`.",
|
|
49
|
+
steps: [],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const browser = await chromium.launch({ headless: true });
|
|
53
|
+
const page = await browser.newPage();
|
|
54
|
+
const stepResults = [];
|
|
55
|
+
let overallOk = true;
|
|
56
|
+
try {
|
|
57
|
+
await page.goto(input.url, { waitUntil: "domcontentloaded" });
|
|
58
|
+
stepResults.push({ op: "goto", ok: true, note: input.url });
|
|
59
|
+
for (const step of input.steps) {
|
|
60
|
+
try {
|
|
61
|
+
switch (step.op) {
|
|
62
|
+
case "goto":
|
|
63
|
+
await page.goto(step.url, { waitUntil: "domcontentloaded" });
|
|
64
|
+
stepResults.push({ op: "goto", ok: true, note: step.url });
|
|
65
|
+
break;
|
|
66
|
+
case "fill":
|
|
67
|
+
await page.fill(step.selector, step.value);
|
|
68
|
+
stepResults.push({ op: "fill", ok: true, note: step.selector });
|
|
69
|
+
break;
|
|
70
|
+
case "click":
|
|
71
|
+
await page.click(step.selector);
|
|
72
|
+
stepResults.push({ op: "click", ok: true, note: step.selector });
|
|
73
|
+
break;
|
|
74
|
+
case "expect_text": {
|
|
75
|
+
const content = await page.textContent(step.selector);
|
|
76
|
+
const ok = !!content && content.includes(step.text);
|
|
77
|
+
stepResults.push({
|
|
78
|
+
op: "expect_text",
|
|
79
|
+
ok,
|
|
80
|
+
note: ok ? "matched" : `expected "${step.text}", got "${content}"`,
|
|
81
|
+
});
|
|
82
|
+
if (!ok)
|
|
83
|
+
overallOk = false;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case "expect_url": {
|
|
87
|
+
const ok = page.url().includes(step.contains);
|
|
88
|
+
stepResults.push({ op: "expect_url", ok, note: ok ? "matched" : `got ${page.url()}` });
|
|
89
|
+
if (!ok)
|
|
90
|
+
overallOk = false;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case "login_with_credential": {
|
|
94
|
+
const password = resolveCredential(input.credentialRef ?? "");
|
|
95
|
+
await page.fill(step.usernameSelector, step.usernameValue);
|
|
96
|
+
await page.fill(step.passwordSelector, password);
|
|
97
|
+
await page.click(step.submitSelector);
|
|
98
|
+
stepResults.push({ op: "login_with_credential", ok: true, note: "submitted (value redacted)" });
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
overallOk = false;
|
|
105
|
+
stepResults.push({ op: step.op, ok: false, note: redact(e.message, input.credentialRef) });
|
|
106
|
+
break; // stop on first hard failure — no point clicking further into a broken page
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
await browser.close();
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
ok: overallOk,
|
|
115
|
+
detail: overallOk ? "all steps passed" : "one or more steps failed — see `steps`",
|
|
116
|
+
steps: stepResults,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export async function runPlaywrightTool(input) {
|
|
120
|
+
return input.kind === "api" ? runApiTest(input) : runUiTest(input);
|
|
121
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { WorkspaceIndex } from "./workspace-index.js";
|
|
2
|
+
export interface DetectedCommands {
|
|
3
|
+
stack: string;
|
|
4
|
+
build?: string;
|
|
5
|
+
test?: string;
|
|
6
|
+
lint?: string;
|
|
7
|
+
typecheck?: string;
|
|
8
|
+
reproduceHint: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A guessed set of commands, not a guaranteed one — surfaced to the model
|
|
12
|
+
* as a strong hint so it calls `run_command` with something that actually
|
|
13
|
+
* exists in this project instead of assuming `npm test` everywhere (or
|
|
14
|
+
* `pytest` in a Node project, etc.). This is what "inform the LLM ... run
|
|
15
|
+
* tests / linter / type-checker / reproduce the bug" means in practice:
|
|
16
|
+
* give it the real command names up front rather than making it discover
|
|
17
|
+
* them by trial and error.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectProjectCommands(root: string, index: WorkspaceIndex): Promise<DetectedCommands>;
|
|
20
|
+
export declare function detectedCommandsPromptBlock(cmds: DetectedCommands): string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* A guessed set of commands, not a guaranteed one — surfaced to the model
|
|
5
|
+
* as a strong hint so it calls `run_command` with something that actually
|
|
6
|
+
* exists in this project instead of assuming `npm test` everywhere (or
|
|
7
|
+
* `pytest` in a Node project, etc.). This is what "inform the LLM ... run
|
|
8
|
+
* tests / linter / type-checker / reproduce the bug" means in practice:
|
|
9
|
+
* give it the real command names up front rather than making it discover
|
|
10
|
+
* them by trial and error.
|
|
11
|
+
*/
|
|
12
|
+
export async function detectProjectCommands(root, index) {
|
|
13
|
+
const has = (p) => index.entries.some((e) => e.relPath === p);
|
|
14
|
+
if (has("package.json")) {
|
|
15
|
+
try {
|
|
16
|
+
const raw = await fs.readFile(path.join(root, "package.json"), "utf8");
|
|
17
|
+
const pkg = JSON.parse(raw);
|
|
18
|
+
const scripts = pkg.scripts ?? {};
|
|
19
|
+
return {
|
|
20
|
+
stack: "node",
|
|
21
|
+
build: scripts.build ? "npm run build" : undefined,
|
|
22
|
+
test: scripts.test ? "npm test" : undefined,
|
|
23
|
+
lint: scripts.lint ? "npm run lint" : undefined,
|
|
24
|
+
typecheck: scripts.typecheck ?? scripts["type-check"] ? "npm run typecheck" : (has("tsconfig.json") ? "npx tsc --noEmit" : undefined),
|
|
25
|
+
reproduceHint: "Reproduce a reported bug with the narrowest test file/command you can, before writing a fix.",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return { stack: "node", reproduceHint: "package.json exists but couldn't be parsed — read it directly first." };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (has("pyproject.toml") || has("requirements.txt") || has("setup.py")) {
|
|
33
|
+
return {
|
|
34
|
+
stack: "python",
|
|
35
|
+
test: "pytest",
|
|
36
|
+
lint: "ruff check .",
|
|
37
|
+
typecheck: "mypy .",
|
|
38
|
+
reproduceHint: "Reproduce with a minimal pytest case before patching.",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (has("go.mod")) {
|
|
42
|
+
return {
|
|
43
|
+
stack: "go",
|
|
44
|
+
build: "go build ./...",
|
|
45
|
+
test: "go test ./...",
|
|
46
|
+
lint: "go vet ./...",
|
|
47
|
+
reproduceHint: "Reproduce with a targeted `go test -run <TestName>` before patching.",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (index.entries.some((e) => e.relPath.endsWith("pom.xml"))) {
|
|
51
|
+
return {
|
|
52
|
+
stack: "java-maven",
|
|
53
|
+
build: "mvn compile",
|
|
54
|
+
test: "mvn test",
|
|
55
|
+
reproduceHint: "Reproduce with a targeted `mvn test -Dtest=<TestClass>` before patching.",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (index.entries.some((e) => e.relPath.endsWith("build.gradle") || e.relPath.endsWith("build.gradle.kts"))) {
|
|
59
|
+
return {
|
|
60
|
+
stack: "java-gradle",
|
|
61
|
+
build: "./gradlew build",
|
|
62
|
+
test: "./gradlew test",
|
|
63
|
+
reproduceHint: "Reproduce with a targeted `./gradlew test --tests <TestClass>` before patching.",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
stack: "unknown",
|
|
68
|
+
reproduceHint: "No recognized project manifest found in the workspace index. Use `search_workspace`/`glob` to look for a " +
|
|
69
|
+
"manifest before guessing a build/test command.",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function detectedCommandsPromptBlock(cmds) {
|
|
73
|
+
const lines = [`## Detected project tooling (stack: ${cmds.stack})`];
|
|
74
|
+
if (cmds.build)
|
|
75
|
+
lines.push(`- build: \`${cmds.build}\``);
|
|
76
|
+
if (cmds.test)
|
|
77
|
+
lines.push(`- test: \`${cmds.test}\``);
|
|
78
|
+
if (cmds.lint)
|
|
79
|
+
lines.push(`- lint: \`${cmds.lint}\``);
|
|
80
|
+
if (cmds.typecheck)
|
|
81
|
+
lines.push(`- typecheck: \`${cmds.typecheck}\``);
|
|
82
|
+
if (!cmds.build && !cmds.test && !cmds.lint && !cmds.typecheck) {
|
|
83
|
+
lines.push("- (none detected — verify with `search_workspace`/`glob` before assuming a command exists)");
|
|
84
|
+
}
|
|
85
|
+
lines.push(cmds.reproduceHint);
|
|
86
|
+
return lines.join("\n");
|
|
87
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared cheapest-first guidance fragments, embedded into the manifest
|
|
3
|
+
* descriptions of the efficient-filesystem toolset so every agent that
|
|
4
|
+
* renders `buildToolManifest` output (Sub/Samurai/Genesis agents, the
|
|
5
|
+
* conversation runner, debate, the Samurai CLI, and therefore the SDLC
|
|
6
|
+
* orchestrator, swarm, healing, and validation-gate paths) automatically
|
|
7
|
+
* sees the efficiency hierarchy next to each tool.
|
|
8
|
+
*
|
|
9
|
+
* The fragments are deliberately plain-language and action-oriented:
|
|
10
|
+
* they tell the model which cheaper alternative exists for a given tool
|
|
11
|
+
* BEFORE it spends tokens on the expensive one.
|
|
12
|
+
*/
|
|
13
|
+
export declare const PROMPT_GUIDANCE: {
|
|
14
|
+
/** Guidance for read-side tools: prefer the cheapest structural read. */
|
|
15
|
+
readFirst: string;
|
|
16
|
+
/** Guidance for write-side tools: prefer surgical edits over full rewrites. */
|
|
17
|
+
editFirst: string;
|
|
18
|
+
/** Guidance after any edit: validate just the patched file. */
|
|
19
|
+
validateAfterEdit: string;
|
|
20
|
+
/** Guidance for source-control reads: prefer summaries over raw output. */
|
|
21
|
+
gitFirst: string;
|
|
22
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// xcoder:version 1 | xcoder:task task-e6370a | xcoder:updated 2026-08-12T16:17:53.138Z | xcoder:subtask code-st-cd4444
|
|
2
|
+
/**
|
|
3
|
+
* Shared cheapest-first guidance fragments, embedded into the manifest
|
|
4
|
+
* descriptions of the efficient-filesystem toolset so every agent that
|
|
5
|
+
* renders `buildToolManifest` output (Sub/Samurai/Genesis agents, the
|
|
6
|
+
* conversation runner, debate, the Samurai CLI, and therefore the SDLC
|
|
7
|
+
* orchestrator, swarm, healing, and validation-gate paths) automatically
|
|
8
|
+
* sees the efficiency hierarchy next to each tool.
|
|
9
|
+
*
|
|
10
|
+
* The fragments are deliberately plain-language and action-oriented:
|
|
11
|
+
* they tell the model which cheaper alternative exists for a given tool
|
|
12
|
+
* BEFORE it spends tokens on the expensive one.
|
|
13
|
+
*/
|
|
14
|
+
export const PROMPT_GUIDANCE = {
|
|
15
|
+
/** Guidance for read-side tools: prefer the cheapest structural read. */
|
|
16
|
+
readFirst: "Cheapest read first: read_outline for a structural skeleton, or read_multiple_files for batched sections — before read_file/read_full_file.",
|
|
17
|
+
/** Guidance for write-side tools: prefer surgical edits over full rewrites. */
|
|
18
|
+
editFirst: "Cheapest edit first: line_patch / edit_file / sed_tool for surgical changes; write_file only for new files or genuine full rewrites (add force: true above 200 lines).",
|
|
19
|
+
/** Guidance after any edit: validate just the patched file. */
|
|
20
|
+
validateAfterEdit: "After any edit, call validate_file to syntax/type-check the patched file before moving on.",
|
|
21
|
+
/** Guidance for source-control reads: prefer summaries over raw output. */
|
|
22
|
+
gitFirst: "Prefer git_diff / git_log (low-token summaries) over raw run_command git invocations — cheaper and workspace-pinned.",
|
|
23
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ScheduledJob {
|
|
2
|
+
id: string;
|
|
3
|
+
cronExpr: string;
|
|
4
|
+
command: string;
|
|
5
|
+
}
|
|
6
|
+
/** Registers a recurring job: cron on POSIX, a translated Windows Task Scheduler task on
|
|
7
|
+
* win32, tagged with an id for later listing/removal. */
|
|
8
|
+
export declare function scheduleCron(id: string, cronExpr: string, command: string): Promise<{
|
|
9
|
+
id: string;
|
|
10
|
+
cronExpr: string;
|
|
11
|
+
}>;
|
|
12
|
+
/** Schedules a one-off command to run after `delaySeconds`, surviving beyond the current process. */
|
|
13
|
+
export declare function scheduleOnce(delaySeconds: number, command: string): Promise<{
|
|
14
|
+
scheduledFor: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function listScheduled(): Promise<ScheduledJob[]>;
|
|
17
|
+
export declare function removeScheduled(id: string): Promise<{
|
|
18
|
+
removed: boolean;
|
|
19
|
+
}>;
|