archondev 2.19.34 → 2.19.37

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.
@@ -4794,6 +4794,56 @@ function extractGovernanceViolations(errorMessage) {
4794
4794
  if (!errorMessage.startsWith(prefix)) return [];
4795
4795
  return errorMessage.slice(prefix.length).split(",").map((item) => item.trim()).filter(Boolean);
4796
4796
  }
4797
+ function isPathScopeGovernanceViolation(errorMessage) {
4798
+ return extractGovernanceViolations(errorMessage).some((violation) => violation.toLowerCase().includes("outside the allowed paths"));
4799
+ }
4800
+ function collectAllowedPathsFromArchitecture(schema) {
4801
+ const paths = (schema.components ?? []).flatMap((component) => component.paths ?? []).filter((path) => typeof path === "string" && path.trim().length > 0);
4802
+ return Array.from(new Set(paths));
4803
+ }
4804
+ async function attemptPathScopeAutoRecovery(atom, cwd, parseSchema, options) {
4805
+ if (!options.nonTerminating || options.autoRecoverAttempted) {
4806
+ return false;
4807
+ }
4808
+ const allowedPaths = collectAllowedPathsFromArchitecture(parseSchema);
4809
+ if (allowedPaths.length === 0) {
4810
+ return false;
4811
+ }
4812
+ const { listLocalAtoms, plan } = await import("./plan-S5EULQKJ.js");
4813
+ const before = await listLocalAtoms();
4814
+ const recoveryStartedAt = Date.now();
4815
+ const recoverySource = atom.description ?? atom.title;
4816
+ const scopedRequest = `${recoverySource}
4817
+
4818
+ Constraints:
4819
+ - Only modify files within these allowed architecture paths: ${allowedPaths.join(", ")}
4820
+ - If required files are outside scope, first propose the minimum architecture path update needed.`;
4821
+ console.log(chalk2.dim("\nAuto-recovery: re-planning with allowed-path scope constraints...\n"));
4822
+ await plan(scopedRequest, { conversational: true });
4823
+ const after = await listLocalAtoms();
4824
+ const byMostRecent = (a, b) => {
4825
+ const aTime = new Date(String(a.updatedAt ?? a.createdAt ?? "")).getTime() || 0;
4826
+ const bTime = new Date(String(b.updatedAt ?? b.createdAt ?? "")).getTime() || 0;
4827
+ return bTime - aTime;
4828
+ };
4829
+ let replacement = after.filter((entry) => {
4830
+ if (entry.status !== "READY") return false;
4831
+ if (entry.externalId === atom.externalId) return false;
4832
+ const updatedAt = new Date(String(entry.updatedAt ?? entry.createdAt ?? "")).getTime() || 0;
4833
+ return updatedAt >= recoveryStartedAt - 2e3;
4834
+ }).sort(byMostRecent)[0];
4835
+ if (!replacement) {
4836
+ replacement = after.filter((entry) => entry.status === "READY" && entry.externalId !== atom.externalId).sort(byMostRecent)[0];
4837
+ }
4838
+ if (!replacement) {
4839
+ console.log(chalk2.yellow("Auto-recovery could not find a replacement READY atom to retry."));
4840
+ return false;
4841
+ }
4842
+ console.log(chalk2.dim(`Auto-recovery: retrying with ${replacement.externalId}...
4843
+ `));
4844
+ await execute(replacement.externalId, { ...options, autoRecoverAttempted: true, nonTerminating: true });
4845
+ return true;
4846
+ }
4797
4847
  function createPrompt() {
4798
4848
  const rl = createInterface({
4799
4849
  input: process.stdin,
@@ -5068,7 +5118,23 @@ ${conflictReport.blockerCount} blocking conflict(s) found.`));
5068
5118
  errorMessage: executionResult.errorMessage
5069
5119
  });
5070
5120
  if (isGovernanceViolation(executionResult.errorMessage)) {
5071
- printExecuteNextActions(atom.externalId, false);
5121
+ const pathScopeViolation = isPathScopeGovernanceViolation(executionResult.errorMessage);
5122
+ if (pathScopeViolation) {
5123
+ const recovered = await attemptPathScopeAutoRecovery(
5124
+ atom,
5125
+ cwd,
5126
+ parseResult.schema,
5127
+ options
5128
+ );
5129
+ if (recovered) {
5130
+ return;
5131
+ }
5132
+ }
5133
+ printExecuteNextActions(
5134
+ atom.externalId,
5135
+ false,
5136
+ pathScopeViolation ? "governance_path" : "generic"
5137
+ );
5072
5138
  return;
5073
5139
  }
5074
5140
  return fail();
@@ -5183,12 +5249,18 @@ Running quality gates for ${targetEnvName}...`));
5183
5249
  prompt.close();
5184
5250
  }
