teamshare-bridge 0.22.7 → 0.22.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +383 -383
- package/dist/bridge/daemon.js +43 -20
- package/dist/bridge/daemon.js.map +1 -1
- package/dist/bridge/install-verify.js +8 -8
- package/dist/bridge/spawn.d.ts +14 -0
- package/dist/bridge/spawn.js +7 -1
- package/dist/bridge/spawn.js.map +1 -1
- package/dist/bridge/wake-handler.d.ts +8 -15
- package/dist/bridge/wake-handler.js +109 -14
- package/dist/bridge/wake-handler.js.map +1 -1
- package/dist/bridge/wake-outbox.js +7 -0
- package/dist/bridge/wake-outbox.js.map +1 -1
- package/dist/cli/commands/plan.js +4 -0
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/lib/browser/human-input-guard.js +98 -98
- package/dist/lib/browser/screen-change.js +60 -60
- package/dist/lib/llm/usage-reader.js +4 -4
- package/dist/lib/workspace/classify.d.ts +29 -0
- package/dist/lib/workspace/classify.js +62 -0
- package/dist/lib/workspace/classify.js.map +1 -1
- package/dist/lib/workspace/presence.d.ts +31 -0
- package/dist/lib/workspace/presence.js +35 -1
- package/dist/lib/workspace/presence.js.map +1 -1
- package/dist/lib/workspace/shim-runner.js +23 -0
- package/dist/lib/workspace/shim-runner.js.map +1 -1
- package/package.json +70 -70
- package/skills/THIRD_PARTY_NOTICES.md +26 -26
- package/skills/architect/LICENSE +21 -21
- package/skills/codebase-design/LICENSE +21 -21
- package/skills/diagnosing-bugs/LICENSE +21 -21
- package/skills/domain-modeling/LICENSE +21 -21
- package/skills/improve-codebase-architecture/LICENSE +21 -21
- package/skills/recover/LICENSE +21 -21
- package/skills/review/LICENSE +21 -21
- package/skills/tdd/LICENSE +21 -21
- package/skills/teamshare-auth-rbac/SKILL.md +78 -78
- package/skills/teamshare-cdd/SKILL.md +205 -205
- package/skills/teamshare-modularity/SKILL.md +146 -146
- package/skills/teamshare-orchestrator-ask/SKILL.md +77 -77
- package/skills/teamshare-scaffold/SKILL.md +116 -116
- package/templates/backend/.env.example.tpl +13 -13
- package/templates/backend/nest-cli.json.tpl +8 -8
- package/templates/backend/package.json.tpl +41 -41
- package/templates/backend/prisma/schema.prisma.tpl +39 -39
- package/templates/backend/src/app.module.ts.tpl +24 -24
- package/templates/backend/src/common/filters/all-exceptions.filter.ts.tpl +59 -59
- package/templates/backend/src/common/guards/jwt-auth.guard.ts.tpl +27 -27
- package/templates/backend/src/common/guards/rbac.guard.ts.tpl +48 -48
- package/templates/backend/src/common/interceptors/transform.interceptor.ts.tpl +44 -44
- package/templates/backend/src/common/pipes/zod-validation.pipe.ts.tpl +29 -29
- package/templates/backend/src/common/swagger/envelope.schemas.ts.tpl +53 -53
- package/templates/backend/src/common/swagger/error.schemas.ts.tpl +62 -62
- package/templates/backend/src/main.ts.tpl +27 -27
- package/templates/backend/src/modules/example/example.controller.ts.tpl +102 -102
- package/templates/backend/src/modules/example/example.dto.ts.tpl +14 -14
- package/templates/backend/src/modules/example/example.module.ts.tpl +10 -10
- package/templates/backend/src/modules/example/example.service.ts.tpl +45 -45
- package/templates/backend/tsconfig.json.tpl +26 -26
- package/templates/common/.gitignore.tpl +42 -42
- package/templates/common/AGENTS.md.tpl +58 -58
- package/templates/common/docs/adr/README.md +25 -25
- package/templates/common/docs/api-contract.md.tpl +72 -72
- package/templates/web/next.config.ts.tpl +7 -7
- package/templates/web/package.json.tpl +37 -37
- package/templates/web/src/app/globals.css.tpl +48 -48
- package/templates/web/src/app/layout.tsx.tpl +25 -25
- package/templates/web/src/components/shared/app-button.tsx.tpl +59 -59
- package/templates/web/src/components/shared/app-empty-state.tsx.tpl +39 -39
- package/templates/web/src/components/shared/app-list-toolbar.tsx.tpl +63 -63
- package/templates/web/src/components/shared/app-skeleton.tsx.tpl +14 -14
- package/templates/web/src/components/shared/app-table.tsx.tpl +128 -128
- package/templates/web/src/components/shared/index.ts.tpl +5 -5
- package/templates/web/src/hooks/use-list-state.ts.tpl +72 -72
- package/templates/web/src/hooks/use-url-tab.ts.tpl +25 -25
- package/templates/web/src/lib/api/client.ts.tpl +123 -123
- package/templates/web/src/lib/providers.tsx.tpl +35 -35
- package/templates/web/src/lib/query-keys.ts.tpl +21 -21
- package/templates/web/src/lib/utils.ts.tpl +7 -7
- package/templates/web/src/lib/validation/schemas.ts.tpl +15 -15
- package/templates/web/src/modules/example/views/example-list-view.tsx.tpl +97 -97
- package/templates/web/tsconfig.json.tpl +23 -23
- package/tools/workspace-arbitration-check.mjs +389 -389
|
@@ -148,12 +148,12 @@ class TypingGuard {
|
|
|
148
148
|
async markOwn(char, key) {
|
|
149
149
|
if (!this.enabled || this.osLevel || this.stoppedFlag)
|
|
150
150
|
return;
|
|
151
|
-
await (0, cdp_1.evaluateJs)(this.page, `(() => {
|
|
152
|
-
const s = window[${JSON.stringify(this.key)}];
|
|
153
|
-
if (!s) return false;
|
|
154
|
-
s.exp = { ch: ${JSON.stringify(char)}, key: ${JSON.stringify(key ?? '')} };
|
|
155
|
-
s.until = performance.now() + ${OS_BRACKET_MS};
|
|
156
|
-
return true;
|
|
151
|
+
await (0, cdp_1.evaluateJs)(this.page, `(() => {
|
|
152
|
+
const s = window[${JSON.stringify(this.key)}];
|
|
153
|
+
if (!s) return false;
|
|
154
|
+
s.exp = { ch: ${JSON.stringify(char)}, key: ${JSON.stringify(key ?? '')} };
|
|
155
|
+
s.until = performance.now() + ${OS_BRACKET_MS};
|
|
156
|
+
return true;
|
|
157
157
|
})()`).catch(() => false);
|
|
158
158
|
}
|
|
159
159
|
async dispose() {
|
|
@@ -161,20 +161,20 @@ class TypingGuard {
|
|
|
161
161
|
return;
|
|
162
162
|
const key = this.key;
|
|
163
163
|
this.key = '';
|
|
164
|
-
await (0, cdp_1.evaluateJs)(this.page, `(() => {
|
|
165
|
-
const s = window[${JSON.stringify(key)}];
|
|
166
|
-
if (s) {
|
|
167
|
-
if (s.el && s.handler) s.el.removeEventListener('keydown', s.handler, true);
|
|
168
|
-
if (s.el && s.handler) s.el.removeEventListener('input', s.handler, true);
|
|
169
|
-
if (document && s.handler) {
|
|
170
|
-
document.removeEventListener('keydown', s.handler, true);
|
|
171
|
-
document.removeEventListener('beforeinput', s.handler, true);
|
|
172
|
-
document.removeEventListener('input', s.handler, true);
|
|
173
|
-
document.removeEventListener('paste', s.handler, true);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
try { delete window[${JSON.stringify(key)}]; } catch (e) {}
|
|
177
|
-
return true;
|
|
164
|
+
await (0, cdp_1.evaluateJs)(this.page, `(() => {
|
|
165
|
+
const s = window[${JSON.stringify(key)}];
|
|
166
|
+
if (s) {
|
|
167
|
+
if (s.el && s.handler) s.el.removeEventListener('keydown', s.handler, true);
|
|
168
|
+
if (s.el && s.handler) s.el.removeEventListener('input', s.handler, true);
|
|
169
|
+
if (document && s.handler) {
|
|
170
|
+
document.removeEventListener('keydown', s.handler, true);
|
|
171
|
+
document.removeEventListener('beforeinput', s.handler, true);
|
|
172
|
+
document.removeEventListener('input', s.handler, true);
|
|
173
|
+
document.removeEventListener('paste', s.handler, true);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
try { delete window[${JSON.stringify(key)}]; } catch (e) {}
|
|
177
|
+
return true;
|
|
178
178
|
})()`).catch(() => false);
|
|
179
179
|
}
|
|
180
180
|
fail(reason) {
|
|
@@ -204,87 +204,87 @@ class TypingGuard {
|
|
|
204
204
|
buildInstallScript(target, key) {
|
|
205
205
|
const selector = JSON.stringify(target.selector ?? '');
|
|
206
206
|
const isEditor = target.isCodeEditor === true;
|
|
207
|
-
return `(() => {
|
|
208
|
-
const KEY = ${JSON.stringify(key)};
|
|
209
|
-
const findEl = () => {
|
|
210
|
-
const sel = ${selector};
|
|
211
|
-
if (sel) { try { const e = document.querySelector(sel); if (e) return e; } catch (err) {} }
|
|
212
|
-
const a = document.activeElement;
|
|
213
|
-
if (a && a !== document.body) return a;
|
|
214
|
-
return document.body;
|
|
215
|
-
};
|
|
216
|
-
const readText = (el) => {
|
|
217
|
-
try {
|
|
218
|
-
const monacoNs = typeof monaco !== 'undefined' ? monaco : window.monaco;
|
|
219
|
-
const editors = monacoNs && monacoNs.editor && monacoNs.editor.getEditors ? monacoNs.editor.getEditors() : null;
|
|
220
|
-
if (${isEditor} && editors && editors.length) return editors[editors.length - 1].getValue();
|
|
221
|
-
const cm6 = document.querySelector('.cm-content[contenteditable="true"]');
|
|
222
|
-
if (${isEditor} && cm6 && (cm6 === el || cm6.contains(el))) return cm6.innerText || '';
|
|
223
|
-
const cm5 = document.querySelector('.CodeMirror');
|
|
224
|
-
if (${isEditor} && cm5 && cm5.CodeMirror) return cm5.CodeMirror.getValue();
|
|
225
|
-
const ace = document.querySelector('.ace_editor');
|
|
226
|
-
if (${isEditor} && ace && ace.env && ace.env.editor) return ace.env.editor.getValue();
|
|
227
|
-
} catch (err) {}
|
|
228
|
-
if (!el) return '';
|
|
229
|
-
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') return el.value || '';
|
|
230
|
-
return el.innerText || el.textContent || '';
|
|
231
|
-
};
|
|
232
|
-
const el = findEl();
|
|
233
|
-
const state = { ext: false, info: '', exp: null, until: 0, el: el, handler: null };
|
|
234
|
-
const describe = (ev) => {
|
|
235
|
-
const t = ev.target && ev.target.tagName ? ev.target.tagName : '?';
|
|
236
|
-
const k = ev.key || ev.data || ev.inputType || ev.type;
|
|
237
|
-
return ev.type + ':' + t + ':' + String(k).slice(0, 24);
|
|
238
|
-
};
|
|
239
|
-
const handler = (ev) => {
|
|
240
|
-
const s = window[KEY];
|
|
241
|
-
if (!s) return;
|
|
242
|
-
const now = performance.now();
|
|
243
|
-
if (s.exp && now <= s.until) {
|
|
244
|
-
const k = ev.key || '';
|
|
245
|
-
const d = ev.data || '';
|
|
246
|
-
if ((s.exp.ch && d === s.exp.ch) || (s.exp.key && k === s.exp.key) || (s.exp.ch && k === s.exp.ch)) {
|
|
247
|
-
s.exp = null;
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
s.ext = true;
|
|
252
|
-
s.info = describe(ev);
|
|
253
|
-
};
|
|
254
|
-
state.handler = handler;
|
|
255
|
-
Object.defineProperty(window, KEY, { value: state, enumerable: false, configurable: true });
|
|
256
|
-
document.addEventListener('keydown', handler, true);
|
|
257
|
-
document.addEventListener('beforeinput', handler, true);
|
|
258
|
-
document.addEventListener('input', handler, true);
|
|
259
|
-
document.addEventListener('paste', handler, true);
|
|
260
|
-
return { text: readText(el) };
|
|
207
|
+
return `(() => {
|
|
208
|
+
const KEY = ${JSON.stringify(key)};
|
|
209
|
+
const findEl = () => {
|
|
210
|
+
const sel = ${selector};
|
|
211
|
+
if (sel) { try { const e = document.querySelector(sel); if (e) return e; } catch (err) {} }
|
|
212
|
+
const a = document.activeElement;
|
|
213
|
+
if (a && a !== document.body) return a;
|
|
214
|
+
return document.body;
|
|
215
|
+
};
|
|
216
|
+
const readText = (el) => {
|
|
217
|
+
try {
|
|
218
|
+
const monacoNs = typeof monaco !== 'undefined' ? monaco : window.monaco;
|
|
219
|
+
const editors = monacoNs && monacoNs.editor && monacoNs.editor.getEditors ? monacoNs.editor.getEditors() : null;
|
|
220
|
+
if (${isEditor} && editors && editors.length) return editors[editors.length - 1].getValue();
|
|
221
|
+
const cm6 = document.querySelector('.cm-content[contenteditable="true"]');
|
|
222
|
+
if (${isEditor} && cm6 && (cm6 === el || cm6.contains(el))) return cm6.innerText || '';
|
|
223
|
+
const cm5 = document.querySelector('.CodeMirror');
|
|
224
|
+
if (${isEditor} && cm5 && cm5.CodeMirror) return cm5.CodeMirror.getValue();
|
|
225
|
+
const ace = document.querySelector('.ace_editor');
|
|
226
|
+
if (${isEditor} && ace && ace.env && ace.env.editor) return ace.env.editor.getValue();
|
|
227
|
+
} catch (err) {}
|
|
228
|
+
if (!el) return '';
|
|
229
|
+
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') return el.value || '';
|
|
230
|
+
return el.innerText || el.textContent || '';
|
|
231
|
+
};
|
|
232
|
+
const el = findEl();
|
|
233
|
+
const state = { ext: false, info: '', exp: null, until: 0, el: el, handler: null };
|
|
234
|
+
const describe = (ev) => {
|
|
235
|
+
const t = ev.target && ev.target.tagName ? ev.target.tagName : '?';
|
|
236
|
+
const k = ev.key || ev.data || ev.inputType || ev.type;
|
|
237
|
+
return ev.type + ':' + t + ':' + String(k).slice(0, 24);
|
|
238
|
+
};
|
|
239
|
+
const handler = (ev) => {
|
|
240
|
+
const s = window[KEY];
|
|
241
|
+
if (!s) return;
|
|
242
|
+
const now = performance.now();
|
|
243
|
+
if (s.exp && now <= s.until) {
|
|
244
|
+
const k = ev.key || '';
|
|
245
|
+
const d = ev.data || '';
|
|
246
|
+
if ((s.exp.ch && d === s.exp.ch) || (s.exp.key && k === s.exp.key) || (s.exp.ch && k === s.exp.ch)) {
|
|
247
|
+
s.exp = null;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
s.ext = true;
|
|
252
|
+
s.info = describe(ev);
|
|
253
|
+
};
|
|
254
|
+
state.handler = handler;
|
|
255
|
+
Object.defineProperty(window, KEY, { value: state, enumerable: false, configurable: true });
|
|
256
|
+
document.addEventListener('keydown', handler, true);
|
|
257
|
+
document.addEventListener('beforeinput', handler, true);
|
|
258
|
+
document.addEventListener('input', handler, true);
|
|
259
|
+
document.addEventListener('paste', handler, true);
|
|
260
|
+
return { text: readText(el) };
|
|
261
261
|
})()`;
|
|
262
262
|
}
|
|
263
263
|
buildReadScript(key) {
|
|
264
|
-
return `(() => {
|
|
265
|
-
const s = window[${JSON.stringify(key)}];
|
|
266
|
-
if (!s) return null;
|
|
267
|
-
const el = s.el && document.contains(s.el) ? s.el : document.activeElement;
|
|
268
|
-
const read = (e) => {
|
|
269
|
-
try {
|
|
270
|
-
const monacoNs = typeof monaco !== 'undefined' ? monaco : window.monaco;
|
|
271
|
-
const editors = monacoNs && monacoNs.editor && monacoNs.editor.getEditors ? monacoNs.editor.getEditors() : null;
|
|
272
|
-
if (editors && editors.length) return editors[editors.length - 1].getValue();
|
|
273
|
-
const cm6 = document.querySelector('.cm-content[contenteditable="true"]');
|
|
274
|
-
if (cm6) return cm6.innerText || '';
|
|
275
|
-
const cm5 = document.querySelector('.CodeMirror');
|
|
276
|
-
if (cm5 && cm5.CodeMirror) return cm5.CodeMirror.getValue();
|
|
277
|
-
const ace = document.querySelector('.ace_editor');
|
|
278
|
-
if (ace && ace.env && ace.env.editor) return ace.env.editor.getValue();
|
|
279
|
-
} catch (err) {}
|
|
280
|
-
if (!e) return '';
|
|
281
|
-
if (e.tagName === 'INPUT' || e.tagName === 'TEXTAREA') return e.value || '';
|
|
282
|
-
return e.innerText || e.textContent || '';
|
|
283
|
-
};
|
|
284
|
-
const out = { text: read(el), external: s.ext === true, externalInfo: s.info || '' };
|
|
285
|
-
s.ext = false;
|
|
286
|
-
s.info = '';
|
|
287
|
-
return out;
|
|
264
|
+
return `(() => {
|
|
265
|
+
const s = window[${JSON.stringify(key)}];
|
|
266
|
+
if (!s) return null;
|
|
267
|
+
const el = s.el && document.contains(s.el) ? s.el : document.activeElement;
|
|
268
|
+
const read = (e) => {
|
|
269
|
+
try {
|
|
270
|
+
const monacoNs = typeof monaco !== 'undefined' ? monaco : window.monaco;
|
|
271
|
+
const editors = monacoNs && monacoNs.editor && monacoNs.editor.getEditors ? monacoNs.editor.getEditors() : null;
|
|
272
|
+
if (editors && editors.length) return editors[editors.length - 1].getValue();
|
|
273
|
+
const cm6 = document.querySelector('.cm-content[contenteditable="true"]');
|
|
274
|
+
if (cm6) return cm6.innerText || '';
|
|
275
|
+
const cm5 = document.querySelector('.CodeMirror');
|
|
276
|
+
if (cm5 && cm5.CodeMirror) return cm5.CodeMirror.getValue();
|
|
277
|
+
const ace = document.querySelector('.ace_editor');
|
|
278
|
+
if (ace && ace.env && ace.env.editor) return ace.env.editor.getValue();
|
|
279
|
+
} catch (err) {}
|
|
280
|
+
if (!e) return '';
|
|
281
|
+
if (e.tagName === 'INPUT' || e.tagName === 'TEXTAREA') return e.value || '';
|
|
282
|
+
return e.innerText || e.textContent || '';
|
|
283
|
+
};
|
|
284
|
+
const out = { text: read(el), external: s.ext === true, externalInfo: s.info || '' };
|
|
285
|
+
s.ext = false;
|
|
286
|
+
s.info = '';
|
|
287
|
+
return out;
|
|
288
288
|
})()`;
|
|
289
289
|
}
|
|
290
290
|
/**
|
|
@@ -62,66 +62,66 @@ function isMainFrameNavigation(params) {
|
|
|
62
62
|
* on the current document.
|
|
63
63
|
*/
|
|
64
64
|
function buildObserverScript() {
|
|
65
|
-
return `
|
|
66
|
-
(() => {
|
|
67
|
-
const KEY = Symbol('__ts_obs');
|
|
68
|
-
if (window[KEY]) return 'already attached';
|
|
69
|
-
const IGNORE = /timer|countdown|elapsed|clock|animation|animate|transition|spinner|progress|loading|toast|notification|alert|banner|snackbar|cookie|consent|modal|overlay|popup|tooltip|badge|tag|avatar|icon|svg|img|video|audio|canvas|font|stylesheet|script|meta|link|head/i;
|
|
70
|
-
const observerChangeScore = ${observerChangeScore.toString()};
|
|
71
|
-
let timer = null;
|
|
72
|
-
let lastText = '';
|
|
73
|
-
function getText() {
|
|
74
|
-
const els = document.querySelectorAll('input[type="radio"],input[type="checkbox"],input[type="text"],input[type="email"],input[type="password"],textarea,label,button');
|
|
75
|
-
return [...els].map(e => {
|
|
76
|
-
const t = (e.innerText || e.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 200);
|
|
77
|
-
return e.type + '|' + t + '|' + (e.checked || false);
|
|
78
|
-
}).join('\\n');
|
|
79
|
-
}
|
|
80
|
-
function check() {
|
|
81
|
-
try {
|
|
82
|
-
const curr = getText();
|
|
83
|
-
if (curr === lastText) return;
|
|
84
|
-
const prev = lastText;
|
|
85
|
-
lastText = curr;
|
|
86
|
-
if (observerChangeScore(prev, curr) >= ${exports.SCREEN_CHANGE_THRESHOLD}) {
|
|
87
|
-
window[KEY].changed = Date.now();
|
|
88
|
-
}
|
|
89
|
-
} catch {}
|
|
90
|
-
}
|
|
91
|
-
const obs = new MutationObserver((mutations) => {
|
|
92
|
-
let hasRelevant = false;
|
|
93
|
-
for (const m of mutations) {
|
|
94
|
-
if (m.target instanceof Element) {
|
|
95
|
-
const tag = m.target.tagName;
|
|
96
|
-
if (tag === 'SCRIPT' || tag === 'STYLE' || tag === 'HEAD') continue;
|
|
97
|
-
const cls = m.target.className || '';
|
|
98
|
-
if (typeof cls === 'string' && IGNORE.test(cls)) continue;
|
|
99
|
-
const id = m.target.id || '';
|
|
100
|
-
if (IGNORE.test(id)) continue;
|
|
101
|
-
if (m.type === 'characterData' && m.target.parentElement) {
|
|
102
|
-
const ptag = m.target.parentElement.tagName;
|
|
103
|
-
if (ptag === 'SCRIPT' || ptag === 'STYLE') continue;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
hasRelevant = true;
|
|
107
|
-
}
|
|
108
|
-
if (hasRelevant) {
|
|
109
|
-
// Raw "something relevant changed" stamp, set immediately (no
|
|
110
|
-
// debounce, no score gate). Used to verify that a click had ANY
|
|
111
|
-
// effect, including a selection that scores below the material
|
|
112
|
-
// threshold - without waiting for a full question swap.
|
|
113
|
-
window[KEY].mutated = Date.now();
|
|
114
|
-
clearTimeout(timer);
|
|
115
|
-
timer = setTimeout(check, 500);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
lastText = getText();
|
|
119
|
-
window[KEY] = { observer: obs, changed: 0, mutated: 0 };
|
|
120
|
-
obs.observe(document.body || document.documentElement, {
|
|
121
|
-
childList: true, subtree: true, characterData: true
|
|
122
|
-
});
|
|
123
|
-
return 'ok';
|
|
124
|
-
})()
|
|
65
|
+
return `
|
|
66
|
+
(() => {
|
|
67
|
+
const KEY = Symbol('__ts_obs');
|
|
68
|
+
if (window[KEY]) return 'already attached';
|
|
69
|
+
const IGNORE = /timer|countdown|elapsed|clock|animation|animate|transition|spinner|progress|loading|toast|notification|alert|banner|snackbar|cookie|consent|modal|overlay|popup|tooltip|badge|tag|avatar|icon|svg|img|video|audio|canvas|font|stylesheet|script|meta|link|head/i;
|
|
70
|
+
const observerChangeScore = ${observerChangeScore.toString()};
|
|
71
|
+
let timer = null;
|
|
72
|
+
let lastText = '';
|
|
73
|
+
function getText() {
|
|
74
|
+
const els = document.querySelectorAll('input[type="radio"],input[type="checkbox"],input[type="text"],input[type="email"],input[type="password"],textarea,label,button');
|
|
75
|
+
return [...els].map(e => {
|
|
76
|
+
const t = (e.innerText || e.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 200);
|
|
77
|
+
return e.type + '|' + t + '|' + (e.checked || false);
|
|
78
|
+
}).join('\\n');
|
|
79
|
+
}
|
|
80
|
+
function check() {
|
|
81
|
+
try {
|
|
82
|
+
const curr = getText();
|
|
83
|
+
if (curr === lastText) return;
|
|
84
|
+
const prev = lastText;
|
|
85
|
+
lastText = curr;
|
|
86
|
+
if (observerChangeScore(prev, curr) >= ${exports.SCREEN_CHANGE_THRESHOLD}) {
|
|
87
|
+
window[KEY].changed = Date.now();
|
|
88
|
+
}
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
const obs = new MutationObserver((mutations) => {
|
|
92
|
+
let hasRelevant = false;
|
|
93
|
+
for (const m of mutations) {
|
|
94
|
+
if (m.target instanceof Element) {
|
|
95
|
+
const tag = m.target.tagName;
|
|
96
|
+
if (tag === 'SCRIPT' || tag === 'STYLE' || tag === 'HEAD') continue;
|
|
97
|
+
const cls = m.target.className || '';
|
|
98
|
+
if (typeof cls === 'string' && IGNORE.test(cls)) continue;
|
|
99
|
+
const id = m.target.id || '';
|
|
100
|
+
if (IGNORE.test(id)) continue;
|
|
101
|
+
if (m.type === 'characterData' && m.target.parentElement) {
|
|
102
|
+
const ptag = m.target.parentElement.tagName;
|
|
103
|
+
if (ptag === 'SCRIPT' || ptag === 'STYLE') continue;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
hasRelevant = true;
|
|
107
|
+
}
|
|
108
|
+
if (hasRelevant) {
|
|
109
|
+
// Raw "something relevant changed" stamp, set immediately (no
|
|
110
|
+
// debounce, no score gate). Used to verify that a click had ANY
|
|
111
|
+
// effect, including a selection that scores below the material
|
|
112
|
+
// threshold - without waiting for a full question swap.
|
|
113
|
+
window[KEY].mutated = Date.now();
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
timer = setTimeout(check, 500);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
lastText = getText();
|
|
119
|
+
window[KEY] = { observer: obs, changed: 0, mutated: 0 };
|
|
120
|
+
obs.observe(document.body || document.documentElement, {
|
|
121
|
+
childList: true, subtree: true, characterData: true
|
|
122
|
+
});
|
|
123
|
+
return 'ok';
|
|
124
|
+
})()
|
|
125
125
|
`;
|
|
126
126
|
}
|
|
127
127
|
//# sourceMappingURL=screen-change.js.map
|
|
@@ -72,10 +72,10 @@ function readOpencode(dbPath, day, agentFilter) {
|
|
|
72
72
|
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
73
73
|
try {
|
|
74
74
|
const { startMs, endMs } = dayBounds(day);
|
|
75
|
-
const rows = db.prepare(`SELECT title, model, cost, tokens_input, tokens_output,
|
|
76
|
-
tokens_reasoning, tokens_cache_read, tokens_cache_write,
|
|
77
|
-
time_created, time_updated
|
|
78
|
-
FROM session WHERE time_created >= ? AND time_created < ?
|
|
75
|
+
const rows = db.prepare(`SELECT title, model, cost, tokens_input, tokens_output,
|
|
76
|
+
tokens_reasoning, tokens_cache_read, tokens_cache_write,
|
|
77
|
+
time_created, time_updated
|
|
78
|
+
FROM session WHERE time_created >= ? AND time_created < ?
|
|
79
79
|
ORDER BY time_created`).all(startMs, endMs);
|
|
80
80
|
const sessions = [];
|
|
81
81
|
for (const row of rows) {
|
|
@@ -30,3 +30,32 @@ export interface Classification {
|
|
|
30
30
|
* passthrough.
|
|
31
31
|
*/
|
|
32
32
|
export declare function classifyCommand(commandLine: string): Classification;
|
|
33
|
+
/**
|
|
34
|
+
* Why a command must not run in a READ-ONLY session, or null if it may (2026-10).
|
|
35
|
+
*
|
|
36
|
+
* ── WHY `cls.cls === 'exclusive'` IS NOT THE TEST ────────────────────────────
|
|
37
|
+
*
|
|
38
|
+
* The instinct is "exclusive means mutating, so refuse exclusive". That misses
|
|
39
|
+
* half of what actually writes: `git add`, `git commit`, `git push`, `git tag`
|
|
40
|
+
* and `git stash` are all classified **shared** (index.lock serializes them
|
|
41
|
+
* against other git writers, which is all that classification is about) and all
|
|
42
|
+
* of them mutate the working tree or the branch. A planning pass runs in the
|
|
43
|
+
* human's own linked folder, so "it got a shared classification" is not
|
|
44
|
+
* permission to commit on their branch.
|
|
45
|
+
*
|
|
46
|
+
* The rule this implements is the user's, stated as an invariant: **a plan must
|
|
47
|
+
* not have intrusive work.** Planning persists its deliverable over MCP
|
|
48
|
+
* (description, acceptance criteria, subtasks, checklist, a `plan.md` note) and
|
|
49
|
+
* reads the tree; it never needs to write to it. Because the bridge no longer
|
|
50
|
+
* serializes planning passes against each other (`NON_BLOCKING_PRESENCE_KINDS`),
|
|
51
|
+
* this is what makes that safe — the pass cannot touch the tree it shares.
|
|
52
|
+
*
|
|
53
|
+
* Deliberately a REFUSAL, not a queue. A shim that waited would hand an agent a
|
|
54
|
+
* command that succeeds minutes later, long after it reasoned about the tree; a
|
|
55
|
+
* refusal with a reason is something a planning agent can immediately adapt to
|
|
56
|
+
* ("use update_task instead").
|
|
57
|
+
*
|
|
58
|
+
* Shared commands that only read stay allowed, so a plan can still `git
|
|
59
|
+
* status`/`git log`/`git diff` and run read-only checks.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readOnlyRefusal(commandLine: string, cls: Classification): string | null;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.classifyCommand = classifyCommand;
|
|
15
|
+
exports.readOnlyRefusal = readOnlyRefusal;
|
|
15
16
|
const BUILD_SCRIPTS = new Set([
|
|
16
17
|
'build', 'compile', 'dist', 'package', 'generate', 'gen', 'prisma',
|
|
17
18
|
'migrate', 'seed', 'db:', 'prepare', 'prepack', 'postinstall', 'clean',
|
|
@@ -181,6 +182,67 @@ function classifyPrisma(rest) {
|
|
|
181
182
|
...(needsGlobal ? { global: ['prisma-generate'] } : {}),
|
|
182
183
|
};
|
|
183
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Why a command must not run in a READ-ONLY session, or null if it may (2026-10).
|
|
187
|
+
*
|
|
188
|
+
* ── WHY `cls.cls === 'exclusive'` IS NOT THE TEST ────────────────────────────
|
|
189
|
+
*
|
|
190
|
+
* The instinct is "exclusive means mutating, so refuse exclusive". That misses
|
|
191
|
+
* half of what actually writes: `git add`, `git commit`, `git push`, `git tag`
|
|
192
|
+
* and `git stash` are all classified **shared** (index.lock serializes them
|
|
193
|
+
* against other git writers, which is all that classification is about) and all
|
|
194
|
+
* of them mutate the working tree or the branch. A planning pass runs in the
|
|
195
|
+
* human's own linked folder, so "it got a shared classification" is not
|
|
196
|
+
* permission to commit on their branch.
|
|
197
|
+
*
|
|
198
|
+
* The rule this implements is the user's, stated as an invariant: **a plan must
|
|
199
|
+
* not have intrusive work.** Planning persists its deliverable over MCP
|
|
200
|
+
* (description, acceptance criteria, subtasks, checklist, a `plan.md` note) and
|
|
201
|
+
* reads the tree; it never needs to write to it. Because the bridge no longer
|
|
202
|
+
* serializes planning passes against each other (`NON_BLOCKING_PRESENCE_KINDS`),
|
|
203
|
+
* this is what makes that safe — the pass cannot touch the tree it shares.
|
|
204
|
+
*
|
|
205
|
+
* Deliberately a REFUSAL, not a queue. A shim that waited would hand an agent a
|
|
206
|
+
* command that succeeds minutes later, long after it reasoned about the tree; a
|
|
207
|
+
* refusal with a reason is something a planning agent can immediately adapt to
|
|
208
|
+
* ("use update_task instead").
|
|
209
|
+
*
|
|
210
|
+
* Shared commands that only read stay allowed, so a plan can still `git
|
|
211
|
+
* status`/`git log`/`git diff` and run read-only checks.
|
|
212
|
+
*/
|
|
213
|
+
function readOnlyRefusal(commandLine, cls) {
|
|
214
|
+
// Everything already known to rewrite tree/branch/install state.
|
|
215
|
+
if (cls.cls === 'exclusive')
|
|
216
|
+
return cls.label;
|
|
217
|
+
const { bin, rest } = base(commandLine);
|
|
218
|
+
if (bin !== 'git')
|
|
219
|
+
return null;
|
|
220
|
+
const sub = (rest[0] ?? '').toLowerCase();
|
|
221
|
+
const args = rest.slice(1).map((a) => a.toLowerCase());
|
|
222
|
+
if (GIT_WRITE_SUBS.has(sub)) {
|
|
223
|
+
// `git branch` only writes with -d/-D/-m/-M; `git stash` only writes for
|
|
224
|
+
// anything other than list/show. Both are read in their common form.
|
|
225
|
+
if (sub === 'branch' && !args.some((a) => ['-d', '-D', '-m', '-M', '--delete', '--move'].includes(a))) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
if (sub === 'stash' && args[0] && ['list', 'show'].includes(args[0])) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
// A BARE `git stash` saves the working tree, so it is a write with no flag to
|
|
232
|
+
// carve it out - unlike `classifyGit`, which treats it as shared.
|
|
233
|
+
return `git ${sub}`;
|
|
234
|
+
}
|
|
235
|
+
if (GIT_WRITE_SUBS_ALWAYS.has(sub))
|
|
236
|
+
return `git ${sub}`;
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* git subcommands classified `shared` (so they run concurrently) that STILL
|
|
241
|
+
* write. See {@link readOnlyRefusal}.
|
|
242
|
+
*/
|
|
243
|
+
const GIT_WRITE_SUBS = new Set(['add', 'commit', 'push', 'tag', 'branch', 'stash']);
|
|
244
|
+
/** Write in every form — no read-only invocation to carve out. */
|
|
245
|
+
const GIT_WRITE_SUBS_ALWAYS = new Set(['update-ref', 'notes', 'am']);
|
|
184
246
|
function classifyGit(rest) {
|
|
185
247
|
const sub = (rest[0] ?? '').toLowerCase();
|
|
186
248
|
if (GIT_EXCLUSIVE.has(sub))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../../src/lib/workspace/classify.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AA2DH,0CA+CC;
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../../src/lib/workspace/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,37 @@ export declare function listPresent(path: string): PresenceEntry[];
|
|
|
30
30
|
export declare function registerPresence(path: string, info?: Omit<PresenceEntry, 'pid' | 'startedAt' | 'updatedAt'>): void;
|
|
31
31
|
/** Remove THIS process from the folder's registry. */
|
|
32
32
|
export declare function unregisterPresence(path: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Kinds that occupy a folder WITHOUT excluding anyone (2026-10).
|
|
35
|
+
*
|
|
36
|
+
* ── WHY A PLAN PASS IS NOT AN OCCUPANT ───────────────────────────────────────
|
|
37
|
+
*
|
|
38
|
+
* A planning pass runs no git pipeline — no branch, no stash, no commit, no
|
|
39
|
+
* push (that is the whole reason `preflightWake` gives it `needsMirror: false`
|
|
40
|
+
* and it works in the linked folder). It reads the tree and writes NOTHING to it:
|
|
41
|
+
* the deliverable is the task's description, acceptance criteria, subtasks,
|
|
42
|
+
* checklist and a `plan.md` note, all persisted over MCP.
|
|
43
|
+
*
|
|
44
|
+
* It nevertheless registered `presence`, and the folder-serialization gate
|
|
45
|
+
* treated any presence row as exclusive. So two agents planning in one folder
|
|
46
|
+
* locked each other out — and because the queue that gate pushed into was never
|
|
47
|
+
* drained (see `wake-handler.ts`), the loser did not wait, it was **lost**. That
|
|
48
|
+
* is the incident behind this set: a human pressed "Improve plan" twice and saw
|
|
49
|
+
* two `Wake received` rows and no work.
|
|
50
|
+
*
|
|
51
|
+
* So a plan is CONCURRENT by construction. This is only safe because a plan is
|
|
52
|
+
* also mechanically read-only: the session runs with `TS_READ_ONLY=1`, which
|
|
53
|
+
* makes the arbitration shims REFUSE every mutating command instead of queueing
|
|
54
|
+
* it (`shim-runner.ts` + `classify.ts#readOnlyRefusal`). A plan that cannot
|
|
55
|
+
* write cannot corrupt the tree it shares, so it has no reason to exclude
|
|
56
|
+
* anyone — and no reason to be excluded.
|
|
57
|
+
*
|
|
58
|
+
* Keep this set and `TS_READ_ONLY` in step. Adding a kind here is a claim that
|
|
59
|
+
* the session writes nothing; if that is not enforced, it is a bug.
|
|
60
|
+
*/
|
|
61
|
+
export declare const NON_BLOCKING_PRESENCE_KINDS: ReadonlySet<string>;
|
|
62
|
+
/** True when this occupant excludes other sessions from the folder. */
|
|
63
|
+
export declare function presenceBlocks(entry: Pick<PresenceEntry, 'kind'>): boolean;
|
|
33
64
|
/**
|
|
34
65
|
* True when at least one OTHER live process occupies the folder. Used by the
|
|
35
66
|
* daemon's auto-worktree escalation ("second agent showed up") and by
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PRESENCE_HEARTBEAT_MS = exports.PRESENCE_TTL_MS = void 0;
|
|
3
|
+
exports.NON_BLOCKING_PRESENCE_KINDS = exports.PRESENCE_HEARTBEAT_MS = exports.PRESENCE_TTL_MS = void 0;
|
|
4
4
|
exports.listPresent = listPresent;
|
|
5
5
|
exports.registerPresence = registerPresence;
|
|
6
6
|
exports.unregisterPresence = unregisterPresence;
|
|
7
|
+
exports.presenceBlocks = presenceBlocks;
|
|
7
8
|
exports.hasOtherOccupants = hasOtherOccupants;
|
|
8
9
|
/**
|
|
9
10
|
* Presence registry (IMP-950): who is working WHERE right now.
|
|
@@ -167,6 +168,39 @@ function unregisterPresence(path) {
|
|
|
167
168
|
/* best-effort */
|
|
168
169
|
}
|
|
169
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Kinds that occupy a folder WITHOUT excluding anyone (2026-10).
|
|
173
|
+
*
|
|
174
|
+
* ── WHY A PLAN PASS IS NOT AN OCCUPANT ───────────────────────────────────────
|
|
175
|
+
*
|
|
176
|
+
* A planning pass runs no git pipeline — no branch, no stash, no commit, no
|
|
177
|
+
* push (that is the whole reason `preflightWake` gives it `needsMirror: false`
|
|
178
|
+
* and it works in the linked folder). It reads the tree and writes NOTHING to it:
|
|
179
|
+
* the deliverable is the task's description, acceptance criteria, subtasks,
|
|
180
|
+
* checklist and a `plan.md` note, all persisted over MCP.
|
|
181
|
+
*
|
|
182
|
+
* It nevertheless registered `presence`, and the folder-serialization gate
|
|
183
|
+
* treated any presence row as exclusive. So two agents planning in one folder
|
|
184
|
+
* locked each other out — and because the queue that gate pushed into was never
|
|
185
|
+
* drained (see `wake-handler.ts`), the loser did not wait, it was **lost**. That
|
|
186
|
+
* is the incident behind this set: a human pressed "Improve plan" twice and saw
|
|
187
|
+
* two `Wake received` rows and no work.
|
|
188
|
+
*
|
|
189
|
+
* So a plan is CONCURRENT by construction. This is only safe because a plan is
|
|
190
|
+
* also mechanically read-only: the session runs with `TS_READ_ONLY=1`, which
|
|
191
|
+
* makes the arbitration shims REFUSE every mutating command instead of queueing
|
|
192
|
+
* it (`shim-runner.ts` + `classify.ts#readOnlyRefusal`). A plan that cannot
|
|
193
|
+
* write cannot corrupt the tree it shares, so it has no reason to exclude
|
|
194
|
+
* anyone — and no reason to be excluded.
|
|
195
|
+
*
|
|
196
|
+
* Keep this set and `TS_READ_ONLY` in step. Adding a kind here is a claim that
|
|
197
|
+
* the session writes nothing; if that is not enforced, it is a bug.
|
|
198
|
+
*/
|
|
199
|
+
exports.NON_BLOCKING_PRESENCE_KINDS = new Set(['plan']);
|
|
200
|
+
/** True when this occupant excludes other sessions from the folder. */
|
|
201
|
+
function presenceBlocks(entry) {
|
|
202
|
+
return !exports.NON_BLOCKING_PRESENCE_KINDS.has(String(entry.kind ?? ''));
|
|
203
|
+
}
|
|
170
204
|
/**
|
|
171
205
|
* True when at least one OTHER live process occupies the folder. Used by the
|
|
172
206
|
* daemon's auto-worktree escalation ("second agent showed up") and by
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../../src/lib/workspace/presence.ts"],"names":[],"mappings":";;;AAsHA,kCAIC;AAeD,4CA8BC;AAGD,gDAQC;AAOD,8CAEC;
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../../src/lib/workspace/presence.ts"],"names":[],"mappings":"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"}
|