@jaybeeuu/agent-cortex 1.38.1 → 1.40.0
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/.agents/skills/style-versioning/SKILL.md +1 -1
- package/.github/workflows/ci.yml +47 -14
- package/AGENTS.md +19 -3
- package/CHANGELOG.md +42 -0
- package/README.md +118 -63
- package/agents/README.md +13 -10
- package/agents/ralph-plan/agent.md +1 -1
- package/agents/ralph-plan.agent.md +1 -1
- package/bin/agent-cortex.mjs +29 -8
- package/bin/installers/claude.mjs +569 -105
- package/bin/installers/copilot.mjs +22 -12
- package/bin/installers/pi.mjs +37 -34
- package/docs/claude-hooks.md +3 -3
- package/docs/ideas/extension-manifests.md +75 -0
- package/docs/ideas/record-ideas-as-beads.md +115 -0
- package/docs/ideas/subagent-visibility.md +72 -0
- package/docs/ideas/task-session-context.md +89 -0
- package/docs/research/skill-design-research.md +4 -4
- package/docs/research/skill-improvements-analysis.md +1 -1
- package/docs/skills/skill-anatomy.md +38 -2
- package/docs/technical-direction/migration-execution-labels.md +132 -0
- package/extensions/agent-modes/README.md +3 -2
- package/extensions/agent-modes/discover.test.ts +30 -7
- package/extensions/agent-modes/discover.ts +1 -1
- package/extensions/skill-stats/index.test.ts +3 -2
- package/lib/cli.mjs +24 -6
- package/package.json +4 -4
- package/plugin.json +1 -1
- package/pnpm-workspace.yaml +1 -1
- package/scripts/build-copilot-agents.mjs +1 -1
- package/scripts/check-no-sync.mjs +49 -0
- package/scripts/lib/compose-agent.mjs +32 -14
- package/skills/engineering/design-an-interface/SKILL.md +78 -58
- package/skills/engineering/grill-with-docs/REFERENCE.md +78 -0
- package/skills/engineering/grill-with-docs/SKILL.md +66 -63
- package/skills/engineering/improve-codebase-architecture/SKILL.md +66 -48
- package/skills/engineering/technical-direction/FORMAT.md +38 -0
- package/skills/engineering/technical-direction/SKILL.md +70 -77
- package/skills/planning/classify-bead/SKILL.md +59 -35
- package/skills/planning/create-task/REFERENCE.md +40 -0
- package/skills/planning/create-task/SKILL.md +70 -66
- package/skills/planning/create-task/scripts/create-chores.ts +6 -1
- package/skills/planning/create-task/scripts/node_modules/.bin/tsc +21 -0
- package/skills/planning/create-task/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/planning/create-task/scripts/node_modules/.bin/tsx +21 -0
- package/skills/planning/prd-to-tasks/REFERENCE.md +66 -0
- package/skills/planning/prd-to-tasks/SKILL.md +86 -170
- package/skills/planning/record-idea/FORMAT.md +44 -0
- package/skills/planning/record-idea/SKILL.md +70 -53
- package/skills/planning/request-refactor-plan/FORMAT.md +45 -0
- package/skills/planning/request-refactor-plan/SKILL.md +57 -46
- package/skills/planning/write-a-prd/FORMAT.md +54 -0
- package/skills/planning/write-a-prd/SKILL.md +49 -48
- package/skills/planning/write-a-ticket/SKILL.md +68 -53
- package/skills/productivity/handoff/SKILL.md +12 -0
- package/skills/productivity/init-beads/SKILL.md +48 -40
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsc +21 -0
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsx +21 -0
- package/skills/productivity/write-a-skill/SKILL.md +2 -1
- package/skills/review/maintain-agent-docs/SKILL.md +71 -51
- package/skills/workflow/hitl-collab/SKILL.md +86 -17
- package/skills/workflow/ralph/REFERENCE.md +22 -17
- package/skills/workflow/ralph/SKILL.md +88 -74
- package/skills/workflow/run-pipeline-stage/REFERENCE.md +22 -0
- package/skills/workflow/run-pipeline-stage/SKILL.md +91 -93
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +6 -107
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsc +21 -0
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsx +21 -0
- package/test/claude-installer.test.mjs +308 -0
- package/test/cli.test.mjs +40 -30
- package/test/copilot-installer.test.mjs +92 -82
- package/test/helpers/fake-claude.mjs +152 -0
- package/test/installer.test.mjs +309 -57
- package/test/pi-installer.test.mjs +115 -99
- package/token-map.README.md +21 -10
- package/token-map.json +7 -6
- package/.claude-plugin/marketplace.json +0 -16
- package/claude/.claude-plugin/plugin.json +0 -11
- package/claude/agents/plan.md +0 -58
- package/claude/agents/ralph-plan.md +0 -121
- package/claude/agents/ralph.md +0 -193
- package/claude/agents/strategy.md +0 -111
- package/claude/hooks/scripts/notify.mjs +0 -54
- package/claude/hooks.json +0 -38
- /package/{claude → claude-extras}/.mcp.json +0 -0
- /package/{claude → claude-extras}/scripts/statusline-command.sh +0 -0
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
//
|
|
31
31
|
// Zero dependencies so it runs on the CI Node and local Node alike.
|
|
32
32
|
|
|
33
|
-
import {
|
|
33
|
+
import { writeFile, mkdir, readdir, stat } from "node:fs/promises";
|
|
34
34
|
import { join, dirname } from "node:path";
|
|
35
35
|
import { fileURLToPath } from "node:url";
|
|
36
36
|
import { composeAgent } from "../../scripts/lib/compose-agent.mjs";
|
|
@@ -38,9 +38,17 @@ import { composeAgent } from "../../scripts/lib/compose-agent.mjs";
|
|
|
38
38
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
39
39
|
const DEFAULT_ROOT = join(MODULE_DIR, "..", "..");
|
|
40
40
|
|
|
41
|
-
function isDirectory(p) {
|
|
41
|
+
async function isDirectory(p) {
|
|
42
42
|
try {
|
|
43
|
-
return
|
|
43
|
+
return (await stat(p)).isDirectory();
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function isFile(p) {
|
|
50
|
+
try {
|
|
51
|
+
return (await stat(p)).isFile();
|
|
44
52
|
} catch {
|
|
45
53
|
return false;
|
|
46
54
|
}
|
|
@@ -71,19 +79,21 @@ function frontmatterYaml(name, fm) {
|
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
/** Compose agents from agents/<name>/; every composable dir must ship a copilot harness. */
|
|
74
|
-
function buildAgents(root) {
|
|
82
|
+
async function buildAgents(root) {
|
|
75
83
|
const files = [];
|
|
76
|
-
const entries =
|
|
84
|
+
const entries = (await readdir(join(root, "agents"), { withFileTypes: true })).sort((a, b) =>
|
|
85
|
+
byName(a.name, b.name),
|
|
86
|
+
);
|
|
77
87
|
|
|
78
88
|
for (const entry of entries) {
|
|
79
89
|
if (!entry.isDirectory()) continue; // skip generated *.agent.md flat files and README
|
|
80
90
|
const dir = join(root, "agents", entry.name);
|
|
81
|
-
if (!
|
|
82
|
-
if (!isDirectory(join(dir, "copilot")) || !
|
|
91
|
+
if (!(await isFile(join(dir, "agent.md")))) continue; // not a composable agent dir
|
|
92
|
+
if (!(await isDirectory(join(dir, "copilot"))) || !(await isFile(join(dir, "copilot", "frontmatter.json")))) {
|
|
83
93
|
throw new Error(`agent "${entry.name}": composable directory without copilot/frontmatter.json — define the copilot harness or exclude the agent`);
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
const fm = composeAgent(root, entry.name, "copilot");
|
|
96
|
+
const fm = await composeAgent(root, entry.name, "copilot");
|
|
87
97
|
files.push({
|
|
88
98
|
name: entry.name,
|
|
89
99
|
file: `${entry.name}.agent.md`,
|
|
@@ -105,9 +115,9 @@ function buildAgents(root) {
|
|
|
105
115
|
* @param {boolean} [options.dryRun] Plan and report without writing anything.
|
|
106
116
|
* @returns {{ output: string, agents: string[], dryRun: boolean }}
|
|
107
117
|
*/
|
|
108
|
-
export function installCopilot({ root = DEFAULT_ROOT, output, dryRun = false } = {}) {
|
|
118
|
+
export async function installCopilot({ root = DEFAULT_ROOT, output, dryRun = false } = {}) {
|
|
109
119
|
const out = output ?? join(root, "agents");
|
|
110
|
-
const files = buildAgents(root);
|
|
120
|
+
const files = await buildAgents(root);
|
|
111
121
|
const summary = {
|
|
112
122
|
output: out,
|
|
113
123
|
agents: files.map((f) => f.name),
|
|
@@ -120,9 +130,9 @@ export function installCopilot({ root = DEFAULT_ROOT, output, dryRun = false } =
|
|
|
120
130
|
return summary;
|
|
121
131
|
}
|
|
122
132
|
|
|
123
|
-
|
|
133
|
+
await mkdir(out, { recursive: true });
|
|
124
134
|
for (const { file, content } of files) {
|
|
125
|
-
|
|
135
|
+
await writeFile(join(out, file), content);
|
|
126
136
|
}
|
|
127
137
|
console.log(`Generated ${files.length} Copilot agent file(s): ${summary.agents.join(", ")}`);
|
|
128
138
|
return summary;
|
package/bin/installers/pi.mjs
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
// Composition per the token-map.json contract:
|
|
9
9
|
// 1. {{SECTION:name}} is resolved from the agent's pi/<name>.md section file
|
|
10
10
|
// (shared composer, scripts/lib/compose-agent.mjs).
|
|
11
|
-
// 2. {{TOOL:key}} is substituted with the pi column
|
|
12
|
-
//
|
|
11
|
+
// 2. {{TOOL:key}} is substituted with the pi column (pi maps ask_user →
|
|
12
|
+
// ask_questions and skill → read); any (future) null pi mapping drops the
|
|
13
|
+
// token from prose with a warning.
|
|
13
14
|
// 3. {{PATH:key}} named keys resolve through the paths table; bare relative
|
|
14
15
|
// paths resolve against the plugin root (default: token-map.json's pi value,
|
|
15
16
|
// overridable with --plugin-root for checkout/symlinked installs).
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
//
|
|
25
26
|
// Zero dependencies so it runs on the CI Node and local Node alike.
|
|
26
27
|
|
|
27
|
-
import {
|
|
28
|
+
import { readFile, writeFile, mkdir, copyFile, readdir, stat } from "node:fs/promises";
|
|
28
29
|
import { join, dirname } from "node:path";
|
|
29
30
|
import { fileURLToPath } from "node:url";
|
|
30
31
|
import { homedir } from "node:os";
|
|
@@ -37,22 +38,22 @@ const PI = "pi";
|
|
|
37
38
|
// extended before this installer can trust it.
|
|
38
39
|
const CONTRACT_VERSION = 1;
|
|
39
40
|
|
|
40
|
-
const
|
|
41
|
+
const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
41
42
|
const DEFAULT_OUTPUT = join(homedir(), ".pi", "agent");
|
|
42
43
|
|
|
43
44
|
const DEFAULT_WARN = (msg) => console.warn(`[pi-installer] ${msg}`);
|
|
44
45
|
|
|
45
|
-
function isDirectory(p) {
|
|
46
|
+
async function isDirectory(p) {
|
|
46
47
|
try {
|
|
47
|
-
return
|
|
48
|
+
return (await stat(p)).isDirectory();
|
|
48
49
|
} catch {
|
|
49
50
|
return false;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
function isFile(p) {
|
|
54
|
+
async function isFile(p) {
|
|
54
55
|
try {
|
|
55
|
-
return
|
|
56
|
+
return (await stat(p)).isFile();
|
|
56
57
|
} catch {
|
|
57
58
|
return false;
|
|
58
59
|
}
|
|
@@ -73,8 +74,8 @@ function isFile(p) {
|
|
|
73
74
|
* @returns {{ agents: {name:string, filePath:string}[], skills: {skills:number, md:number, files:number, dir:string},
|
|
74
75
|
* warnings: string[], dryRun: boolean, agentsDir: string, skillsDir: string }}
|
|
75
76
|
*/
|
|
76
|
-
export function installPi(options = {}) {
|
|
77
|
-
const root = options.root ??
|
|
77
|
+
export async function installPi(options = {}) {
|
|
78
|
+
const root = options.root ?? PACKAGE_ROOT;
|
|
78
79
|
const output = options.output ?? DEFAULT_OUTPUT;
|
|
79
80
|
const dryRun = options.dryRun ?? false;
|
|
80
81
|
const warnings = [];
|
|
@@ -83,7 +84,7 @@ export function installPi(options = {}) {
|
|
|
83
84
|
(options.warn ?? DEFAULT_WARN)(msg);
|
|
84
85
|
};
|
|
85
86
|
|
|
86
|
-
const tokenMap = loadTokenMap(root);
|
|
87
|
+
const tokenMap = await loadTokenMap(root);
|
|
87
88
|
if (typeof tokenMap.version === "number" && tokenMap.version > CONTRACT_VERSION) {
|
|
88
89
|
throw new Error(
|
|
89
90
|
`token-map.json version ${tokenMap.version} is newer than the contract version ${CONTRACT_VERSION} this installer implements — upgrade agent-cortex`,
|
|
@@ -94,26 +95,28 @@ export function installPi(options = {}) {
|
|
|
94
95
|
const agentsDir = join(output, "agents");
|
|
95
96
|
const skillsDir = join(output, "skills");
|
|
96
97
|
|
|
97
|
-
const agents = installAgents({ root, agentsDir, dryRun, pluginRoot, tokenMap, warn });
|
|
98
|
-
const skills = installSkills({ root, skillsDir, dryRun, pluginRoot, tokenMap, warn });
|
|
98
|
+
const agents = await installAgents({ root, agentsDir, dryRun, pluginRoot, tokenMap, warn });
|
|
99
|
+
const skills = await installSkills({ root, skillsDir, dryRun, pluginRoot, tokenMap, warn });
|
|
99
100
|
|
|
100
101
|
return { agents, skills, warnings, dryRun, agentsDir, skillsDir };
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
// ─── Agents ──────────────────────────────────────────────────────────────────
|
|
104
105
|
|
|
105
|
-
function installAgents({ root, agentsDir, dryRun, pluginRoot, tokenMap, warn }) {
|
|
106
|
+
async function installAgents({ root, agentsDir, dryRun, pluginRoot, tokenMap, warn }) {
|
|
106
107
|
const written = [];
|
|
107
108
|
const agentsSrc = join(root, "agents");
|
|
108
|
-
for (const entry of
|
|
109
|
+
for (const entry of (await readdir(agentsSrc, { withFileTypes: true })).sort((a, b) =>
|
|
110
|
+
a.name.localeCompare(b.name),
|
|
111
|
+
)) {
|
|
109
112
|
if (!entry.isDirectory()) continue; // skip generated *.agent.md flat files
|
|
110
113
|
const dir = join(agentsSrc, entry.name);
|
|
111
|
-
if (!isFile(join(dir, "agent.md"))) continue; // not a composable agent dir
|
|
112
|
-
if (!isDirectory(join(dir, PI)) || !isFile(join(dir, PI, "frontmatter.json"))) {
|
|
114
|
+
if (!(await isFile(join(dir, "agent.md")))) continue; // not a composable agent dir
|
|
115
|
+
if (!(await isDirectory(join(dir, PI))) || !(await isFile(join(dir, PI, "frontmatter.json")))) {
|
|
113
116
|
throw new Error(`agent "${entry.name}": composable directory without pi/frontmatter.json — define the pi harness or exclude the agent`);
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
const fm = composeAgent(root, entry.name, PI, {
|
|
119
|
+
const fm = await composeAgent(root, entry.name, PI, {
|
|
117
120
|
dropNullTools: true,
|
|
118
121
|
pluginRoot,
|
|
119
122
|
resolveRelativePaths: true,
|
|
@@ -123,8 +126,8 @@ function installAgents({ root, agentsDir, dryRun, pluginRoot, tokenMap, warn })
|
|
|
123
126
|
const content = renderPiAgent(entry.name, fm, tools);
|
|
124
127
|
const filePath = join(agentsDir, `${entry.name}.agent.md`);
|
|
125
128
|
if (!dryRun) {
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
await mkdir(agentsDir, { recursive: true });
|
|
130
|
+
await writeFile(filePath, content);
|
|
128
131
|
}
|
|
129
132
|
written.push({ name: entry.name, filePath });
|
|
130
133
|
}
|
|
@@ -147,24 +150,24 @@ function renderPiAgent(name, fm, tools) {
|
|
|
147
150
|
|
|
148
151
|
// ─── Skills ──────────────────────────────────────────────────────────────────
|
|
149
152
|
|
|
150
|
-
function installSkills({ root, skillsDir, dryRun, pluginRoot, tokenMap, warn }) {
|
|
153
|
+
async function installSkills({ root, skillsDir, dryRun, pluginRoot, tokenMap, warn }) {
|
|
151
154
|
const skillsSrc = join(root, "skills");
|
|
152
|
-
if (!isDirectory(skillsSrc)) return { skills: 0, md: 0, files: 0, dir: skillsDir };
|
|
155
|
+
if (!(await isDirectory(skillsSrc))) return { skills: 0, md: 0, files: 0, dir: skillsDir };
|
|
153
156
|
|
|
154
157
|
const transform = (content) =>
|
|
155
158
|
substituteTokens(content, PI, tokenMap, { dropNullTools: true, pluginRoot, resolveRelativePaths: true, warn });
|
|
156
159
|
|
|
157
|
-
if (!dryRun)
|
|
160
|
+
if (!dryRun) await mkdir(skillsDir, { recursive: true });
|
|
158
161
|
let skills = 0;
|
|
159
162
|
let md = 0;
|
|
160
163
|
let files = 0;
|
|
161
|
-
for (const group of
|
|
164
|
+
for (const group of (await readdir(skillsSrc)).sort()) {
|
|
162
165
|
const groupDir = join(skillsSrc, group);
|
|
163
|
-
if (!isDirectory(groupDir)) continue;
|
|
164
|
-
for (const name of
|
|
165
|
-
if (!isFile(join(groupDir, name, "SKILL.md"))) continue;
|
|
166
|
+
if (!(await isDirectory(groupDir))) continue;
|
|
167
|
+
for (const name of (await readdir(groupDir)).sort()) {
|
|
168
|
+
if (!(await isFile(join(groupDir, name, "SKILL.md")))) continue;
|
|
166
169
|
skills += 1;
|
|
167
|
-
const stats = copyTree(join(groupDir, name), join(skillsDir, group, name), transform, dryRun);
|
|
170
|
+
const stats = await copyTree(join(groupDir, name), join(skillsDir, group, name), transform, dryRun);
|
|
168
171
|
md += stats.md;
|
|
169
172
|
files += stats.files;
|
|
170
173
|
}
|
|
@@ -173,24 +176,24 @@ function installSkills({ root, skillsDir, dryRun, pluginRoot, tokenMap, warn })
|
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
/** Recursively copy a tree; transform .md file contents, copy everything else verbatim. */
|
|
176
|
-
function copyTree(src, dest, transform, dryRun) {
|
|
179
|
+
async function copyTree(src, dest, transform, dryRun) {
|
|
177
180
|
let md = 0;
|
|
178
181
|
let files = 0;
|
|
179
|
-
const entries =
|
|
182
|
+
const entries = await readdir(src, { withFileTypes: true });
|
|
180
183
|
for (const entry of entries) {
|
|
181
184
|
const from = join(src, entry.name);
|
|
182
185
|
const to = join(dest, entry.name);
|
|
183
186
|
if (entry.isDirectory()) {
|
|
184
|
-
const stats = copyTree(from, to, transform, dryRun);
|
|
187
|
+
const stats = await copyTree(from, to, transform, dryRun);
|
|
185
188
|
md += stats.md;
|
|
186
189
|
files += stats.files;
|
|
187
190
|
} else if (entry.isFile()) {
|
|
188
191
|
files += 1;
|
|
189
192
|
if (entry.name.endsWith(".md")) md += 1;
|
|
190
193
|
if (dryRun) continue;
|
|
191
|
-
|
|
192
|
-
if (entry.name.endsWith(".md"))
|
|
193
|
-
else
|
|
194
|
+
await mkdir(dest, { recursive: true });
|
|
195
|
+
if (entry.name.endsWith(".md")) await writeFile(to, transform(await readFile(from, "utf-8")));
|
|
196
|
+
else await copyFile(from, to);
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
return { md, files };
|
package/docs/claude-hooks.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The pi extensions in `extensions/` were audited for Claude Code equivalents.
|
|
4
4
|
Implemented ports live in `hooks/claude/hooks.json` (copied verbatim into the
|
|
5
|
-
|
|
6
|
-
`hooks/claude/scripts/` and are bundled into `
|
|
5
|
+
materialised plugin as its `hooks.json`); support scripts live in
|
|
6
|
+
`hooks/claude/scripts/` and are bundled into the plugin's `hooks/scripts/` by
|
|
7
7
|
`bin/installers/claude.mjs` (referenced from hooks.json via `$CLAUDE_PLUGIN_ROOT`).
|
|
8
8
|
|
|
9
9
|
Claude Code's hook model differs from PI's: hooks are shell commands fed a JSON
|
|
@@ -100,7 +100,7 @@ for little signal. Rejected; Claude Code ships its own usage analytics
|
|
|
100
100
|
## `subagent/` → Reject (native)
|
|
101
101
|
|
|
102
102
|
pi's `subagent` tool spawns isolated `pi --mode json` processes. Claude Code has
|
|
103
|
-
native subagents — the plugin already ships
|
|
103
|
+
native subagents — the plugin already ships `~/.agent-cortex/claude/agents/*.md` (including
|
|
104
104
|
`ralph`, `plan`, `strategy`, `ralph-plan`) executed via the built-in Agent/Task
|
|
105
105
|
tools with per-session context isolation — so a hook-based workaround would be
|
|
106
106
|
strictly worse.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Idea: extension-manifests
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Backlog idea (not implementation-ready)
|
|
5
|
+
|
|
6
|
+
## Created
|
|
7
|
+
2026-08-25
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
PI extensions and Claude/Copilot plugins are installed individually (`pi install <ext>`) and
|
|
11
|
+
live implicit in the machine's state (`~/.pi/agent/extensions/`) with no declared manifest of
|
|
12
|
+
what the author uses or where it came from. A fresh machine, clean `~/.pi`, or a failed update
|
|
13
|
+
leaves the environment without the expected extensions. The toolset isn't reproducible and
|
|
14
|
+
isn't documented anywhere in the author's repos. Experimenting with an extension (install, try,
|
|
15
|
+
remove) is also all manual, and there's no way to uninstall cleanly.
|
|
16
|
+
|
|
17
|
+
## Who benefits
|
|
18
|
+
The author. Installing/updating agent-cortex becomes a reliable way to restore a known PI +
|
|
19
|
+
Claude environment (agent-cortex + declared extensions in one step). The manifests document and
|
|
20
|
+
reproduce the toolset across machines. A prune CLI makes extension experimentation fast and safe.
|
|
21
|
+
|
|
22
|
+
## Proposed outcome
|
|
23
|
+
agent-cortex ships **committed extension manifests** (reviewed and stored on GitHub) declaring
|
|
24
|
+
which extensions to install — **per harness**: one manifest for PI extensions, one for
|
|
25
|
+
Claude/Copilot plugins. On install or update of agent-cortex, it reads the manifests and
|
|
26
|
+
installs the declared extensions. The manifests are the single source of truth.
|
|
27
|
+
|
|
28
|
+
Key decisions from the interview:
|
|
29
|
+
|
|
30
|
+
1. **No monitoring** — nothing observes installs, and the CLI never writes the manifests.
|
|
31
|
+
Adding an extension = edit the manifest, commit it, ship it. This keeps the source of truth
|
|
32
|
+
in GitHub where it belongs (and gets the usual PR/review flow).
|
|
33
|
+
2. **Per-harness manifests** — separate records for the pi harness vs the Claude harness, each
|
|
34
|
+
carrying the extension source (git URL / package name) for that harness's installer. The
|
|
35
|
+
install-on-update path handles each harness with its own mechanism.
|
|
36
|
+
3. **Prune CLI with a TUI** — a CLI command (e.g. `agent-cortex ext prune`) opens an interactive
|
|
37
|
+
TUI listing locally-installed extensions; selecting one **uninstalls** it from the local
|
|
38
|
+
environment. Removing from the manifest is done manually on GitHub. This supports the
|
|
39
|
+
experimentation loop: install → try → prune locally, then curate the manifest separately.
|
|
40
|
+
|
|
41
|
+
agent-cortex's own bundled extensions (auto-discovered via `pi install`, e.g. `skill-stats`)
|
|
42
|
+
are deliberately excluded from the manifests — only third-party extensions are declared.
|
|
43
|
+
|
|
44
|
+
## Validity check
|
|
45
|
+
- Evidence we already have: agent-cortex already has an install surface to hang this on
|
|
46
|
+
(`pi install` package discovery for the pi harness, plus the existing `bin/agent-cortex.mjs`
|
|
47
|
+
install command and `postinstall` script). The repo already carries a `plugin.json` (Claude
|
|
48
|
+
harness) alongside `package.json` (pi harness), showing the per-harness split is natural.
|
|
49
|
+
- Riskiest assumption: that an automated install-on-update of declared extensions is safe and
|
|
50
|
+
desirable (auto-installing on every update could surprise, or fail mid-flight on a new
|
|
51
|
+
machine lacking auth/network). Also, the TUI prune needs the local extension store's shape
|
|
52
|
+
(`~/.pi/agent/extensions/` for pi; whatever Claude uses) to be introspectable.
|
|
53
|
+
- What would invalidate this idea: if auto-install-on-update proves too disruptive (better as
|
|
54
|
+
an explicit `agent-cortex ext install` command), or if the pi/Claude installers don't expose
|
|
55
|
+
the store in a way that supports listing + uninstall for the TUI.
|
|
56
|
+
|
|
57
|
+
## Constraints
|
|
58
|
+
- Manifests live in this repo, committed via the normal PR flow — the CLI never edits them.
|
|
59
|
+
- Install-on-update must be idempotent and safe to skip/fail gracefully (no hard breakage of
|
|
60
|
+
agent-cortex's own install on extension failure).
|
|
61
|
+
- Follow the repo's extension conventions where relevant (lightweight, no internal LLM calls).
|
|
62
|
+
- If any local data is persisted (e.g. prune history), write to `~/.pi/agent-cortex/`.
|
|
63
|
+
|
|
64
|
+
## Next validation step
|
|
65
|
+
Confirm the install surface for each harness: how `pi install <source>` works for the pi side,
|
|
66
|
+
and how Claude/Copilot plugins get installed, plus whether each store can be listed and
|
|
67
|
+
uninstalled programmatically (needed for the prune TUI). Then prototype the manifest + one
|
|
68
|
+
harness's install-on-update path.
|
|
69
|
+
|
|
70
|
+
## Notes
|
|
71
|
+
Recorded 2026-08-25. The idea was refined during the interview: initially framed as
|
|
72
|
+
"record the extensions I use" (observer-based), corrected to a **committed manifest** model —
|
|
73
|
+
recording happens by editing + committing, not by monitoring. Prune uninstalls locally only;
|
|
74
|
+
the manifest stays GitHub-managed. This idea is adjacent to `record-ideas-as-beads`: both make
|
|
75
|
+
agent-cortex the declared source of truth for the author's environment and workflow.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Idea: record-ideas-as-beads
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Fleshed out 2026-08-25 — design decisions locked in an interview; not yet implemented.
|
|
5
|
+
|
|
6
|
+
## Created
|
|
7
|
+
2026-08-25
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
Ideas currently live as loose markdown files in `docs/ideas/`. This sits awkwardly alongside
|
|
11
|
+
the rest of the workflow, which is almost entirely bead-based (bd). Because ideas aren't beads,
|
|
12
|
+
they can't be searched with `bd label`, can't express relationships/dependencies to real tasks,
|
|
13
|
+
can't be given priority that surfaces alongside other work, and can't sync to remote via
|
|
14
|
+
`bd dolt push`. There's no clean promotion path from "idea" to "epic" to "executable task".
|
|
15
|
+
|
|
16
|
+
## Who benefits
|
|
17
|
+
The author's daily planning loop. Ideas are the beginning of epics, so making them first-class
|
|
18
|
+
beads gives a single coherent backlog where an idea can grow relationships to the tasks it
|
|
19
|
+
spawns. The plan/agent-nexus agents benefit too: agent-nexus will eventually schedule work
|
|
20
|
+
through planning stages (not just execution), and a beads-native idea record gives it a clean
|
|
21
|
+
input to plan against.
|
|
22
|
+
|
|
23
|
+
## Proposed outcome
|
|
24
|
+
Record ideas as beads labelled `kind:idea`, replacing `docs/ideas/*.md` entirely (bead-only —
|
|
25
|
+
files deleted after migration). `bd` already supports labels natively (`bd create -l`,
|
|
26
|
+
`bd label add/list`). An idea bead maps directly to an epic; promoting it means spawning task
|
|
27
|
+
beads as children and letting the idea bead become the epic node.
|
|
28
|
+
|
|
29
|
+
## Fleshed-out design (decided 2026-08-25)
|
|
30
|
+
|
|
31
|
+
### Label & identification
|
|
32
|
+
- **`kind:idea` label** marks idea beads. Ideas do NOT use `deferred` status — they stay
|
|
33
|
+
`open` so they're visible to idea tooling; hiding from actionable work is done by exclusion,
|
|
34
|
+
not status.
|
|
35
|
+
- **ralph excludes them**: ready queries use `bd ready --exclude-label kind:idea`
|
|
36
|
+
(verified: `bd ready` supports `--exclude-label`). Idea beads never appear as claimable work.
|
|
37
|
+
- Optional companion labels: `priority:<0-4>`, `epic:<id>` once promoted.
|
|
38
|
+
|
|
39
|
+
### Flesh-out workflow (the skill that consumes them)
|
|
40
|
+
There should be a **flesh-out skill** (e.g. `flesh-out-idea`) that answers: *"which idea beads
|
|
41
|
+
are ready to be fleshed out?"* This is `bd ready -l kind:idea` — the blocker-aware ready query
|
|
42
|
+
scoped to ideas. Because `bd ready` already respects dependencies, an idea bead that
|
|
43
|
+
`depends-on` in-flight work (e.g. "needs unified-ci-pipeline landed first") naturally shows as
|
|
44
|
+
*not ready* until its deps close. That's exactly the semantics wanted:
|
|
45
|
+
- `bd ready -l kind:idea` → list & pick an idea ready for fleshing.
|
|
46
|
+
- The skill runs the record-idea-style interview (why / how / when / priority) at deeper depth,
|
|
47
|
+
updating the bead's description/design/notes as the idea ripens.
|
|
48
|
+
- Once fleshed out enough, the idea can be promoted (below).
|
|
49
|
+
|
|
50
|
+
### Promotion path: idea → epic → tasks
|
|
51
|
+
Parent-child hierarchy (chosen over labels+deps only):
|
|
52
|
+
1. Idea bead starts with `kind:idea`, type defaulted appropriately (still `task` type, or set
|
|
53
|
+
`epic` type on promotion).
|
|
54
|
+
2. On promotion: `bd label add <idea> epic:<idea-id>` (or flip to an epic label), then spawn
|
|
55
|
+
task beads with `--parent <idea-id>` — children inherit the epic relationship natively.
|
|
56
|
+
3. The idea bead becomes the epic node; its children are the executable tasks. Closing the
|
|
57
|
+
children resolves to the epic closing.
|
|
58
|
+
|
|
59
|
+
### Content model (bead fields)
|
|
60
|
+
Map the current idea-template sections onto bd fields:
|
|
61
|
+
| md template field | bd field |
|
|
62
|
+
|---|---|
|
|
63
|
+
| Title | `--title` |
|
|
64
|
+
| Problem / Why | `--description` |
|
|
65
|
+
| How we might do it | `--design` |
|
|
66
|
+
| When / Priority / Validity / Constraints / Notes | `--notes` (structured, keep section markers) |
|
|
67
|
+
| anything referential | `--context` |
|
|
68
|
+
|
|
69
|
+
Multiple sections per field use explicit markers (`## Validity check`, etc.) inside the field
|
|
70
|
+
so the flesh-out interview can find/update them later.
|
|
71
|
+
|
|
72
|
+
### Skill changes
|
|
73
|
+
- **`record-idea`**: replace scaffold-file flow (`new-idea.sh` → `docs/ideas/x.md`) with bead
|
|
74
|
+
creation: interview → `bd create "<title>" -l kind:idea -d "<why>" --design "<how>"
|
|
75
|
+
--notes "<when/priority/validity>"`. Keep the interview; drop the markdown scaffold script.
|
|
76
|
+
- New **`flesh-out-idea`** skill (see above) — validates readiness (`bd ready -l kind:idea`),
|
|
77
|
+
picks an idea, drives the deepening interview, updates the bead, optionally promotes.
|
|
78
|
+
|
|
79
|
+
### Migration
|
|
80
|
+
- Bulk-migrate the existing `docs/ideas/*.md` records to beads: read each file, map sections to
|
|
81
|
+
bd fields, `bd create -l kind:idea`, preserve priority. Run as a one-off (manual or scripted).
|
|
82
|
+
- Then **delete `docs/ideas/`** — bead-only going forward.
|
|
83
|
+
- Update `AGENTS.md` + any stale references that point at `docs/ideas/`.
|
|
84
|
+
- The `record-idea` skill itself must unlearn the docs/ideas path.
|
|
85
|
+
|
|
86
|
+
## Validity check
|
|
87
|
+
- Evidence we already have: `bd ready --exclude-label` and `bd ready -l` both exist and compose
|
|
88
|
+
(label filtering + blocker-aware ready semantics) — the two core mechanisms this idea needs
|
|
89
|
+
are native, no feature build. `--parent` exists for the hierarchy. 9-10 idea files exist to
|
|
90
|
+
migrate; the record-idea skill and its script are the only two consumers of the file flow.
|
|
91
|
+
- Riskiest assumption: that keeping ideas `open` (not `deferred`) + label exclusion is
|
|
92
|
+
discoverable enough — ralph, plan agents, and the author must remember the exclusion. The
|
|
93
|
+
`bd-tool` skill's labels table needs `kind:idea` documented with the exclusion convention.
|
|
94
|
+
- What would invalidate this idea: if label-based exclusion leaks idea beads into `bd ready`
|
|
95
|
+
via some path (e.g. `bd ready` without the exclude flag), or if losing the scannable
|
|
96
|
+
`docs/ideas/` directory hurts occasional review more than bead queries help it.
|
|
97
|
+
|
|
98
|
+
## Constraints
|
|
99
|
+
- Ideas stay quick to scan: `bd list -l kind:idea` + `bd show <id>` should be a comfortable
|
|
100
|
+
replacement for opening the directory.
|
|
101
|
+
- Idea beads must never appear in ralph's actionable-ready view.
|
|
102
|
+
- `record-idea` and `bd-tool` skills stay consistent — no stale references to docs/ideas.
|
|
103
|
+
- Priority of ideas uses the same P0-P4 scale as tasks (P4 = backlog default for ideas).
|
|
104
|
+
|
|
105
|
+
## Next validation step
|
|
106
|
+
Prototype one idea as a labelled bead: create it with `-l kind:idea`, confirm `bd ready`
|
|
107
|
+
excludes it by default and `bd ready -l kind:idea` surfaces it; then promote it (add epic label,
|
|
108
|
+
spawn a child task) to confirm the hierarchy reads correctly. If the prototype passes, do the
|
|
109
|
+
bulk migration + skill updates.
|
|
110
|
+
|
|
111
|
+
## Notes
|
|
112
|
+
Interview on 2026-08-25 locked: labels over status (kind:idea + ralph exclusion), bead-only
|
|
113
|
+
content (files deleted), parent-child promotion, and record-idea skill rewritten to create
|
|
114
|
+
beads. Agent-nexus is the planned consumer. Once this lands, this very record becomes an
|
|
115
|
+
idea-bead (and then this file is deleted — the migration eats its own tail).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Idea: subagent-visibility
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Backlog idea (not implementation-ready)
|
|
5
|
+
|
|
6
|
+
## Created
|
|
7
|
+
2026-08-25
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
The bundled `subagent` extension delegates work to separate `pi` processes with isolated
|
|
11
|
+
context windows. It streams output live, shows per-agent usage stats (turns, tokens, cost), and
|
|
12
|
+
supports abort — but after a run there's no retained record of what each subagent actually did
|
|
13
|
+
(files touched, decisions, blockers), and while a run is in flight there's no richer
|
|
14
|
+
dashboard-level view of what each agent is up to. There's also no way to influence a running
|
|
15
|
+
subagent: you can only watch or Ctrl+C the whole thing. For the ralph-style parallel dispatches
|
|
16
|
+
(up to 5 concurrent chores) this is a real blind spot.
|
|
17
|
+
|
|
18
|
+
## Who benefits
|
|
19
|
+
The author, whenever running parallel subagent work (ralph pipeline chores, parallel research).
|
|
20
|
+
A live dashboard helps during runs; persisted per-run reports turn subagent work into a
|
|
21
|
+
reviewable after-action record (which also complements the HITL/summary flow). Mid-run steering
|
|
22
|
+
reduces wasted tokens from subagents heading the wrong way and having to restart.
|
|
23
|
+
|
|
24
|
+
## Proposed outcome
|
|
25
|
+
Expand (or adopt, if a store extension fits) subagent tooling to give:
|
|
26
|
+
|
|
27
|
+
1. **Live dashboard** — richer TUI during runs: per-agent status (phase, current tool call,
|
|
28
|
+
files touched), so you can see what each parallel subagent is doing without digging into
|
|
29
|
+
streamed output.
|
|
30
|
+
2. **Persisted reports** — a per-run record per subagent (what it did, files changed,
|
|
31
|
+
decisions, blockers), stored for after-action review. Persistence should follow the repo
|
|
32
|
+
convention: write to `~/.pi/agent-cortex/`, tagged with project path for per-project slicing.
|
|
33
|
+
3. **Mid-run steering** — send a message to a running subagent to change its direction
|
|
34
|
+
("skip that, focus on X") rather than killing and restarting.
|
|
35
|
+
|
|
36
|
+
Decision from the interview: **evaluate the pi extension store first** — if a maintained
|
|
37
|
+
extension already covers dashboard + reports (and ideally steering), adopt it; otherwise expand
|
|
38
|
+
the bundled `subagent` extension. Building is a fallback, not the default.
|
|
39
|
+
|
|
40
|
+
## Validity check
|
|
41
|
+
- Evidence we already have: the bundled `subagent` extension is a working base — it already
|
|
42
|
+
spawns `pi` subprocesses, streams, and collects usage data, so the hooks for a dashboard and
|
|
43
|
+
reports exist in some form. The repo has a data convention (`~/.pi/agent-cortex/`, per-project
|
|
44
|
+
tagging) that reports would slot into.
|
|
45
|
+
- Riskiest assumption: that mid-run steering is technically feasible — subagents run as separate
|
|
46
|
+
`pi` processes, so steering likely needs a message channel (e.g. a FIFO / IPC pipe into the
|
|
47
|
+
running process, or a PI-native way to inject input). If the process model doesn't allow input
|
|
48
|
+
mid-run, the interaction half collapses to "abort and re-dispatch with corrected instruction".
|
|
49
|
+
- What would invalidate this idea: if store extensions are all visibility-only (no steering) and
|
|
50
|
+
the process model rules out mid-run input, the remaining value is dashboard + reports only.
|
|
51
|
+
Also, if subagents use private pipes that block reading live state cheaply, the dashboard may
|
|
52
|
+
be constrained to what the streamer already shows.
|
|
53
|
+
|
|
54
|
+
## Constraints
|
|
55
|
+
- Keep it lightweight and consistent with the repo's extension conventions (no internal LLM
|
|
56
|
+
calls in the extension itself).
|
|
57
|
+
- Should compose with ralph's parallel dispatch (up to 5 concurrent chores) without making the
|
|
58
|
+
TUI unusable.
|
|
59
|
+
- Steering must be safe: a message is advisory input to the subagent, not a force-kill;
|
|
60
|
+
abort stays available.
|
|
61
|
+
|
|
62
|
+
## Next validation step
|
|
63
|
+
Two-part check before building: (1) search the pi extension store for subagent/dashboard/steering
|
|
64
|
+
extensions and evaluate against this wishlist; (2) verify whether a running `pi` subagent
|
|
65
|
+
process accepts input mid-run (checked against how the subagent extension spawns processes and
|
|
66
|
+
whether PI exposes any IPC/input channel) — this decides whether steering is scoped in.
|
|
67
|
+
|
|
68
|
+
## Notes
|
|
69
|
+
Recorded 2026-08-25. Interview decisions: visibility = both live dashboard AND persisted
|
|
70
|
+
per-run reports; interaction = mid-run steering (not approve-gates, not pause/resume); path =
|
|
71
|
+
evaluate store first, fall back to expanding the bundled `subagent` extension. Complements
|
|
72
|
+
`unified-ci-pipeline` (pipeline visibility) and the ralph parallelism work in this repo.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Idea: task-session-context
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Backlog idea (not implementation-ready)
|
|
5
|
+
|
|
6
|
+
## Created
|
|
7
|
+
2026-08-25
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
Coding sessions accumulate context turn by turn: every question, every tool call, every
|
|
11
|
+
tangent stays in the window until it's manually compacted or the session is restarted. Keeping
|
|
12
|
+
the context small and relevant is an active management burden — the author has to notice the
|
|
13
|
+
bloat, decide what matters, and intervene. Long conversations either burn tokens or require
|
|
14
|
+
frequent manual resets that drop useful memory.
|
|
15
|
+
|
|
16
|
+
## Who benefits
|
|
17
|
+
The author, daily. Removing context management from the loop means sessions stay small and
|
|
18
|
+
focused no matter how long the overall thread runs. It also produces a durable, reviewable log
|
|
19
|
+
of work: each task's bead + summary memory is an audit trail of what was done and why.
|
|
20
|
+
|
|
21
|
+
## Proposed outcome
|
|
22
|
+
A workflow organised around **tasks** instead of sessions. Whenever the user does something
|
|
23
|
+
discrete — asks a new question, records an idea, fleshes out a piece of work — it **begins a
|
|
24
|
+
task**:
|
|
25
|
+
|
|
26
|
+
1. **Task = blank session with memory context.** The task starts a fresh, self-contained
|
|
27
|
+
session. It does NOT get every turn and tool call of the parent conversation — only access
|
|
28
|
+
to the accumulated **memories** of what came before (a summary/compressed view, not the raw
|
|
29
|
+
transcript).
|
|
30
|
+
2. **Self-contained execution.** The task works on its own: it takes action, and **records
|
|
31
|
+
memories along the way** as it produces outcomes.
|
|
32
|
+
3. **Single summary memory on completion.** The last thing a task does is write one summary
|
|
33
|
+
memory capturing its outcome. These memories are additive — the running memory store grows as
|
|
34
|
+
tasks complete.
|
|
35
|
+
4. **Fresh session continues the thread.** Once the task completes, a new session starts with
|
|
36
|
+
access to the memories — including the new summary — so to the user it feels like one
|
|
37
|
+
continuous thread, but each underlying session stays small.
|
|
38
|
+
|
|
39
|
+
**Ties into beads (bd):** "the completion of a bead is the completion of a task". A bead becomes
|
|
40
|
+
the log of work completed: the task's outcome is recorded on/with the bead, the fresh session
|
|
41
|
+
starts, and the bead is accompanied by **referential memory** (a pointer/memory entry that links
|
|
42
|
+
the outcome to the bead). So the bead doubles as the durable record AND the context-boundary
|
|
43
|
+
marker: starting a bead is the trigger for task-session separation.
|
|
44
|
+
|
|
45
|
+
**The bead is the artifact — the session is disposable.** Once a task is complete, the whole
|
|
46
|
+
conversation context is no longer needed; the bead is the artifact. The current conversation is
|
|
47
|
+
the live example: recording this idea is a task, and when it's done the transcript of every turn
|
|
48
|
+
and tool call can be discarded — what remains is the record plus its summary/referential memory.
|
|
49
|
+
This is the load-bearing philosophical point of the idea: sessions exist to serve tasks, not the
|
|
50
|
+
other way around. Context is an implementation detail of a single task; the bead is the durable
|
|
51
|
+
unit of history.
|
|
52
|
+
|
|
53
|
+
The mechanism likely needs: a memory store (per-project, e.g. under `~/.pi/agent-cortex/` or a
|
|
54
|
+
records convention), a session-scoping rule (what memories a fresh task session is seeded with),
|
|
55
|
+
the summary-writing step, and the bead ↔ memory linkage.
|
|
56
|
+
|
|
57
|
+
## Validity check
|
|
58
|
+
- Evidence we already have: the repo already runs on beads as the unit of work (bd), and the
|
|
59
|
+
ralph pipeline already treats beads as self-contained executable units — so task-per-bead
|
|
60
|
+
separation is a natural extension of an existing pattern. Existing ideas
|
|
61
|
+
(`record-ideas-as-beads`, `pi-task-memory`, `extension-manifests`) all push in the direction of
|
|
62
|
+
making agent-cortex the declared, memory-rich source of truth.
|
|
63
|
+
- Riskiest assumption: that a fresh session seeded with *memories only* (no raw transcript) is
|
|
64
|
+
sufficient context for a task — the compression of a conversation into memories must not lose
|
|
65
|
+
the specifics a task needs. Also: whether the harness (pi/Claude) even supports programmatic
|
|
66
|
+
session spawning with a seed context cleanly enough for this to feel seamless.
|
|
67
|
+
- What would invalidate this idea: if memory-as-context proves lossy in a way that keeps tasks
|
|
68
|
+
mis-executing (then the blank-session model needs the raw transcript after all, defeating the
|
|
69
|
+
point); or if the session boundary machinery (start/stop/spawn with seed) fights the harness.
|
|
70
|
+
|
|
71
|
+
## Constraints
|
|
72
|
+
- Sessions must stay small — this is the whole point; memory is the interface, not the transcript.
|
|
73
|
+
- Memories are additive and durable; the summary memory is the handoff contract between tasks.
|
|
74
|
+
- The bead is the work log AND the context boundary: no task completion without its summary
|
|
75
|
+
memory and bead record.
|
|
76
|
+
- Must not break the existing task loops (ralph pipeline stages, HITL handoffs) — it should
|
|
77
|
+
compose with them, not fork them.
|
|
78
|
+
|
|
79
|
+
## Next validation step
|
|
80
|
+
Flesh-out session (proposed by the author): nail down the trigger rules (what counts as "begin a
|
|
81
|
+
task"), the memory store schema and what a "memory" is vs a summary, how a fresh session gets
|
|
82
|
+
seeded, and how the bead carries the summary + referential memory. Then a spike: one task
|
|
83
|
+
completing with summary → fresh session seeded → verify the thread feels continuous.
|
|
84
|
+
|
|
85
|
+
## Notes
|
|
86
|
+
Recorded 2026-08-25. The author explicitly wants to flesh this out later — this record captures
|
|
87
|
+
the working concept. It connects several existing ideas: `record-ideas-as-beads` (beads as the
|
|
88
|
+
unit of everything), `pi-task-memory` (memory as a first-class mechanism), and
|
|
89
|
+
`subagent-visibility` (visibility into what task sessions do).
|