5185
5251
  }
5186
- function printExecuteNextActions(atomExternalId, success) {
5252
+ function printExecuteNextActions(atomExternalId, success, context = "generic") {
5187
5253
  console.log();
5188
5254
  console.log(chalk2.bold("Next best action:"));
5189
5255
  if (success) {
5190
5256
  console.log(chalk2.dim(` \u2022 Run ${chalk2.cyan("archon list")} to select your next atom.`));
5191
5257
  } else {
5258
+ if (context === "governance_path") {
5259
+ console.log(chalk2.dim(` \u2022 In chat, say ${chalk2.cyan('"adjust this atom to allowed paths"')} to re-scope automatically.`));
5260
+ console.log(chalk2.dim(` \u2022 Then say ${chalk2.cyan('"continue"')} to execute the re-scoped atom.`));
5261
+ console.log(chalk2.dim(` \u2022 Run ${chalk2.cyan(`archon show ${atomExternalId}`)} to inspect the blocked atom.`));
5262
+ return;
5263
+ }
5192
5264
  console.log(chalk2.dim(` \u2022 Run ${chalk2.cyan(`archon show ${atomExternalId}`)} to inspect this atom.`));
5193
5265
  }
5194
5266
  console.log(chalk2.dim(` \u2022 Run ${chalk2.cyan("archon credits")} to verify balance/tier.`));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  execute
3
- } from "./chunk-MSWU7N4T.js";
3
+ } from "./chunk-KZP4GK6K.js";
4
4
  import "./chunk-EBHHIUCB.js";
5
5
  import "./chunk-LGWUWEEJ.js";
