archondev 2.19.30 → 2.19.32

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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/dist/index.js +122 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -123,6 +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 require explicit `create atom` before task creation.
127
+ - Chat execution now requires explicit execute intent (for example, `execute atom`) instead of generic `continue`.
126
128
 
127
129
  **Tip:** Use `archon plan --edit` to adjust title and acceptance criteria before planning.
128
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`.
package/dist/index.js CHANGED
@@ -3701,6 +3701,10 @@ async function handleAgentConversationInput(cwd, input) {
3701
3701
  return true;
3702
3702
  }
3703
3703
  if (wantsProposalBeforeExecution(input)) {
3704
+ if (shouldDoAnalysisBeforeAtom(input)) {
3705
+ await provideAnalysisFirstPlan(cwd, input);
3706
+ return true;
3707
+ }
3704
3708
  await showProposalForApproval(input);
3705
3709
  return true;
3706
3710
  }
@@ -3780,16 +3784,70 @@ Showing latest planned atom (${latest.externalId})...
3780
3784
  await show2(latest.externalId);
3781
3785
  }
3782
3786
  function isPlanApprovalDirective(input) {
3783
- const normalized = input.trim().toLowerCase();
3784
- return normalized === "approve" || normalized === "approve plan" || normalized === "approved" || normalized === "yes" || normalized === "yes, proceed" || normalized === "proceed";
3787
+ const normalized = normalizeDirectiveInput(input);
3788
+ if (!normalized) return false;
3789
+ const directApprovals = /* @__PURE__ */ new Set([
3790
+ "approve",
3791
+ "approve plan",
3792
+ "approved",
3793
+ "yes",
3794
+ "yes proceed",
3795
+ "y",
3796
+ "ok",
3797
+ "okay",
3798
+ "proceed",
3799
+ "go ahead",
3800
+ "continue",
3801
+ "do it",
3802
+ "sounds good",
3803
+ "looks good"
3804
+ ]);
3805
+ if (directApprovals.has(normalized)) return true;
3806
+ if (normalized.startsWith("yes ")) return true;
3807
+ if (/\b(approve|approved)\b/.test(normalized)) return true;
3808
+ const hasProceedSignal = /\b(go ahead|proceed|continue|do it|move forward|keep going)\b/.test(normalized);
3809
+ const hasPlanReference = /\b(plan|proposal|that|this|capsule|capsules)\b/.test(normalized);
3810
+ return hasProceedSignal && hasPlanReference;
3785
3811
  }
3786
3812
  function isExecutionDirective(input) {
3787
- const normalized = input.trim().toLowerCase();
3788
- return normalized === "execute" || normalized === "execute atom" || normalized === "run atom" || normalized === "run it now" || normalized === "implement now" || normalized === "start execution" || normalized === "go ahead and execute";
3813
+ const normalized = normalizeDirectiveInput(input);
3814
+ if (!normalized) return false;
3815
+ const directExecution = /* @__PURE__ */ new Set([
3816
+ "execute",
3817
+ "execute atom",
3818
+ "run atom",
3819
+ "run it now",
3820
+ "implement now",
3821
+ "start execution",
3822
+ "go ahead and execute",
3823
+ "execute now",
3824
+ "run now",
3825
+ "start now"
3826
+ ]);
3827
+ if (directExecution.has(normalized)) return true;
3828
+ return /\b(execute|run|implement|start)\b/.test(normalized) && /\b(atom|task|plan|it|now)\b/.test(normalized);
3789
3829
  }
3790
3830
  function isCreateAtomDirective(input) {
3791
- const normalized = input.trim().toLowerCase();
3792
- return normalized === "create atom" || normalized === "make atom" || normalized === "save as atom" || normalized === "turn this into a task" || normalized === "create task";
3831
+ const normalized = normalizeDirectiveInput(input);
3832
+ if (!normalized) return false;
3833
+ const directCreate = /* @__PURE__ */ new Set([
3834
+ "create",
3835
+ "create atom",
3836
+ "save this",
3837
+ "make atom",
3838
+ "save as atom",
3839
+ "turn this into a task",
3840
+ "create task",
3841
+ "save it",
3842
+ "go ahead",
3843
+ "proceed",
3844
+ "yes"
3845
+ ]);
3846
+ if (directCreate.has(normalized)) return true;
3847
+ return /\b(create|save|make|turn)\b/.test(normalized) && /\b(atom|task|plan|this|it)\b/.test(normalized);
3848
+ }
3849
+ function normalizeDirectiveInput(input) {
3850
+ return input.trim().toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
3793
3851
  }
3794
3852
  function shouldDoAnalysisBeforeAtom(input) {
3795
3853
  const normalized = input.toLowerCase();
@@ -3816,9 +3874,9 @@ async function applyApprovedProposal(cwd) {
3816
3874
  console.log(chalk5.dim('\nReply "execute atom" when you want implementation to start, or tell me what to change.'));
3817
3875
  }
3818
3876
  async function provideAnalysisFirstPlan(cwd, request) {
3819
- console.log(chalk5.dim("\n> Great. I will analyze first and return a concrete recommendation before creating atoms.\n"));
3877
+ console.log(chalk5.dim("\n> I analyzed your request and generated a recommendation + sample draft first.\n"));
3820
3878
  const markdownFiles = collectMarkdownFiles(cwd);
3821
- const dayOneCandidates = markdownFiles.filter((file) => /(day[-_ ]?0?1|lesson[-_ ]?0?1|first)/i.test(file));
3879
+ const dayOneCandidates = markdownFiles.filter((file) => isDayOnePath(file));
3822
3880
  const capsuleCandidates = markdownFiles.filter((file) => /capsule/i.test(file));
3823
3881
  const primaryCandidates = dayOneCandidates.length > 0 ? dayOneCandidates : capsuleCandidates;
3824
3882
  const reviewedFiles = primaryCandidates.slice(0, 8);
@@ -3851,9 +3909,15 @@ async function provideAnalysisFirstPlan(cwd, request) {
3851
3909
  console.log(chalk5.dim(` 2. Define capsule boundaries and titles (${capsuleCount} capsule${capsuleCount > 1 ? "s" : ""}).`));
3852
3910
  console.log(chalk5.dim(" 3. Draft capsule markdown(s) with consistent template and learning objective per capsule."));
3853
3911
  console.log(chalk5.dim(" 4. Add index/manifest links and quick validation checks for user flow."));
3912
+ const sampleDraft = buildSampleCapsuleDraft(cwd, reviewedFiles, capsuleCount);
3913
+ if (sampleDraft) {
3914
+ console.log();
3915
+ console.log(chalk5.bold("Sample output for day 1 (draft):"));
3916
+ console.log(sampleDraft);
3917
+ }
3854
3918
  pendingAnalysisToAtomRequest = request;
3855
3919
  console.log();
3856
- console.log(chalk5.dim('Reply "create atom" to save this as a governed task, or tell me what to adjust first.'));
3920
+ console.log(chalk5.dim('Reply with "yes", "go ahead", or "create atom" when you want me to implement this in governed mode.'));
3857
3921
  }
3858
3922
  function collectMarkdownFiles(cwd) {
3859
3923
  const results = [];
@@ -3897,6 +3961,51 @@ function computeContentStats(cwd, files) {
3897
3961
  }
3898
3962
  return { totalWords, totalHeadings };
3899
3963
  }
3964
+ function isDayOnePath(path2) {
3965
+ const normalized = path2.toLowerCase();
3966
+ return /\b(day[-_ ]?0*1|lesson[-_ ]?0*1|email[-_ ]?day[-_ ]?0*1)\b/.test(normalized) && !/\b(day[-_ ]?(?:1[0-9]|[2-9])|lesson[-_ ]?(?:1[0-9]|[2-9]))\b/.test(normalized);
3967
+ }
3968
+ function buildSampleCapsuleDraft(cwd, files, capsuleCount) {
3969
+ if (files.length === 0) return null;
3970
+ const primary = files[0];
3971
+ if (!primary) return null;
3972
+ let content = "";
3973
+ try {
3974
+ content = readFileSync3(join6(cwd, primary), "utf-8");
3975
+ } catch {
3976
+ return null;
3977
+ }
3978
+ const lines = content.split("\n").map((line) => line.trim());
3979
+ const heading = lines.find((line) => line.startsWith("#"))?.replace(/^#+\s*/, "") || "Day 1 Lesson";
3980
+ const paragraphs = content.split("\n\n").map((p) => p.replace(/\s+/g, " ").trim()).filter((p) => p.length > 40 && !p.startsWith("#") && !p.startsWith("- ") && !p.startsWith("* "));
3981
+ const objective = paragraphs[0] ?? "Introduce the day-1 core idea with a clear, practical framing.";
3982
+ const concept = paragraphs[1] ?? "Explain the key concept in plain language with one relatable example.";
3983
+ const practice = paragraphs[2] ?? "Give one guided prompt so the learner can apply the idea immediately.";
3984
+ if (capsuleCount <= 1) {
3985
+ return [
3986
+ chalk5.dim(" ---"),
3987
+ chalk5.dim(` title: "${heading} - Core Capsule"`),
3988
+ chalk5.dim(' type: "lesson_capsule"'),
3989
+ chalk5.dim(" day: 1"),
3990
+ chalk5.dim(" ---"),
3991
+ chalk5.dim(" ## Objective"),
3992
+ chalk5.dim(` ${objective}`),
3993
+ chalk5.dim(" ## Core Concept"),
3994
+ chalk5.dim(` ${concept}`),
3995
+ chalk5.dim(" ## Practice"),
3996
+ chalk5.dim(` ${practice}`)
3997
+ ].join("\n");
3998
+ }
3999
+ return [
4000
+ chalk5.dim(" Capsule 1: Foundation"),
4001
+ chalk5.dim(` - Objective: ${objective}`),
4002
+ chalk5.dim(` - Core Concept: ${concept}`),
4003
+ chalk5.dim(""),
4004
+ chalk5.dim(" Capsule 2: Application"),
4005
+ chalk5.dim(` - Guided Practice: ${practice}`),
4006
+ chalk5.dim(" - Reflection Prompt: What changed in your understanding after this exercise?")
4007
+ ].join("\n");
4008
+ }
3900
4009
  async function continueWithCurrentTask(cwd) {
3901
4010
  const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-RHDFDSZE.js");
3902
4011
  const atoms = await listLocalAtoms2();
@@ -4031,6 +4140,10 @@ function containsActionIntent(input) {
4031
4140
  async function handlePostExploreAction(cwd, request, options = {}) {
4032
4141
  const sourceInput = options.originalInput?.trim() || request;
4033
4142
  if (wantsProposalBeforeExecution(sourceInput)) {
4143
+ if (shouldDoAnalysisBeforeAtom(sourceInput)) {
4144
+ await provideAnalysisFirstPlan(cwd, sourceInput);
4145
+ return;
4146
+ }
4034
4147
  await showProposalForApproval(sourceInput);
4035
4148
  return;
4036
4149
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archondev",
3
- "version": "2.19.30",
3
+ "version": "2.19.32",
4
4
  "description": "Local-first AI-powered development governance system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {