archondev 2.19.30 → 2.19.31

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,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
  }
@@ -3789,7 +3793,7 @@ function isExecutionDirective(input) {
3789
3793
  }
3790
3794
  function isCreateAtomDirective(input) {
3791
3795
  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";
3796
+ return normalized === "create atom" || normalized === "save this" || normalized === "make atom" || normalized === "save as atom" || normalized === "turn this into a task" || normalized === "create task";
3793
3797
  }
3794
3798
  function shouldDoAnalysisBeforeAtom(input) {
3795
3799
  const normalized = input.toLowerCase();
@@ -3816,9 +3820,9 @@ async function applyApprovedProposal(cwd) {
3816
3820
  console.log(chalk5.dim('\nReply "execute atom" when you want implementation to start, or tell me what to change.'));
3817
3821
  }
3818
3822
  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"));
3823
+ console.log(chalk5.dim("\n> I analyzed your request and generated a recommendation + sample draft first.\n"));
3820
3824
  const markdownFiles = collectMarkdownFiles(cwd);
3821
- const dayOneCandidates = markdownFiles.filter((file) => /(day[-_ ]?0?1|lesson[-_ ]?0?1|first)/i.test(file));
3825
+ const dayOneCandidates = markdownFiles.filter((file) => isDayOnePath(file));
3822
3826
  const capsuleCandidates = markdownFiles.filter((file) => /capsule/i.test(file));
3823
3827
  const primaryCandidates = dayOneCandidates.length > 0 ? dayOneCandidates : capsuleCandidates;
3824
3828
  const reviewedFiles = primaryCandidates.slice(0, 8);
@@ -3851,9 +3855,15 @@ async function provideAnalysisFirstPlan(cwd, request) {
3851
3855
  console.log(chalk5.dim(` 2. Define capsule boundaries and titles (${capsuleCount} capsule${capsuleCount > 1 ? "s" : ""}).`));
3852
3856
  console.log(chalk5.dim(" 3. Draft capsule markdown(s) with consistent template and learning objective per capsule."));
3853
3857
  console.log(chalk5.dim(" 4. Add index/manifest links and quick validation checks for user flow."));
3858
+ const sampleDraft = buildSampleCapsuleDraft(cwd, reviewedFiles, capsuleCount);
3859
+ if (sampleDraft) {
3860
+ console.log();
3861
+ console.log(chalk5.bold("Sample output for day 1 (draft):"));
3862
+ console.log(sampleDraft);
3863
+ }
3854
3864
  pendingAnalysisToAtomRequest = request;
3855
3865
  console.log();
3856
- console.log(chalk5.dim('Reply "create atom" to save this as a governed task, or tell me what to adjust first.'));
3866
+ console.log(chalk5.dim('Reply "save this" (or "create atom") if you want me to implement this in governed mode.'));
3857
3867
  }
3858
3868
  function collectMarkdownFiles(cwd) {
3859
3869
  const results = [];
@@ -3897,6 +3907,51 @@ function computeContentStats(cwd, files) {
3897
3907
  }
3898
3908
  return { totalWords, totalHeadings };
3899
3909
  }
3910
+ function isDayOnePath(path2) {
3911
+ const normalized = path2.toLowerCase();
3912
+ 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);
3913
+ }
3914
+ function buildSampleCapsuleDraft(cwd, files, capsuleCount) {
3915
+ if (files.length === 0) return null;
3916
+ const primary = files[0];
3917
+ if (!primary) return null;
3918
+ let content = "";
3919
+ try {
3920
+ content = readFileSync3(join6(cwd, primary), "utf-8");
3921
+ } catch {
3922
+ return null;
3923
+ }
3924
+ const lines = content.split("\n").map((line) => line.trim());
3925
+ const heading = lines.find((line) => line.startsWith("#"))?.replace(/^#+\s*/, "") || "Day 1 Lesson";
3926
+ const paragraphs = content.split("\n\n").map((p) => p.replace(/\s+/g, " ").trim()).filter((p) => p.length > 40 && !p.startsWith("#") && !p.startsWith("- ") && !p.startsWith("* "));
3927
+ const objective = paragraphs[0] ?? "Introduce the day-1 core idea with a clear, practical framing.";
3928
+ const concept = paragraphs[1] ?? "Explain the key concept in plain language with one relatable example.";
3929
+ const practice = paragraphs[2] ?? "Give one guided prompt so the learner can apply the idea immediately.";
3930
+ if (capsuleCount <= 1) {
3931
+ return [
3932
+ chalk5.dim(" ---"),
3933
+ chalk5.dim(` title: "${heading} - Core Capsule"`),
3934
+ chalk5.dim(' type: "lesson_capsule"'),
3935
+ chalk5.dim(" day: 1"),
3936
+ chalk5.dim(" ---"),
3937
+ chalk5.dim(" ## Objective"),
3938
+ chalk5.dim(` ${objective}`),
3939
+ chalk5.dim(" ## Core Concept"),
3940
+ chalk5.dim(` ${concept}`),
3941
+ chalk5.dim(" ## Practice"),
3942
+ chalk5.dim(` ${practice}`)
3943
+ ].join("\n");
3944
+ }
3945
+ return [
3946
+ chalk5.dim(" Capsule 1: Foundation"),
3947
+ chalk5.dim(` - Objective: ${objective}`),
3948
+ chalk5.dim(` - Core Concept: ${concept}`),
3949
+ chalk5.dim(""),
3950
+ chalk5.dim(" Capsule 2: Application"),
3951
+ chalk5.dim(` - Guided Practice: ${practice}`),
3952
+ chalk5.dim(" - Reflection Prompt: What changed in your understanding after this exercise?")
3953
+ ].join("\n");
3954
+ }
3900
3955
  async function continueWithCurrentTask(cwd) {
3901
3956
  const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-RHDFDSZE.js");
3902
3957
  const atoms = await listLocalAtoms2();
@@ -4031,6 +4086,10 @@ function containsActionIntent(input) {
4031
4086
  async function handlePostExploreAction(cwd, request, options = {}) {
4032
4087
  const sourceInput = options.originalInput?.trim() || request;
4033
4088
  if (wantsProposalBeforeExecution(sourceInput)) {
4089
+ if (shouldDoAnalysisBeforeAtom(sourceInput)) {
4090
+ await provideAnalysisFirstPlan(cwd, sourceInput);
4091
+ return;
4092
+ }
4034
4093
  await showProposalForApproval(sourceInput);
4035
4094
  return;
4036
4095
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archondev",
3
- "version": "2.19.30",
3
+ "version": "2.19.31",
4
4
  "description": "Local-first AI-powered development governance system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {