create-walle 0.9.3 → 0.9.4

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 (75) hide show
  1. package/README.md +2 -1
  2. package/package.json +1 -1
  3. package/template/claude-task-manager/db.js +5 -1
  4. package/template/claude-task-manager/public/css/walle.css +317 -0
  5. package/template/claude-task-manager/public/index.html +404 -101
  6. package/template/claude-task-manager/public/js/walle.js +1256 -86
  7. package/template/claude-task-manager/server.js +189 -14
  8. package/template/docs/site/api/README.md +146 -0
  9. package/template/docs/site/skills/README.md +99 -5
  10. package/template/package.json +1 -1
  11. package/template/wall-e/agent.js +54 -0
  12. package/template/wall-e/api-walle.js +452 -3
  13. package/template/wall-e/brain.js +45 -1
  14. package/template/wall-e/channels/telegram-channel.js +96 -0
  15. package/template/wall-e/chat.js +61 -2
  16. package/template/wall-e/coding-context.js +252 -0
  17. package/template/wall-e/coding-orchestrator.js +625 -0
  18. package/template/wall-e/coding-review.js +189 -0
  19. package/template/wall-e/core-tasks.js +12 -3
  20. package/template/wall-e/deploy.sh +4 -4
  21. package/template/wall-e/fly.toml +2 -2
  22. package/template/wall-e/package.json +4 -1
  23. package/template/wall-e/skills/_bundled/coding-agent/SKILL.md +17 -0
  24. package/template/wall-e/skills/_bundled/coding-agent/run.js +142 -0
  25. package/template/wall-e/skills/_bundled/email-sync/SKILL.md +12 -7
  26. package/template/wall-e/skills/_bundled/email-sync/mail-reader.jxa +76 -46
  27. package/template/wall-e/skills/_bundled/email-sync/run.js +42 -2
  28. package/template/wall-e/skills/_bundled/glean-team-sync/SKILL.md +57 -0
  29. package/template/wall-e/skills/_bundled/glean-team-sync/run.js +254 -0
  30. package/template/wall-e/skills/_bundled/slack-mentions/SKILL.md +1 -1
  31. package/template/wall-e/skills/_bundled/slack-mentions/run.js +268 -121
  32. package/template/wall-e/skills/_templates/data-fetcher.md +27 -0
  33. package/template/wall-e/skills/_templates/manual-action.md +19 -0
  34. package/template/wall-e/skills/_templates/periodic-checker.md +29 -0
  35. package/template/wall-e/skills/_templates/script-runner.md +21 -0
  36. package/template/wall-e/skills/claude-code-reader.js +16 -4
  37. package/template/wall-e/skills/skill-executor.js +23 -1
  38. package/template/wall-e/skills/skill-validator.js +73 -0
  39. package/template/wall-e/tests/brain.test.js +3 -3
  40. package/template/wall-e/tests/coding-agent-integration.test.js +240 -0
  41. package/template/wall-e/tests/coding-context.test.js +212 -0
  42. package/template/wall-e/tests/coding-orchestrator.test.js +303 -0
  43. package/template/wall-e/tests/coding-review.test.js +141 -0
  44. package/template/claude-task-manager/package-lock.json +0 -1607
  45. package/template/claude-task-manager/tests/test-ai-search.js +0 -61
  46. package/template/claude-task-manager/tests/test-editor-ux.js +0 -76
  47. package/template/claude-task-manager/tests/test-editor-ux2.js +0 -51
  48. package/template/claude-task-manager/tests/test-features-v2.js +0 -127
  49. package/template/claude-task-manager/tests/test-insights-cached.js +0 -78
  50. package/template/claude-task-manager/tests/test-insights.js +0 -124
  51. package/template/claude-task-manager/tests/test-permissions-v2.js +0 -127
  52. package/template/claude-task-manager/tests/test-permissions.js +0 -122
  53. package/template/claude-task-manager/tests/test-pin.js +0 -51
  54. package/template/claude-task-manager/tests/test-prompts.js +0 -164
  55. package/template/claude-task-manager/tests/test-recent-sessions.js +0 -96
  56. package/template/claude-task-manager/tests/test-review.js +0 -104
  57. package/template/claude-task-manager/tests/test-send-dropdown.js +0 -76
  58. package/template/claude-task-manager/tests/test-send-final.js +0 -30
  59. package/template/claude-task-manager/tests/test-send-fixes.js +0 -76
  60. package/template/claude-task-manager/tests/test-send-integration.js +0 -107
  61. package/template/claude-task-manager/tests/test-send-visual.js +0 -34
  62. package/template/claude-task-manager/tests/test-session-create.js +0 -147
  63. package/template/claude-task-manager/tests/test-sidebar-ux.js +0 -83
  64. package/template/claude-task-manager/tests/test-url-hash.js +0 -68
  65. package/template/claude-task-manager/tests/test-ux-crop.js +0 -34
  66. package/template/claude-task-manager/tests/test-ux-review.js +0 -130
  67. package/template/claude-task-manager/tests/test-zoom-card.js +0 -76
  68. package/template/claude-task-manager/tests/test-zoom.js +0 -92
  69. package/template/claude-task-manager/tests/test-zoom2.js +0 -67
  70. package/template/docs/openclaw-vs-walle-comparison.md +0 -103
  71. package/template/docs/ux-improvement-plan.md +0 -84
  72. package/template/wall-e/docs/specs/2026-04-01-publish-plan.md +0 -112
  73. package/template/wall-e/docs/specs/SKILL-FORMAT.md +0 -326
  74. package/template/wall-e/package-lock.json +0 -533
  75. package/template/wall-e/skills/_bundled/slack-mentions/.watermark.json +0 -4
