archondev 2.19.37 → 2.19.39
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/README.md
CHANGED
|
@@ -123,8 +123,8 @@ pnpm exec tsx scripts/init-governance-db.ts
|
|
|
123
123
|
- You can paste multi‑line requests into interactive prompts; Archon captures them as a single response.
|
|
124
124
|
- Proposal approvals like `approve plan` now bind to the pending proposal context in chat mode.
|
|
125
125
|
- Governance boundary/path checks in execute now steer with actionable guidance and set atoms to `BLOCKED` rather than hard failing.
|
|
126
|
-
- Analysis-first requests now return recommendations first and
|
|
127
|
-
- Chat
|
|
126
|
+
- Analysis-first requests now return recommendations first and accept natural confirmations (`yes`, `go ahead`, `create`) to create governed tasks.
|
|
127
|
+
- Chat continuation supports natural directives (`continue`, `move forward`), and path-scope governance blocks now attempt automatic re-plan + retry recovery.
|
|
128
128
|
|
|
129
129
|
**Tip:** Use `archon plan --edit` to adjust title and acceptance criteria before planning.
|
|
130
130
|
**Web Checks:** If Archon detects a web project, it prompts to run A11y/SEO/GEO checks and stores your preference in `.archon/config.yaml`.
|
|
@@ -4182,12 +4182,32 @@ var ExecutorAgent = class {
|
|
|
4182
4182
|
* Execute an approved plan
|
|
4183
4183
|
*/
|
|
4184
4184
|
async executeAtom(atom, plan, architecture, cwd = process.cwd()) {
|
|
4185
|
+
if (plan.files_to_modify.length === 0) {
|
|
4186
|
+
return {
|
|
4187
|
+
success: false,
|
|
4188
|
+
diffs: [],
|
|
4189
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
4190
|
+
qualityChecksPassed: false,
|
|
4191
|
+
errorMessage: "Architecture violations: Plan has no target files to modify (files_to_modify is empty)",
|
|
4192
|
+
rollbackPerformed: false
|
|
4193
|
+
};
|
|
4194
|
+
}
|
|
4185
4195
|
const userMessage = await this.buildPrompt(atom, plan, architecture, cwd);
|
|
4186
4196
|
const response = await this.client.chat(SYSTEM_PROMPT, userMessage, {
|
|
4187
4197
|
temperature: 0.2,
|
|
4188
4198
|
maxTokens: 8192
|
|
4189
4199
|
});
|
|
4190
4200
|
const diffs = this.parseDiffs(response.content);
|
|
4201
|
+
if (diffs.length === 0) {
|
|
4202
|
+
return {
|
|
4203
|
+
success: false,
|
|
4204
|
+
diffs,
|
|
4205
|
+
usage: response.usage,
|
|
4206
|
+
qualityChecksPassed: false,
|
|
4207
|
+
errorMessage: "Architecture violations: Executor returned no file diffs; plan may be underspecified",
|
|
4208
|
+
rollbackPerformed: false
|
|
4209
|
+
};
|
|
4210
|
+
}
|
|
4191
4211
|
const violations = this.checkArchitectureViolations(diffs, plan, architecture);
|
|
4192
4212
|
if (violations.length > 0) {
|
|
4193
4213
|
return {
|
|
@@ -4324,6 +4344,8 @@ var ExecutorAgent = class {
|
|
|
4324
4344
|
parts.push("");
|
|
4325
4345
|
parts.push("# Your Task");
|
|
4326
4346
|
parts.push("Implement the plan by generating the file changes.");
|
|
4347
|
+
parts.push('Only output diffs for files listed under "Files to Modify".');
|
|
4348
|
+
parts.push("Do not invent new file paths or directories.");
|
|
4327
4349
|
parts.push("Output complete file contents for each file using the diff format.");
|
|
4328
4350
|
parts.push(`Remember: Your implementation style should match the ${posture.toUpperCase()} posture.`);
|
|
4329
4351
|
return parts.join("\n");
|
|
@@ -4802,7 +4824,8 @@ function collectAllowedPathsFromArchitecture(schema) {
|
|
|
4802
4824
|
return Array.from(new Set(paths));
|
|
4803
4825
|
}
|
|
4804
4826
|
async function attemptPathScopeAutoRecovery(atom, cwd, parseSchema, options) {
|
|
4805
|
-
|
|
4827
|
+
const recoveryDepth = options.autoRecoverDepth ?? 0;
|
|
4828
|
+
if (!options.nonTerminating || recoveryDepth >= 2) {
|
|
4806
4829
|
return false;
|
|
4807
4830
|
}
|
|
4808
4831
|
const allowedPaths = collectAllowedPathsFromArchitecture(parseSchema);
|
|
@@ -4813,12 +4836,24 @@ async function attemptPathScopeAutoRecovery(atom, cwd, parseSchema, options) {
|
|
|
4813
4836
|
const before = await listLocalAtoms();
|
|
4814
4837
|
const recoveryStartedAt = Date.now();
|
|
4815
4838
|
const recoverySource = atom.description ?? atom.title;
|
|
4816
|
-
const
|
|
4839
|
+
const normalizedAllowedPaths = allowedPaths.map((path) => path.trim()).filter(Boolean);
|
|
4840
|
+
const forcedBasePath = normalizedAllowedPaths.map((path) => path.replace(/\/\*\*$/, "").replace(/\*.*$/, "")).find((path) => path.length > 0 && path !== ".");
|
|
4841
|
+
const strictScopeLine = normalizedAllowedPaths.join(", ");
|
|
4842
|
+
const scopedRequest = recoveryDepth === 0 ? `${recoverySource}
|
|
4817
4843
|
|
|
4818
4844
|
Constraints:
|
|
4819
|
-
- Only modify files within these allowed architecture paths: ${
|
|
4820
|
-
-
|
|
4821
|
-
|
|
4845
|
+
- Only modify files within these allowed architecture paths: ${strictScopeLine}
|
|
4846
|
+
- Before implementation, choose exact target file paths and ensure every path matches the allowed scope.
|
|
4847
|
+
- If required files are outside scope, first propose the minimum architecture path update needed.` : `${recoverySource}
|
|
4848
|
+
|
|
4849
|
+
Hard Constraints:
|
|
4850
|
+
- EVERY output file path MUST start with: ${forcedBasePath ?? normalizedAllowedPaths[0]}
|
|
4851
|
+
- Do not create files outside this base path.
|
|
4852
|
+
- If this cannot satisfy the task, return a minimal architecture path update proposal instead of writing out-of-scope files.`;
|
|
4853
|
+
const phaseLabel = recoveryDepth === 0 ? "scope-constrained retry" : "forced-base-path retry";
|
|
4854
|
+
console.log(chalk2.dim(`
|
|
4855
|
+
Auto-recovery: re-planning with ${phaseLabel}...
|
|
4856
|
+
`));
|
|
4822
4857
|
await plan(scopedRequest, { conversational: true });
|
|
4823
4858
|
const after = await listLocalAtoms();
|
|
4824
4859
|
const byMostRecent = (a, b) => {
|
|
@@ -4841,7 +4876,7 @@ Constraints:
|
|
|
4841
4876
|
}
|
|
4842
4877
|
console.log(chalk2.dim(`Auto-recovery: retrying with ${replacement.externalId}...
|
|
4843
4878
|
`));
|
|
4844
|
-
await execute(replacement.externalId, { ...options,
|
|
4879
|
+
await execute(replacement.externalId, { ...options, autoRecoverDepth: recoveryDepth + 1, nonTerminating: true });
|
|
4845
4880
|
return true;
|
|
4846
4881
|
}
|
|
4847
4882
|
function createPrompt() {
|
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
EnvironmentConfigLoader,
|
|
57
57
|
EnvironmentValidator,
|
|
58
58
|
execute
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-3E5QISRH.js";
|
|
60
60
|
import {
|
|
61
61
|
cloudCancel,
|
|
62
62
|
cloudLogs,
|
|
@@ -2618,6 +2618,8 @@ var PAID_TIER_DEFAULT_CHAT_MODEL = "gemini-3.1-pro-preview";
|
|
|
2618
2618
|
var pendingProposalRequest = null;
|
|
2619
2619
|
var pendingProposalMode = "atom";
|
|
2620
2620
|
var pendingAnalysisToAtomRequest = null;
|
|
2621
|
+
var pendingAnalysisReviewedFiles = [];
|
|
2622
|
+
var pendingAnalysisCapsuleCount = null;
|
|
2621
2623
|
function uiText(rich, plain) {
|
|
2622
2624
|
return isTerminalSafeMode() ? plain : rich;
|
|
2623
2625
|
}
|
|
@@ -3681,9 +3683,14 @@ async function handleAgentConversationInput(cwd, input) {
|
|
|
3681
3683
|
if (pendingAnalysisToAtomRequest && isCreateAtomDirective(normalized)) {
|
|
3682
3684
|
const request = pendingAnalysisToAtomRequest;
|
|
3683
3685
|
pendingAnalysisToAtomRequest = null;
|
|
3686
|
+
const reviewedFiles = [...pendingAnalysisReviewedFiles];
|
|
3687
|
+
pendingAnalysisReviewedFiles = [];
|
|
3688
|
+
const capsuleCount = pendingAnalysisCapsuleCount ?? 1;
|
|
3689
|
+
pendingAnalysisCapsuleCount = null;
|
|
3690
|
+
const enrichedRequest = enrichApprovedAnalysisRequest(request, reviewedFiles, capsuleCount);
|
|
3684
3691
|
console.log(chalk5.dim("\n> Great. Creating a governed task from the approved analysis plan.\n"));
|
|
3685
3692
|
const { plan: plan3 } = await import("./plan-S5EULQKJ.js");
|
|
3686
|
-
await plan3(await withAllowedPathScope(cwd,
|
|
3693
|
+
await plan3(await withAllowedPathScope(cwd, enrichedRequest), { conversational: true });
|
|
3687
3694
|
console.log(chalk5.dim("\n> Starting implementation now...\n"));
|
|
3688
3695
|
await continueWithCurrentTask(cwd);
|
|
3689
3696
|
return true;
|
|
@@ -3937,9 +3944,23 @@ async function provideAnalysisFirstPlan(cwd, request) {
|
|
|
3937
3944
|
console.log(sampleDraft);
|
|
3938
3945
|
}
|
|
3939
3946
|
pendingAnalysisToAtomRequest = request;
|
|
3947
|
+
pendingAnalysisReviewedFiles = reviewedFiles;
|
|
3948
|
+
pendingAnalysisCapsuleCount = capsuleCount;
|
|
3940
3949
|
console.log();
|
|
3941
3950
|
console.log(chalk5.dim('Reply with "yes", "go ahead", or "create atom" when you want me to implement this in governed mode.'));
|
|
3942
3951
|
}
|
|
3952
|
+
function enrichApprovedAnalysisRequest(request, reviewedFiles, capsuleCount) {
|
|
3953
|
+
const normalizedFiles = reviewedFiles.map((file) => file.trim()).filter((file) => file.length > 0);
|
|
3954
|
+
if (normalizedFiles.length === 0) {
|
|
3955
|
+
return request;
|
|
3956
|
+
}
|
|
3957
|
+
return `${request}
|
|
3958
|
+
|
|
3959
|
+
Approved analysis context:
|
|
3960
|
+
- Day-1 source files to use: ${normalizedFiles.join(", ")}
|
|
3961
|
+
- Create a sample using ${capsuleCount} capsule${capsuleCount === 1 ? "" : "s"}.
|
|
3962
|
+
- Keep implementation in these files unless a path-scope update is explicitly approved.`;
|
|
3963
|
+
}
|
|
3943
3964
|
function collectMarkdownFiles(cwd) {
|
|
3944
3965
|
const results = [];
|
|
3945
3966
|
const queue = ["."];
|
|
@@ -4061,7 +4082,7 @@ async function continueWithCurrentTask(cwd) {
|
|
|
4061
4082
|
console.log(chalk5.dim(`
|
|
4062
4083
|
Continuing with ${nextAtom.externalId}...
|
|
4063
4084
|
`));
|
|
4064
|
-
const { execute: execute2 } = await import("./execute-
|
|
4085
|
+
const { execute: execute2 } = await import("./execute-6YDCYC4Z.js");
|
|
4065
4086
|
await execute2(nextAtom.externalId, { nonTerminating: true });
|
|
4066
4087
|
}
|
|
4067
4088
|
async function replanLatestBlockedAtom(cwd) {
|
|
@@ -4259,6 +4280,7 @@ async function withAllowedPathScope(cwd, request) {
|
|
|
4259
4280
|
|
|
4260
4281
|
Constraints:
|
|
4261
4282
|
- Only modify files within these allowed architecture paths: ${allowedPaths.join(", ")}
|
|
4283
|
+
- Before writing code/content, choose exact output file paths and ensure each one stays inside allowed scope.
|
|
4262
4284
|
- If required files are outside this scope, propose the minimum architecture path update first.`;
|
|
4263
4285
|
}
|
|
4264
4286
|
async function planTask() {
|
|
@@ -4356,7 +4378,7 @@ async function executeNext() {
|
|
|
4356
4378
|
const atomId = await prompt("Enter atom ID to execute (or press Enter for first pending)");
|
|
4357
4379
|
const targetId = atomId.trim() || pendingAtoms[0]?.id;
|
|
4358
4380
|
if (targetId) {
|
|
4359
|
-
const { execute: execute2 } = await import("./execute-
|
|
4381
|
+
const { execute: execute2 } = await import("./execute-6YDCYC4Z.js");
|
|
4360
4382
|
await execute2(targetId, {});
|
|
4361
4383
|
} else {
|
|
4362
4384
|
console.log(chalk5.yellow("No atom to execute."));
|