6
6
  import "./chunk-WGLVDEZC.js";
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ import {
56
56
  EnvironmentConfigLoader,
57
57
  EnvironmentValidator,
58
58
  execute
59
- } from "./chunk-MSWU7N4T.js";
59
+ } from "./chunk-KZP4GK6K.js";
60
60
  import {
61
61
  cloudCancel,
62
62
  cloudLogs,
@@ -3683,7 +3683,7 @@ async function handleAgentConversationInput(cwd, input) {
3683
3683
  pendingAnalysisToAtomRequest = null;
3684
3684
  console.log(chalk5.dim("\n> Great. Creating a governed task from the approved analysis plan.\n"));
3685
3685
  const { plan: plan3 } = await import("./plan-S5EULQKJ.js");
3686
- await plan3(request, { conversational: true });
3686
+ await plan3(await withAllowedPathScope(cwd, request), { conversational: true });
3687
3687
  console.log(chalk5.dim("\n> Starting implementation now...\n"));
3688
3688
  await continueWithCurrentTask(cwd);
3689
3689
  return true;
@@ -3724,7 +3724,7 @@ async function handleAgentConversationInput(cwd, input) {
3724
3724
  }
3725
3725
  console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
3726
3726
  const { plan: plan2 } = await import("./plan-S5EULQKJ.js");
3727
- await plan2(input, { conversational: true });
3727
+ await plan2(await withAllowedPathScope(cwd, input), { conversational: true });
3728
3728
  if (shouldAutoExecuteAfterPlanning(input)) {
3729
3729
  await continueWithCurrentTask(cwd);
3730
3730
  return true;
@@ -3886,7 +3886,7 @@ async function applyApprovedProposal(cwd) {
3886
3886
  }
3887
3887
  console.log(chalk5.dim("\n> Great. I will create the task from your approved request.\n"));
3888
3888
  const { plan: plan2 } = await import("./plan-S5EULQKJ.js");
3889
- await plan2(approvedRequest, { conversational: true });
3889
+ await plan2(await withAllowedPathScope(cwd, approvedRequest), { conversational: true });
3890
3890
  if (shouldAutoExecuteAfterPlanning(approvedRequest)) {
3891
3891
  await continueWithCurrentTask(cwd);
3892
3892
  return;
@@ -4061,7 +4061,7 @@ async function continueWithCurrentTask(cwd) {
4061
4061
  console.log(chalk5.dim(`
4062
4062
  Continuing with ${nextAtom.externalId}...
4063
4063
  `));
4064
- const { execute: execute2 } = await import("./execute-ACRWMKWF.js");
4064
+ const { execute: execute2 } = await import("./execute-HXE6WQFQ.js");
4065
4065
  await execute2(nextAtom.externalId, { nonTerminating: true });
4066
4066
  }
4067
4067
  async function replanLatestBlockedAtom(cwd) {
@@ -4172,7 +4172,7 @@ async function handleFreeformJourneyInput(cwd, input) {
4172
4172
  if (state.hasArchitecture) {
4173
4173
  console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
4174
4174
  const { plan: plan3 } = await import("./plan-S5EULQKJ.js");
4175
- await plan3(freeform, { conversational: true });
4175
+ await plan3(await withAllowedPathScope(cwd, freeform), { conversational: true });
4176
4176
  return true;
4177
4177
  }
4178
4178
  console.log(chalk5.dim("\n> Let me understand your project better...\n"));
@@ -4181,7 +4181,7 @@ async function handleFreeformJourneyInput(cwd, input) {
4181
4181
  }
4182
4182
  console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
4183
4183
  const { plan: plan2 } = await import("./plan-S5EULQKJ.js");
4184
- await plan2(freeform, { conversational: true });
4184
+ await plan2(await withAllowedPathScope(cwd, freeform), { conversational: true });
4185
4185
  return true;
4186
4186
  }
4187
4187
  function extractActionableFollowUpFromExplore(input) {
@@ -4240,7 +4240,7 @@ async function handlePostExploreAction(cwd, request, options = {}) {
4240
4240
  console.log(chalk5.dim("> Got it! Creating a task for this...\n"));
4241
4241
  }
4242
4242
  const { plan: plan2 } = await import("./plan-S5EULQKJ.js");
4243
- await plan2(request, { conversational: true });
4243
+ await plan2(await withAllowedPathScope(cwd, request), { conversational: true });
4244
4244
  if (options.agentMode) {
4245
4245
  if (shouldAutoExecuteAfterPlanning(sourceInput)) {
4246
4246
  await continueWithCurrentTask(cwd);
@@ -4250,6 +4250,17 @@ async function handlePostExploreAction(cwd, request, options = {}) {
4250
4250
  console.log(chalk5.dim('\nReply "execute atom" when you want implementation to start, or tell me what to change.'));
4251
4251
  }
4252
4252
  }
4253
+ async function withAllowedPathScope(cwd, request) {
4254
+ const allowedPaths = await listArchitecturePaths(cwd);
4255
+ if (allowedPaths.length === 0) {
4256
+ return request;
4257
+ }
4258
+ return `${request}
4259
+
4260
+ Constraints:
4261
+ - Only modify files within these allowed architecture paths: ${allowedPaths.join(", ")}
4262
+ - If required files are outside this scope, propose the minimum architecture path update first.`;
4263
+ }
4253
4264
  async function planTask() {
4254
4265
  const { plan: plan2 } = await import("./plan-S5EULQKJ.js");
4255
4266
  const description = await promptWithCommands("Describe what you want to build", { allowMultiline: true });
@@ -4345,7 +4356,7 @@ async function executeNext() {
4345
4356
  const atomId = await prompt("Enter atom ID to execute (or press Enter for first pending)");
4346
4357
  const targetId = atomId.trim() || pendingAtoms[0]?.id;
4347
4358
  if (targetId) {
4348
- const { execute: execute2 } = await import("./execute-ACRWMKWF.js");
4359
+ const { execute: execute2 } = await import("./execute-HXE6WQFQ.js");
4349
4360
  await execute2(targetId, {});
4350
4361
  } else {
4351
4362
  console.log(chalk5.yellow("No atom to execute."));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archondev",
3
- "version": "2.19.34",
3
+ "version": "2.19.37",
4
4
  "description": "Local-first AI-powered development governance system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {