@yemi33/minions 0.1.1878 → 0.1.1880

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.
@@ -61,12 +61,60 @@ async function refreshPlans() {
61
61
  } catch (e) { console.error('plans refresh:', e.message); }
62
62
  }
63
63
 
64
+ /**
65
+ * Returns true when a failed plan follow-up work item's intended outcome has
66
+ * been satisfied by a later/alternate path — so the stale failure should not
67
+ * drive the plan's top-level "has failures" badge.
68
+ *
69
+ * Reconciliation rules (issue #2366):
70
+ * - Failed `itemType: 'pr'` (Create PR for plan): satisfied when a PR linked
71
+ * to the same plan exists in any non-terminated state (active/merged/linked).
72
+ * The original failure is preserved on the WI for audit; it just doesn't
73
+ * count toward the rollup once a PR actually got created.
74
+ * - Failed `itemType: 'verify'`: satisfied when a newer verify WI for the
75
+ * same plan + project exists and is done OR in-flight (pending/dispatched).
76
+ *
77
+ * Returns false when the outcome cannot be confirmed satisfied — failure
78
+ * remains live and drives the badge.
79
+ */
80
+ function isFollowUpOutcomeSatisfied(wi, allWorkItems, allPrs) {
81
+ if (!wi || wi.status !== 'failed') return false;
82
+ if (wi.itemType === 'pr') {
83
+ // PR for this plan was created on any non-terminated path.
84
+ // "abandoned" / "closed" are terminal failures; everything else counts as
85
+ // the desired outcome being reached.
86
+ return (allPrs || []).some(pr =>
87
+ pr && pr.sourcePlan === wi.sourcePlan &&
88
+ pr.status !== 'abandoned' && pr.status !== 'closed'
89
+ );
90
+ }
91
+ if (wi.itemType === 'verify') {
92
+ // A newer verify WI for the same plan + project that is in flight or done.
93
+ const wiCreated = wi.created || '';
94
+ return (allWorkItems || []).some(other =>
95
+ other && other !== wi && other.itemType === 'verify' &&
96
+ other.sourcePlan === wi.sourcePlan &&
97
+ (other.project || '') === (wi.project || '') &&
98
+ (other.status === 'done' || other.status === 'pending' || other.status === 'dispatched') &&
99
+ (other.created || '') > wiCreated
100
+ );
101
+ }
102
+ return false;
103
+ }
104
+
64
105
  /**
65
106
  * Derive effective plan/PRD status from work items (single source of truth).
66
107
  * PRD JSON status is treated as user intent (approved, paused, rejected),
67
108
  * but completion/progress is always derived from actual work item state.
109
+ *
110
+ * opts.allPrs — optional PR records used to reconcile stale failed follow-up
111
+ * tasks (issue #2366). Falls back to window._lastStatus.pullRequests in the
112
+ * browser. Pass `[]` to disable reconciliation.
68
113
  */
