symbiot 0.10.0 → 0.10.2
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/index.mjs +21 -10
- package/package.json +2 -2
package/index.mjs
CHANGED
|
@@ -122,22 +122,31 @@ function buildTasksMd(name, ctx, list) {
|
|
|
122
122
|
function pushTasks() {
|
|
123
123
|
const tasks = loadTasks().filter((t) => !t.done);
|
|
124
124
|
if (!tasks.length) return { empty: true, written: [], unresolved: [] };
|
|
125
|
-
|
|
125
|
+
// Resolve repo name -> path from the already-scanned map when we have it
|
|
126
|
+
// (avoids a fresh full scan); fall back to a scan only if needed.
|
|
127
|
+
const byName = {};
|
|
128
|
+
const src = (LAST_MAP && LAST_MAP.nodes) ? LAST_MAP.nodes.filter((n) => n.type === "repo").map((n) => ({ name: n.label, path: n.meta && n.meta.path })) : findAllRepos(BASE);
|
|
129
|
+
for (const r of src) if (r.path && !byName[r.name]) byName[r.name] = r.path;
|
|
126
130
|
const groups = {}; for (const t of tasks) { const k = t.repo || ""; (groups[k] = groups[k] || []).push(t); }
|
|
127
131
|
const written = [], unresolved = [];
|
|
128
132
|
for (const name of Object.keys(groups)) {
|
|
129
133
|
const list = groups[name], path = name && byName[name];
|
|
130
134
|
if (!path) { unresolved.push({ name: name || "(no repo)", count: list.length }); continue; }
|
|
131
135
|
try {
|
|
136
|
+
// Cheap, per-repo signals only — no full drift scan (that can be very slow
|
|
137
|
+
// on big repos and would block the request).
|
|
132
138
|
const st = repoState(path);
|
|
133
139
|
const commits = sh(`git -C ${JSON.stringify(path)} log --format='%s' -10 2>/dev/null`).split("\n").filter(Boolean);
|
|
134
|
-
const drift = driftRepo(path, {}).flags.map((f) => (f.level === "warn" ? "⚠ " : "") + f.text);
|
|
135
140
|
const open = openWork([{ path, name }]).slice(0, 12);
|
|
136
141
|
const det = detectRepo({ path, name, recency: 0 });
|
|
137
142
|
const stack = [...det.langs.slice(0, 4), ...det.tools].join(", ");
|
|
143
|
+
const risk = [];
|
|
144
|
+
if (st.stale) risk.push("stale checkout — working tree is an old snapshot, not new work");
|
|
145
|
+
if (st.behind) risk.push(`${st.behind} behind upstream on ${st.branch}`);
|
|
146
|
+
if (st.dirty && !st.stale) risk.push(`${st.dirty} uncommitted (${st.mod} mod / ${st.del} del / ${st.add} new)`);
|
|
138
147
|
const dir = join(path, ".symbiot"); mkdirSync(dir, { recursive: true });
|
|
139
148
|
const file = join(dir, "TASKS.md");
|
|
140
|
-
writeFileSync(file, buildTasksMd(name, { branch: st.branch, commits, open, drift, stack }, list));
|
|
149
|
+
writeFileSync(file, buildTasksMd(name, { branch: st.branch, commits, open, drift: risk, stack }, list));
|
|
141
150
|
written.push({ name, file, count: list.length });
|
|
142
151
|
} catch (e) { unresolved.push({ name, count: list.length, error: String((e && e.message) || e) }); }
|
|
143
152
|
}
|
|
@@ -1202,13 +1211,15 @@ if(clean.length)h+="<div class='muted' style='margin-top:10px'>clean: "+esc(clea
|
|
|
1202
1211
|
if(!repos.length)h+="<div class='muted'>No repos found under your home folder.</div>";
|
|
1203
1212
|
out.innerHTML=h;});}
|
|
1204
1213
|
function addTaskUI(){var i=document.getElementById('newtask');var v=(i.value||'').trim();if(!v)return;api('/api/tasks/add',{text:v,repo:''}).then(function(){i.value='';loadTasks();});}
|
|
1205
|
-
function pushTasksUI(){var o=document.getElementById('pushout');
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
if(r.
|
|
1209
|
-
|
|
1210
|
-
h+="<
|
|
1211
|
-
|
|
1214
|
+
function pushTasksUI(){var o=document.getElementById('pushout');var btn=document.getElementById('pushtasks');btn.disabled=true;
|
|
1215
|
+
o.innerHTML="<div class='muted' style='margin-top:10px'><span class='dot-c' style='background:var(--amber)'></span> Writing .symbiot/TASKS.md into your repos…</div>";
|
|
1216
|
+
api('/api/tasks/push',{}).then(function(r){btn.disabled=false;
|
|
1217
|
+
if(r.empty){o.innerHTML="<div class='muted' style='margin-top:10px'>No open tasks to send. Tick ideas in a repo review, or add tasks above.</div>";return;}
|
|
1218
|
+
var n=(r.written||[]).length;var h="<div class='drift' style='margin-top:10px'><div class='dh'><span class='dot-c'></span><span class='dn'>Done — wrote "+n+" file"+(n===1?"":"s")+"</span></div>";
|
|
1219
|
+
if(n){h+="<ul>";r.written.forEach(function(w){h+="<li class='info'>✓ <b>"+esc(w.name)+"</b> <span class='ev'>"+esc(w.file)+" ("+w.count+" task"+(w.count===1?"":"s")+")</span></li>";});h+="</ul>";}
|
|
1220
|
+
if(r.unresolved&&r.unresolved.length){h+="<div class='dd' style='margin-top:6px'>⚠ not written (repo not found under your home folder): "+esc(r.unresolved.map(function(u){return u.name;}).join(", "))+"</div>";}
|
|
1221
|
+
h+="<div class='dd' style='margin-top:8px'>Now tell your coding agent, in each repo: <b>“Read .symbiot/TASKS.md and implement the unchecked items.”</b></div></div>";
|
|
1222
|
+
o.innerHTML=h;}).catch(function(e){btn.disabled=false;o.innerHTML="<div class='err' style='margin-top:10px'>Couldn't write tasks: "+esc(String((e&&e.message)||e))+"</div>";});}
|
|
1212
1223
|
function selectNode(id){sel=id;render();updateBar(id);var n=nodeById(id);api('/api/node?id='+encodeURIComponent(id)).then(showDetail);
|
|
1213
1224
|
if(n&&n.type==='repo'&&n.meta&&n.meta.path){loadReview(n.label,n.meta.path);}else{hideReview();}}
|
|
1214
1225
|
function screenToGraph(el,ev){var rc=el.getBoundingClientRect();var mx=(ev.clientX-rc.left)/rc.width*GW;var my=(ev.clientY-rc.top)/rc.height*GH;return {x:(mx-view.x)/view.k,y:(my-view.y)/view.k};}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "symbiot",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Your week, written from your real work. Reads your local git and writes it up with the AI of your choice — Claude, OpenAI, Gemini, or a local model.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"@anthropic-ai/sdk": "^0.128.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
|
-
"test": "node test/fixtures.mjs"
|
|
45
|
+
"test": "node test/fixtures.mjs && node test/smoke.mjs"
|
|
46
46
|
}
|
|
47
47
|
}
|