@@ -1,130 +0,0 @@
1
- #!/usr/bin/env node
2
- const puppeteer = require('puppeteer');
3
- const TOKEN = process.env.CTM_TEST_TOKEN || 'test-token-placeholder';
4
-
5
- async function runTest() {
6
- const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] });
7
- const page = await browser.newPage();
8
- page.on('pageerror', err => console.error('[PAGE ERROR]', err.message));
9
- await page.setViewport({ width: 1920, height: 1080 });
10
- await page.goto(`http://localhost:3456/prompts.html?token=${TOKEN}`, { waitUntil: 'networkidle2', timeout: 15000 });
11
- await new Promise(r => setTimeout(r, 1000));
12
-
13
- // Screenshot 1: Empty/welcome state
14
- await page.screenshot({ path: 'tests/screenshots/ux-01-welcome.png' });
15
-
16
- // Click on "Email Cron v2" prompt
17
- const items = await page.$$('.prompt-item');
18
- for (const item of items) {
19
- const title = await item.$eval('.prompt-title', el => el.textContent.trim());
20
- if (title.includes('Email Cron')) {
21
- await item.click();
22
- console.log('Clicked:', title);
23
- break;
24
- }
25
- }
26
- await new Promise(r => setTimeout(r, 800));
27
-
28
- // Screenshot 2: Full page with editor open
29
- await page.screenshot({ path: 'tests/screenshots/ux-02-editor-full.png' });
30
-
31
- // Screenshot 3: Editor content area (cropped)
32
- const editorWrapper = await page.$('.editor-wrapper');
33
- if (editorWrapper) {
34
- await editorWrapper.screenshot({ path: 'tests/screenshots/ux-03-editor-content.png' });
35
- }
36
-
37
- // Screenshot 4: Meta bar and toolbar area
38
- const metaBar = await page.$('.meta-bar');
39
- const toolbar = await page.$('.editor-toolbar');
40
- if (metaBar && toolbar) {
41
- const mBox = await metaBar.boundingBox();
42
- const tBox = await toolbar.boundingBox();
43
- const clip = {
44
- x: mBox.x,
45
- y: mBox.y,
46
- width: Math.max(mBox.width, tBox.width),
47
- height: (tBox.y + tBox.height) - mBox.y
48
- };
49
- await page.screenshot({ path: 'tests/screenshots/ux-04-meta-toolbar.png', clip });
50
- }
51
-
52
- // Screenshot 5: Sidebar
53
- const sidebar = await page.$('#prompt-sidebar');
54
- if (sidebar) {
55
- await sidebar.screenshot({ path: 'tests/screenshots/ux-05-sidebar.png' });
56
- }
57
-
58
- // Screenshot 6: Scroll down to see more content
59
- await page.evaluate(() => {
60
- const w = document.querySelector('.editor-wrapper');
61
- if (w) w.scrollTop = w.scrollHeight;
62
- });
63
- await new Promise(r => setTimeout(r, 300));
64
- await page.screenshot({ path: 'tests/screenshots/ux-06-scrolled-bottom.png' });
65
-
66
- // Screenshot 7: Mobile-ish width
67
- await page.setViewport({ width: 768, height: 1024 });
68
- await new Promise(r => setTimeout(r, 500));
69
- await page.screenshot({ path: 'tests/screenshots/ux-07-tablet.png' });
70
-
71
- // Check some computed styles for the analysis
72
- await page.setViewport({ width: 1920, height: 1080 });
73
- await new Promise(r => setTimeout(r, 300));
74
-
75
- const styles = await page.evaluate(() => {
76
- const editor = document.getElementById('editor');
77
- const wrapper = document.querySelector('.editor-wrapper');
78
- const metaBar = document.querySelector('.meta-bar');
79
- const titleInput = document.getElementById('prompt-title-input');
80
- const toolbar = document.querySelector('.editor-toolbar');
81
-
82
- const get = el => {
83
- if (!el) return null;
84
- const cs = getComputedStyle(el);
85
- return {
86
- fontFamily: cs.fontFamily,
87
- fontSize: cs.fontSize,
88
- lineHeight: cs.lineHeight,
89
- color: cs.color,
90
- background: cs.backgroundColor,
91
- padding: cs.padding,
92
- maxWidth: cs.maxWidth,
93
- margin: cs.margin,
94
- };
95
- };
96
-
97
- // Check link styles
98
- const links = editor.querySelectorAll('a');
99
- const linkStyles = links.length ? getComputedStyle(links[0]) : null;
100
-
101
- // Check strong/bold styles
102
- const strongs = editor.querySelectorAll('strong');
103
- const strongStyle = strongs.length ? getComputedStyle(strongs[0]) : null;
104
-
105
- // Check paragraphs
106
- const paragraphs = editor.querySelectorAll('p');
107
- const pStyle = paragraphs.length ? getComputedStyle(paragraphs[0]) : null;
108
-
109
- return {
110
- editor: get(editor),
111
- wrapper: get(wrapper),
112
- metaBar: get(metaBar),
113
- titleInput: get(titleInput),
114
- toolbar: get(toolbar),
115
- link: linkStyles ? { color: linkStyles.color, textDecoration: linkStyles.textDecoration } : null,
116
- strong: strongStyle ? { fontWeight: strongStyle.fontWeight, fontSize: strongStyle.fontSize } : null,
117
- paragraph: pStyle ? { marginBottom: pStyle.marginBottom, lineHeight: pStyle.lineHeight } : null,
118
- editorWidth: editor.getBoundingClientRect().width,
119
- wrapperWidth: wrapper.getBoundingClientRect().width,
120
- };
121
- });
122
-
123
- console.log('\n=== Computed Styles ===');
124
- console.log(JSON.stringify(styles, null, 2));
125
-
126
- await browser.close();
127
- console.log('\nScreenshots saved to tests/screenshots/ux-*.png');
128
- }
129
-
130
- runTest();
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env node
2
- const puppeteer = require('puppeteer');
3
- const TOKEN = process.env.CTM_TEST_TOKEN || 'test-token-placeholder';
4
-
5
- async function runTest() {
6
- const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] });
7
- const page = await browser.newPage();
8
- page.on('pageerror', err => console.error('[PAGE ERROR]', err.message));
9
- await page.setViewport({ width: 1920, height: 1080 });
10
- await page.goto(`http://localhost:3456/prompts.html?token=${TOKEN}`, { waitUntil: 'networkidle2', timeout: 15000 });
11
- await new Promise(r => setTimeout(r, 1000));
12
-
13
- // Open Email Cron v2
14
- const items = await page.$$('.prompt-item');
15
- for (const item of items) {
16
- const title = await item.$eval('.prompt-title', el => el.textContent.trim());
17
- if (title.includes('Email Cron')) { await item.click(); break; }
18
- }
19
- await new Promise(r => setTimeout(r, 800));
20
-
21
- // Helper: crop to editor area
22
- async function cropEditor(filename) {
23
- const wrapper = await page.$('.editor-wrapper');
24
- if (wrapper) {
25
- const box = await wrapper.boundingBox();
26
- const clip = {
27
- x: box.x,
28
- y: box.y,
29
- width: Math.min(box.width, 1400),
30
- height: Math.min(box.height, 700),
31
- };
32
- await page.screenshot({ path: `tests/screenshots/${filename}`, clip });
33
- }
34
- }
35
-
36
- // 100% zoom
37
- console.log('Testing 100% zoom...');
38
- await cropEditor('zoom-card-100.png');
39
-
40
- // 75% zoom
41
- await page.select('#zoom-select', '75');
42
- await new Promise(r => setTimeout(r, 300));
43
- console.log('Testing 75% zoom...');
44
- await cropEditor('zoom-card-75.png');
45
-
46
- // 150% zoom
47
- await page.select('#zoom-select', '150');
48
- await new Promise(r => setTimeout(r, 300));
49
- console.log('Testing 150% zoom...');
50
- await cropEditor('zoom-card-150.png');
51
-
52
- // 200% zoom
53
- await page.select('#zoom-select', '200');
54
- await new Promise(r => setTimeout(r, 300));
55
- console.log('Testing 200% zoom...');
56
- await cropEditor('zoom-card-200.png');
57
-
58
- // Check computed properties
59
- const info = await page.evaluate(() => {
60
- const editor = document.getElementById('editor');
61
- const wrapper = document.querySelector('.editor-wrapper');
62
- return {
63
- editorZoom: editor.style.zoom,
64
- editorWidth: editor.getBoundingClientRect().width,
65
- editorHeight: editor.getBoundingClientRect().height,
66
- wrapperScrollWidth: wrapper.scrollWidth,
67
- wrapperClientWidth: wrapper.clientWidth,
68
- wrapperScrollHeight: wrapper.scrollHeight,
69
- };
70
- });
71
- console.log('\nAt 200% zoom:', JSON.stringify(info, null, 2));
72
-
73
- await browser.close();
74
- }
75
-
76
- runTest();
@@ -1,92 +0,0 @@
1
- #!/usr/bin/env node
2
- const puppeteer = require('puppeteer');
3
-
4
- const TOKEN = process.env.CTM_TEST_TOKEN || 'test-token-placeholder';
5
- const BASE_URL = `http://localhost:3456/prompts.html?token=${TOKEN}`;
6
-
7
- async function runTest() {
8
- const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] });
9
- const page = await browser.newPage();
10
- page.on('pageerror', err => console.error('[PAGE ERROR]', err.message));
11
- page.on('console', msg => { if (msg.type() === 'error') console.log('[CONSOLE ERROR]', msg.text()); });
12
- await page.setViewport({ width: 1920, height: 1080 });
13
- await page.goto(BASE_URL, { waitUntil: 'networkidle2', timeout: 15000 });
14
- await new Promise(r => setTimeout(r, 800));
15
-
16
- // Open first prompt
17
- const items = await page.$$('.prompt-item');
18
- if (items.length) await items[0].click();
19
- await new Promise(r => setTimeout(r, 500));
20
-
21
- // Check toolbar visibility
22
- const toolbarDisplay = await page.$eval('#editor-toolbar', el => getComputedStyle(el).display);
23
- console.log('Toolbar computed display:', toolbarDisplay);
24
-
25
- // Check zoom select
26
- const selectExists = !!(await page.$('#zoom-select'));
27
- console.log('Zoom select exists:', selectExists);
28
- const selectVal = await page.$eval('#zoom-select', el => el.value);
29
- console.log('Zoom select value:', selectVal);
30
-
31
- // List all toolbar buttons with their onclick
32
- const btns = await page.$$eval('.toolbar-btn', els => els.map(e => ({
33
- text: e.textContent.trim(),
34
- onclick: e.getAttribute('onclick'),
35
- visible: getComputedStyle(e).display !== 'none',
36
- })));
37
- console.log('\nAll toolbar buttons:');
38
- btns.forEach(b => console.log(` "${b.text}" → onclick="${b.onclick}" visible=${b.visible}`));
39
-
40
- // Find + and - buttons
41
- const plusBtn = btns.find(b => b.text === '+');
42
- const minusBtn = btns.find(b => b.onclick && b.onclick.includes('zoomEditor(-1)'));
43
- console.log('\nPlus button:', plusBtn ? 'FOUND' : 'NOT FOUND');
44
- console.log('Minus button:', minusBtn ? 'FOUND' : 'NOT FOUND');
45
-
46
- // Test: click + button
47
- console.log('\n--- Test: Click + button ---');
48
- const valBefore = await page.$eval('#zoom-select', el => el.value);
49
- console.log('Before:', valBefore);
50
-
51
- await page.evaluate(() => {
52
- const btn = Array.from(document.querySelectorAll('.toolbar-btn')).find(b => b.getAttribute('onclick') === 'zoomEditor(1)');
53
- console.log('Found btn:', btn);
54
- if (btn) btn.click();
55
- });
56
- await new Promise(r => setTimeout(r, 200));
57
-
58
- const valAfter = await page.$eval('#zoom-select', el => el.value);
59
- console.log('After click +:', valAfter);
60
-
61
- // Test: direct JS call
62
- console.log('\n--- Test: Direct zoomEditor(1) ---');
63
- try {
64
- await page.evaluate(() => zoomEditor(1));
65
- const valAfter2 = await page.$eval('#zoom-select', el => el.value);
66
- console.log('After direct call:', valAfter2);
67
- } catch (e) {
68
- console.log('ERROR calling zoomEditor:', e.message);
69
- }
70
-
71
- // Test: check if zoomEditor is defined
72
- const fnExists = await page.evaluate(() => typeof zoomEditor);
73
- console.log('\ntypeof zoomEditor:', fnExists);
74
- const setZoomExists = await page.evaluate(() => typeof setZoom);
75
- console.log('typeof setZoom:', setZoomExists);
76
- const applyZoomExists = await page.evaluate(() => typeof applyZoom);
77
- console.log('typeof applyZoom:', applyZoomExists);
78
-
79
- // Test: select dropdown
80
- console.log('\n--- Test: Select 200% from dropdown ---');
81
- await page.select('#zoom-select', '200');
82
- await new Promise(r => setTimeout(r, 200));
83
- const wrapperFontSize = await page.$eval('#editor-wrapper', el => el.style.fontSize);
84
- console.log('Wrapper fontSize:', wrapperFontSize);
85
-
86
- await page.screenshot({ path: 'tests/screenshots/zoom-debug.png' });
87
- console.log('\nScreenshot saved');
88
-
89
- await browser.close();
90
- }
91
-
92
- runTest();
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env node
2
- const puppeteer = require('puppeteer');
3
- const TOKEN = process.env.CTM_TEST_TOKEN || 'test-token-placeholder';
4
-
5
- async function runTest() {
6
- const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] });
7
- const page = await browser.newPage();
8
- page.on('pageerror', err => console.error('[PAGE ERROR]', err.message));
9
- await page.setViewport({ width: 1920, height: 1080 });
10
- await page.goto(`http://localhost:3456/prompts.html?token=${TOKEN}`, { waitUntil: 'networkidle2', timeout: 15000 });
11
- await new Promise(r => setTimeout(r, 800));
12
-
13
- // Open first prompt
14
- const items = await page.$$('.prompt-item');
15
- if (items.length) await items[0].click();
16
- await new Promise(r => setTimeout(r, 500));
17
-
18
- // Crop to editor area for comparison
19
- const clip = { x: 220, y: 90, width: 900, height: 400 };
20
-
21
- // 100%
22
- console.log('Screenshot at 100%...');
23
- await page.screenshot({ path: 'tests/screenshots/zoom-crop-100.png', clip });
24
-
25
- // 150%
26
- await page.select('#zoom-select', '150');
27
- await new Promise(r => setTimeout(r, 300));
28
- const fs150 = await page.$eval('#editor-wrapper', el => el.style.fontSize);
29
- console.log('fontSize at 150%:', fs150);
30
- await page.screenshot({ path: 'tests/screenshots/zoom-crop-150.png', clip });
31
-
32
- // 200%
33
- await page.select('#zoom-select', '200');
34
- await new Promise(r => setTimeout(r, 300));
35
- const fs200 = await page.$eval('#editor-wrapper', el => el.style.fontSize);
36
- console.log('fontSize at 200%:', fs200);
37
- await page.screenshot({ path: 'tests/screenshots/zoom-crop-200.png', clip });
38
-
39
- // 75%
40
- await page.select('#zoom-select', '75');
41
- await new Promise(r => setTimeout(r, 300));
42
- const fs75 = await page.$eval('#editor-wrapper', el => el.style.fontSize);
43
- console.log('fontSize at 75%:', fs75);
44
- await page.screenshot({ path: 'tests/screenshots/zoom-crop-75.png', clip });
45
-
46
- // Check actual computed font size of editor text
47
- const computed100 = await page.evaluate(() => {
48
- document.getElementById('editor-wrapper').style.fontSize = '100%';
49
- return getComputedStyle(document.getElementById('editor')).fontSize;
50
- });
51
- const computed200 = await page.evaluate(() => {
52
- document.getElementById('editor-wrapper').style.fontSize = '200%';
53
- return getComputedStyle(document.getElementById('editor')).fontSize;
54
- });
55
- console.log('\nComputed font-size at 100%:', computed100);
56
- console.log('Computed font-size at 200%:', computed200);
57
-
58
- if (computed100 === computed200) {
59
- console.log('\nFAIL: Zoom has no visual effect! The font-size% on wrapper is not cascading to the editor content.');
60
- } else {
61
- console.log('\nPASS: Zoom changes computed font size.');
62
- }
63
-
64
- await browser.close();
65
- }
66
-
67
- runTest();
@@ -1,103 +0,0 @@
1
- # OpenClaw vs. Wall-E: Intelligence Comparison
2
-
3
- *Date: 2026-04-03*
4
-
5
- ## The Fundamental Architectural Difference
6
-
7
- **OpenClaw is a *routing plane*. Wall-E is a *cognitive loop*.**
8
-
9
- They solve different problems, and that shapes everything about how "intelligent" they feel.
10
-
11
- | | OpenClaw | Wall-E |
12
- |---|---|---|
13
- | **Core metaphor** | Gateway / message router | Digital twin / brain |
14
- | **Intelligence source** | Claude (or any LLM) on every turn | Claude for extraction + pre-computed brain state |
15
- | **Proactivity** | Cron jobs -> spawn agent turn | Ingest/think/reflect loops + skill planner |
16
- | **Memory** | Vector embeddings + session transcripts | SPO knowledge triples + raw memories + FTS |
17
- | **Identity** | Configurable name/emoji prefix | Deep identity from 28k+ ingested memories |
18
- | **Channels** | 23+ messaging platforms | iMessage, Slack DM, CTM chat |
19
- | **Architecture** | ~200k+ lines TypeScript monorepo | ~10k lines Node.js |
20
-
21
- ## Where OpenClaw Feels "Smarter"
22
-
23
- ### 1. The Gateway is the brain -- every message gets a full Claude turn
24
-
25
- OpenClaw's Pi agent runtime (`pi-embedded-runner.ts`) runs a full LLM call for every single incoming message. The agent has access to tools (bash, file read/write, web search, canvas, image gen, cron management, subagent spawning, session management) and Claude decides what to do. This means:
26
-
27
- - It can reason about *anything* in real-time
28
- - It can chain tool calls naturally (search -> read -> respond)
29
- - It doesn't need pre-computed knowledge -- it reasons on the fly
30
-
31
- Wall-E, by contrast, pre-computes knowledge in batch loops (think every 2 min, reflect every hour). The chat handler builds a static system prompt from brain state. This means Wall-E's "intelligence" at chat time is limited to what's already been extracted and stored.
32
-
33
- ### 2. Subagent orchestration
34
-
35
- OpenClaw can spawn child agents (`subagent-spawn.ts`) -- isolated sessions with their own tools, models, and timeouts. This enables multi-step autonomous workflows where one agent delegates to another. Wall-E has no equivalent -- it's a single-threaded daemon.
36
-
37
- ### 3. Cron = proactive muscle
38
-
39
- OpenClaw's cron system (`server-cron.ts`) spawns full agent turns on a schedule. The agent gets the same tools as a chat turn -- so a cron job can browse the web, check APIs, write files, and send messages autonomously.
40
-
41
- Wall-E's `runDueSkills()` is similar in concept but far simpler -- it runs predefined prompt templates through Claude tool-use. The prompts are static, not adaptive.
42
-
43
- ### 4. Compaction and context management
44
-
45
- OpenClaw has a sophisticated compaction system (`compaction.ts`) that progressively summarizes conversation history, preserves identifiers and decisions, drops old chunks first, and handles tool-result pairing. This means long conversations stay coherent.
46
-
47
- Wall-E has no compaction -- chat context is built fresh each time from brain state. Long conversations will eventually hit token limits and simply fail.
48
-
49
- ### 5. Memory search with embeddings
50
-
51
- OpenClaw's `memory-search.ts` uses hybrid search: vector embeddings + full-text with MMR (Maximal Marginal Relevance) and temporal decay. This means it can find semantically relevant memories, not just keyword matches.
52
-
53
- Wall-E uses BM25 full-text search only (via SQLite FTS5). Good for exact matches, but misses semantic connections.
54
-
55
- ## Where Wall-E Has Unique Strengths
56
-
57
- ### 1. Deep identity model
58
-
59
- Wall-E has something OpenClaw doesn't: a *persistent cognitive identity*. The knowledge triples (subject-predicate-object), relationship graph with trust levels, behavioral patterns, and 28k+ memories create a model of *who Juncao is*. The system prompt in `chat.js` includes actual Slack messages as voice samples, people interaction summaries, and topic frequencies.
60
-
61
- OpenClaw's identity is a configurable name/emoji + optional SOUL.md persona file. It has no self-model.
62
-
63
- ### 2. The think loop is genuine cognition
64
-
65
- Wall-E's `think.js` does something unique: it takes raw memories and *extracts structured knowledge* (SPO triples), detects contradictions between new and existing knowledge, and generates questions when it's uncertain. This is closer to how a brain actually learns -- not just retrieving, but *processing and integrating*.
66
-
67
- OpenClaw has no equivalent batch learning process.
68
-
69
- ### 3. Autonomy tiers
70
-
71
- Wall-E's graduated trust system (Tier 1-4 per domain, with demotion on rejection) is a thoughtful approach to autonomous action. OpenClaw has approval mechanisms, but they're per-tool policy, not a learned trust model.
72
-
73
- ## Why Wall-E Feels "Pulled Back"
74
-
75
- ### 1. Static system prompt, no dynamic reasoning chain
76
-
77
- Wall-E builds one big system prompt with everything pre-loaded (knowledge, people, memories, skills). Claude sees a snapshot, not a live workspace. OpenClaw's agent gets tools and *discovers* what it needs on each turn.
78
-
79
- ### 2. No autonomous action loop
80
-
81
- Wall-E's daemon loops (ingest/think/reflect) are *passive processing*. They crunch data but never take initiative. The skill planner runs due skills on a timer, but the skills are pre-defined prompt templates. There's no "look at what's happening and decide to do something" loop.
82
-
83
- OpenClaw's cron + subagent spawning means it can proactively decide "it's Monday morning, let me check your calendar, summarize your Slack, and send you a briefing."
84
-
85
- ### 3. No multi-turn tool orchestration
86
-
87
- Wall-E's chat does tool-use (search_memories, run_skill, mcp_call), but each chat turn is essentially independent. There's no concept of a long-running task that spans multiple turns. OpenClaw's session model preserves full conversation state and allows agent turns to build on each other.
88
-
89
- ### 4. No event-driven triggers
90
-
91
- Wall-E runs on fixed timers. OpenClaw can react to webhooks, channel events, and cron triggers. If someone mentions you in Slack, OpenClaw can immediately spawn a response. Wall-E would only notice on its next poll cycle.
92
-
93
- ## Key Upgrades to Make Wall-E More Proactive
94
-
95
- 1. **Event-driven wake**: Instead of polling every 60s, react to channel events immediately.
96
- 2. **Autonomous reasoning turn**: Periodic "what should I do?" turn where Wall-E decides whether to take action.
97
- 3. **Persistent conversation context**: Maintain session state with compaction instead of fresh system prompt each time.
98
- 4. **Dynamic tool discovery**: Let Wall-E discover what it needs via tool calls instead of pre-loading everything.
99
- 5. **Background tasks / subagents**: Spawn long-running tasks that run independently.
100
-
101
- ## Summary
102
-
103
- OpenClaw is a mature *infrastructure* project -- it solves the "connect to everything, route to Claude, let Claude figure it out" problem extremely well. Wall-E is a more ambitious *cognitive* project -- it's trying to actually *be* you, not just respond on your behalf. The gap is that Wall-E has the brain but not the muscles. It knows you deeply but doesn't act on that knowledge. The fix isn't to copy OpenClaw's architecture wholesale, but to give Wall-E's brain an *agency layer* -- the ability to decide, act, and iterate autonomously.
@@ -1,84 +0,0 @@
1
- # CTM & Wall-E UX Improvement Plan
2
-
3
- Date: 2026-04-03
4
-
5
- ## Phase 1: First Impressions (New User Experience)
6
-
7
- ### 1.1 Simplify Navigation
8
- - Group nav into primary (Sessions, Prompts, WALL-E) and secondary
9
- - Move Insights, Permissions, Review, Rules, Backups behind "More" dropdown
10
- - Keeps nav clean for new users, power users still have access
11
-
12
- ### 1.2 Better Empty State
13
- - Sessions welcome: 1 clear CTA "Start a Claude Session" with brief explanation
14
- - Remove keyboard shortcuts from welcome (move to ? help overlay)
15
- - Add "What can I do?" quick examples
16
-
17
- ### 1.3 Hide Queue Builder by Default
18
- - Queue Builder panel takes ~25% screen width, always open
19
- - Make it a toggle/drawer, collapsed by default
20
- - Show "Queue" button in toolbar that opens it
21
-
22
- ### 1.4 Wall-E Onboarding
23
- - First-time visitor sees intro card: "I'm Wall-E" with 3-4 example actions
24
- - Disappears after first interaction or dismiss
25
-
26
- ### 1.5 Reduce Wall-E Sub-tabs
27
- - Current: Chat, Tasks, Brain, Actions, Skills, Timeline, Questions, Status (8 tabs)
28
- - Proposed: Chat, Tasks, Skills as primary; Brain/Actions/Timeline/Questions/Status behind "More"
29
-
30
- ## Phase 2: Information Hierarchy & Readability
31
-
32
- ### 2.1 Task Cards Cleanup
33
- - Collapse output by default (click to expand)
34
- - Add colored status dots (green=running, yellow=pending, red=failed, gray=paused)
35
- - Reduce metadata noise — show schedule + last run, hide others until hover/expand
36
-
37
- ### 2.2 Prompts Toolbar Simplification
38
- - Essential always visible: bold, italic, lists, headings
39
- - Advanced in overflow: font selector, zoom, chains/templates/patterns/harvest/copilot sub-tabs
40
- - Move sub-tabs into prompt editor sidebar or contextual menu
41
-
42
- ### 2.3 Insights Action-First Layout
43
- - Put the action item (green arrow text) FIRST, then explanation
44
- - Add category icons for workflow/prompt-effectiveness/skill-gap/cost-saving
45
-
46
- ### 2.4 Permissions Explainer
47
- - Add brief card at top: "Permissions control what Claude Code can do automatically"
48
- - Better risk color coding (red=high, yellow=medium, green=low)
49
-
50
- ## Phase 3: Visual Polish & Consistency
51
-
52
- ### 3.1 Unified Status Indicators
53
- - Colored dots + icons for all states across tasks, sessions, integrations
54
- - Running=green pulse, Pending=yellow, Failed=red, Paused=gray, Connected=green, Disconnected=red
55
-
56
- ### 3.2 Chat Improvements
57
- - Date separators between conversations
58
- - Softer "YOU" label (lowercase or muted)
59
- - Proper markdown table rendering in chat
60
-
61
- ### 3.3 Setup Page Polish
62
- - Move Data Storage into collapsible "Advanced" section
63
- - Add step progress indicator
64
-
65
- ### 3.4 Consistent Card Styling
66
- - Unify border radius, padding, shadow across all pages
67
-
68
- ## Phase 4: Progressive Disclosure
69
-
70
- ### 4.1 Contextual Tooltips
71
- - First-time hints for Shadow Approver, Queue Builder, Harvest, Copilot
72
-
73
- ### 4.2 Keyboard Shortcuts Overlay
74
- - Press ? to see all shortcuts (like GitHub)
75
-
76
- ### 4.3 Collapsible Sidebar Filters
77
- - Sessions filters collapse to single row
78
-
79
- ## Implementation Notes
80
-
81
- - Test all changes on dev instance (port 4000), never restart primary (port 3456)
82
- - Use /ctm-dev skill for testing
83
- - Each phase can be implemented independently
84
- - Phase 1 has highest impact for new users
@@ -1,112 +0,0 @@
1
- # Publishing Plan: CTM & Wall-E
2
-
3
- **Date:** 2026-04-01
4
- **Author:** Wall-E Team
5
- **Domain:** https://walle.sh
6
-
7
- ## Overview
8
-
9
- Publish CTM (Claude Task Manager) and Wall-E (personal digital twin agent) as open-source tools that others can discover, install, and run locally.
10
-
11
- ## Phases
12
-
13
- ### Phase 1: Code Cleanup & Open Source (Current)
14
-
15
- **Goal:** Make the codebase safe and portable for public GitHub.
16
-
17
- #### Security Cleanup
18
-
19
- | Issue | Severity | Files | Fix |
20
- |---|---|---|---|
21
- | Hardcoded Slack User ID `YOUR_SLACK_USER_ID` | Critical | 5 files in `scripts/`, `slack-ingest.js` | Env var `SLACK_OWNER_USER_ID` |
22
- | `owner@example.com` in SKILL.md examples | High | `email-sync/SKILL.md`, `google-calendar/SKILL.md` | Replace with `owner@example.com` |
23
- | Hardcoded Slack handle in queries | High | `slack-backfill.js`, `slack-channel-history.js`, `morning-briefing/run.js` | Read from config/brain |
24
- | `OWNER_NAME` owner name constant | High | `pull-slack-via-claude.js`, `slack-ingest.js` | Use `brain.getOwnerName()` |
25
- | Hardcoded `.walle/data` | Medium | `server.js`, `db.js`, `brain.js`, `api-walle.js` | Default to `~/.walle/data` |
26
-
27
- #### Repo Hygiene
28
-
29
- - [ ] `.env.example` documenting all env vars
30
- - [ ] `.gitignore` excludes `.db`, `.env`, compiled binaries, oauth tokens
31
- - [ ] MIT `LICENSE` file
32
- - [ ] Scrub git history or start fresh public repo (if secrets were ever committed)
33
-
34
- #### Already Good
35
-
36
- - API keys (ANTHROPIC_API_KEY, SLACK_TOKEN) read from env vars
37
- - `.db` files not in repo
38
- - `CTM_DATA_DIR` / `WALL_E_DATA_DIR` env vars already supported
39
-
40
- ### Phase 2: Distribution & Discovery
41
-
42
- **Goal:** Make it easy for others to find and install.
43
-
44
- | Channel | Effort | Reach | Priority |
45
- |---|---|---|---|
46
- | GitHub repo + README | Low | Devs who search GitHub | P0 |
47
- | `npx create-walle` scaffolder | Medium | Anyone with Node.js | P1 |
48
- | Claude Code skill registry | Low | Claude Code users | P1 |
49
- | Homebrew tap | Medium | macOS users | P2 |
50
- | walle.sh website | High | Broadest | P2 |
51
-
52
- #### README Requirements
53
-
54
- - One-paragraph pitch
55
- - Screenshot / demo GIF
56
- - "Try it in 2 minutes" quickstart
57
- - Architecture diagram (CTM <-> Wall-E <-> Brain)
58
- - List of bundled skills (calendar, slack, email, morning briefing)
59
- - Configuration reference
60
-
61
- #### npx Scaffolder
62
-
63
- ```bash
64
- npx create-walle
65
- # Clones repo, runs npm install, creates ~/.walle/data,
66
- # prompts for ANTHROPIC_API_KEY, owner name, optional Slack token
67
- # Starts CTM + Wall-E daemon
68
- ```
69
-
70
- ### Phase 3: Website — walle.sh
71
-
72
- **Goal:** Landing page, docs, and eventually auth + cloud hosting.
73
-
74
- | Sub-phase | What | Tech |
75
- |---|---|---|
76
- | 3a | Static landing page: pitch, screenshots, install guide | Cloudflare Pages (free, deploys from repo) |
77
- | 3b | Interactive docs: skill catalog, API reference | Same, or Astro/Starlight |
78
- | 3c | Auth + cloud DB | Fly.io (already deployed), Turso/Libsql for SQLite-compat cloud DB, Clerk or Passkeys for auth |
79
- | 3d | Web-based setup wizard | Create account -> configure integrations -> download CLI |
80
-
81
- #### Domain DNS Roadmap
82
-
83
- | Record | Now | Later |
84
- |---|---|---|
85
- | `walle.sh` | `127.0.0.1` (local alias) | Cloudflare Pages (landing) |
86
- | `app.walle.sh` | — | Fly.io (cloud CTM + Wall-E) |
87
- | `api.walle.sh` | — | Fly.io (public API) |
88
- | `docs.walle.sh` | — | Cloudflare Pages (documentation) |
89
-
90
- ### Phase 4: Multi-User & Marketplace
91
-
92
- **Goal:** Let others contribute skills; host as SaaS.
93
-
94
- - Per-user data isolation (separate brain DBs)
95
- - Skill marketplace: browse, install, rate community skills
96
- - Usage-based pricing or free tier + pro
97
- - Telemetry opt-in for usage insights
98
- - Rate limiting / cost management (Wall-E daemon burns API tokens)
99
-
100
- ## Branding
101
-
102
- - **Public name:** Wall-E (memorable, the face of the project)
103
- - **CTM** is the task manager component (less catchy, keep as internal name)
104
- - **Domain:** walle.sh
105
- - **Tagline ideas:** "Your personal digital twin" / "An AI that knows you"
106
-
107
- ## Open Questions
108
-
109
- 1. Start fresh public repo or clean history of current repo?
110
- 2. Pricing model for cloud version? Free tier limits?
111
- 3. Skill contribution guidelines and review process?
112
- 4. Should the Slack/Email/Calendar sync skills require specific setup guides per-platform?