69
- function derivePlanStatus(prdFile, mdFile, prdJsonStatus, workItems) {
114
+ function derivePlanStatus(prdFile, mdFile, prdJsonStatus, workItems, opts) {
115
+ const allPrs = (opts && opts.allPrs)
116
+ || (typeof window !== 'undefined' && window._lastStatus && window._lastStatus.pullRequests)
117
+ || [];
70
118
  const wi = workItems.filter(w =>
71
119
  w.sourcePlan === prdFile || w.sourcePlan === mdFile ||
72
120
  (w.type === 'plan-to-prd' && (w.planFile === prdFile || w.planFile === mdFile))
@@ -74,8 +122,18 @@ function derivePlanStatus(prdFile, mdFile, prdJsonStatus, workItems) {
74
122
  const implementWi = wi.filter(w => w.type !== 'plan-to-prd' && w.type !== 'verify');
75
123
  const hasPendingPrd = wi.some(w => w.type === 'plan-to-prd' && (w.status === 'pending' || w.status === 'dispatched'));
76
124
  const hasActiveWork = implementWi.some(w => w.status === 'pending' || w.status === 'dispatched');
77
- const allDone = implementWi.length > 0 && implementWi.every(w => w.status === 'done' || w.status === 'decomposed');
78
- const hasFailed = implementWi.some(w => w.status === 'failed');
125
+ // A WI is "effectively done" when it succeeded normally OR when it is a
126
+ // reconciled follow-up failure (intended outcome satisfied elsewhere — #2366).
127
+ // The original failure record is preserved on the WI for audit; it just
128
+ // stops blocking plan completion and stops driving the red badge.
129
+ const isReconciledFailure = (w) =>
130
+ w.status === 'failed' &&
131
+ (w.itemType === 'pr' || w.itemType === 'verify') &&
132
+ isFollowUpOutcomeSatisfied(w, workItems, allPrs);
133
+ const isEffectivelyDone = (w) =>
134
+ w.status === 'done' || w.status === 'decomposed' || isReconciledFailure(w);
135
+ const allDone = implementWi.length > 0 && implementWi.every(isEffectivelyDone);
136
+ const hasFailed = implementWi.some(w => w.status === 'failed' && !isReconciledFailure(w));
79
137
 
80
138
  // User-set statuses take priority when no work has started
81
139
  if (prdJsonStatus === 'rejected') return 'rejected';
@@ -897,4 +955,4 @@ async function planUnarchive(file, btn) {
897
955
  } catch (e) { showToast('cmd-toast', 'Error: ' + e.message, false); refresh(); }
898
956
  }
899
957
 
900
- window.MinionsPlans = { openCreatePlanModal, refreshPlans, derivePlanStatus, renderPlans, openArchivedPlansModal, planExecute, planReexecuteModal, planReexecuteSubmit, planSubmitRevise, planShowRevise, planHideRevise, planView, planApprove, planArchive, planUnarchive, planDelete, planPause, planReject, planDiscuss, planOpenInDocChat, planRegeneratePRD, openVerifyGuide, triggerVerify };
958
+ window.MinionsPlans = { openCreatePlanModal, refreshPlans, derivePlanStatus, isFollowUpOutcomeSatisfied, renderPlans, openArchivedPlansModal, planExecute, planReexecuteModal, planReexecuteSubmit, planSubmitRevise, planShowRevise, planHideRevise, planView, planApprove, planArchive, planUnarchive, planDelete, planPause, planReject, planDiscuss, planOpenInDocChat, planRegeneratePRD, openVerifyGuide, triggerVerify };
@@ -0,0 +1,34 @@
1
+ # Per-Agent Memory Files
2
+
3
+ This directory holds **per-agent personal memory files** — one markdown file per
4
+ named agent (e.g. `dallas.md`, `rebecca.md`). Each file is a personal notebook
5
+ for that agent: the consolidation pipeline appends inbox findings authored by
6
+ the agent to their own file, and the engine injects the agent's file into their
7
+ prompt context on every dispatch (alongside the broadcast `notes.md`).
8
+
9
+ ## How it works
10
+
11
+ 1. **Authoring**: When an agent writes a learnings file under
12
+ `notes/inbox/<agent>-<task>-<date>.md`, the YAML frontmatter `agent:` field
13
+ identifies the author. Filename prefix (`<agent>-...`) is used as fallback.
14
+ 2. **Consolidation**: `engine/consolidation.js` runs on every tick. After the
15
+ shared `notes.md` digest is written, `classifyToKnowledgeBase` also
16
+ appends each item to `knowledge/agents/<agent>.md` when the agent is a
17
+ known team member (matches `config.agents`). This is **strict superset**
18
+ semantics — broadcast consolidation still happens; per-agent routing is in
19
+ addition.
20
+ 3. **Prompt injection**: `engine/playbook.js` injects, in order, `pinned.md`,
21
+ `notes.md`, then `knowledge/agents/<agentId>.md` (when present) into the
22
+ agent's prompt. Missing files are silently skipped.
23
+
24
+ ## Conventions
25
+
26
+ - One `.md` file per agent, named `<agent-id>.md` (lowercase).
27
+ - Append-only from the consolidation engine — agents should not edit their
28
+ own memory files directly. To record a learning, write to
29
+ `notes/inbox/` as usual; the sweep will route it.
30
+ - Capped at ~25 KB per file; oldest sections are pruned at section
31
+ boundaries to stay under budget.
32
+ - Frontmatter `agent:` in inbox notes is the canonical author field.
33
+ - Temp agents (e.g. `temp-mp1fnkze...`) are skipped — only configured
34
+ team members get a memory file.
@@ -0,0 +1,9 @@
1
+ # Dallas — Personal Memory
2
+
3
+ This is Dallas's personal memory file, curated by the consolidation pipeline
4
+ from inbox findings tagged `agent: dallas`. The engine injects this file into
5
+ Dallas's prompt context on every dispatch (alongside `notes.md`).
6
+
7
+ See `knowledge/agents/README.md` for the convention.
8
+
9
+ <!-- Append-only; consolidation engine writes new sections below. -->
@@ -0,0 +1,9 @@
1
+ # Lambert — Personal Memory
2
+
3
+ This is Lambert's personal memory file, curated by the consolidation pipeline
4
+ from inbox findings tagged `agent: lambert`. The engine injects this file into
5
+ Lambert's prompt context on every dispatch (alongside `notes.md`).
6
+
7
+ See `knowledge/agents/README.md` for the convention.
8
+
9
+ <!-- Append-only; consolidation engine writes new sections below. -->
@@ -0,0 +1,9 @@
1
+ # Ralph — Personal Memory
2
+
3
+ This is Ralph's personal memory file, curated by the consolidation pipeline
4
+ from inbox findings tagged `agent: ralph`. The engine injects this file into
5
+ Ralph's prompt context on every dispatch (alongside `notes.md`).
6
+
7
+ See `knowledge/agents/README.md` for the convention.
8
+
9
+ <!-- Append-only; consolidation engine writes new sections below. -->
@@ -0,0 +1,9 @@
1
+ # Rebecca — Personal Memory
2
+
3
+ This is Rebecca's personal memory file, curated by the consolidation pipeline
4
+ from inbox findings tagged `agent: rebecca`. The engine injects this file into
5
+ Rebecca's prompt context on every dispatch (alongside `notes.md`).
6
+
7
+ See `knowledge/agents/README.md` for the convention.
8
+
9
+ <!-- Append-only; consolidation engine writes new sections below. -->
@@ -0,0 +1,9 @@
1
+ # Ripley — Personal Memory
2
+
3
+ This is Ripley's personal memory file, curated by the consolidation pipeline
4
+ from inbox findings tagged `agent: ripley`. The engine injects this file into
5
+ Ripley's prompt context on every dispatch (alongside `notes.md`).
6
+
7
+ See `knowledge/agents/README.md` for the convention.
8
+
9
+ <!-- Append-only; consolidation engine writes new sections below. -->
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1878",
3
+ "version": "0.1.1880",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"
7
7
  },
8
8
  "scripts": {
9
+ "package:check": "node tools/check-package-boundary.js public",
10
+ "package:prepare:public": "node tools/prepare-package.js public",
11
+ "package:prepare:internal": "node tools/prepare-package.js internal",
9
12
  "test": "node test/run-parallel.js",
10
13
  "test:sequential": "node test/unit.test.js",
11
14
  "test:unit": "node test/run-parallel.js",
@@ -32,11 +35,28 @@
32
35
  ],
33
36
  "author": "yemi33",
34
37
  "license": "MIT",
38
+ "files": [
39
+ "agents/*/charter.md",
40
+ "bin/",
41
+ "config.template.json",
42
+ "dashboard/",
43
+ "dashboard-build.js",
44
+ "dashboard.js",
45
+ "docs/",
46
+ "engine/",
47
+ "engine.js",
48
+ "knowledge/agents/*.md",
49
+ "minions.js",
50
+ "playbooks/",
51
+ "prompts/",
52
+ "routing.md",
53
+ "skills/"
54
+ ],
35
55
  "repository": {
36
56
  "type": "git",
37
57
  "url": "https://github.com/yemi33/minions.git"
38
58
  },
39
- "homepage": "https://github.com/yemi33/minions#readme",
59
+ "homepage": "https://yemi33.github.io/minions/",
40
60
  "engines": {
41
61
  "node": ">=18"
42
62
  },
File without changes
package/.claudeignore DELETED
@@ -1,5 +0,0 @@
1
- agents/
2
- engine/tmp/
3
- engine/contexts/
4
- prd/*.backup
5
- plans/archive/
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- * text=auto eol=lf
2
- *.ps1 text eol=crlf