app
Adom Browser Extension
Public Made by Adomby adom
Your AI's hands in your real, signed-in browser. The Adom Browser Extension (abe) works with both Chrome and Edge: build, drive, and test web apps, and log past vendor walls, in the browser you already use - cookies, SSO, saved logins and captcha trust intact. The nbrowser_* bridge (pup's counterpart) runs in your actual logged-in profile.
#!/usr/bin/env node
// Guard/hint coverage gate. Every verb dispatched in sw.js MUST be classified in
// tools/verbs-policy.json, and every 'mutating' verb MUST be wired through the ownership
// guard (its `verb: 'nbrowser_x'` requireOwned tag must appear in the source). A new verb
// that isn't classified — or a mutating verb that isn't gated — fails this check, so the
// safety doctrine can't silently decay as the surface grows. Run: node tools/check-guard-coverage.mjs
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
const sw = readFileSync(join(root, 'extension/src/sw.js'), 'utf8');
const native = readFileSync(join(root, 'extension/src/native.js'), 'utf8');
const server = readFileSync(join(root, 'bridge/server.js'), 'utf8');
const policy = JSON.parse(readFileSync(join(root, 'tools/verbs-policy.json'), 'utf8'));
const dispatched = [...new Set([...sw.matchAll(/case 'nbrowser_([a-z_]+)'/g)].map((m) => m[1]))];
const src = sw + native;
const errors = [];
// Parse the VERB_META table: verb -> its (single-line) entry text, so we can assert HINT COVERAGE — every
// verb an AI can call must ship a non-empty hint + non-empty pitfalls, or the AI is left guessing.
const metaEntry = new Map([...server.matchAll(/^ {2}nbrowser_([a-z_]+): (\{.*\}),?\s*$/gm)].map((m) => [m[1], m[2]]));
for (const verb of dispatched) {
const cls = policy[verb];
if (!cls) { errors.push(`UNCLASSIFIED verb 'nbrowser_${verb}' — add it to tools/verbs-policy.json (readonly|meta|mutating|owned_implicit|global|alias)`); continue; }
if (cls === 'mutating' && !src.includes(`verb: 'nbrowser_${verb}'`)) {
errors.push(`UNGATED mutating verb 'nbrowser_${verb}' — its resolveTabId call must pass { requireOwned: true, verb: 'nbrowser_${verb}' }`);
}
if (cls === 'alias') continue; // aliases inherit the canonical verb's hint
const entry = metaEntry.get(verb);
if (!entry) { errors.push(`NO HINT: verb 'nbrowser_${verb}' has no VERB_META entry in bridge/server.js — add { hint, related, pitfalls } so the AI knows what it does / what next / the traps`); continue; }
if (/hint:\s*(''|"")/.test(entry) || !/hint:/.test(entry)) errors.push(`EMPTY HINT: 'nbrowser_${verb}' VERB_META has no hint`);
if (/pitfalls:\s*\[\s*\]/.test(entry)) errors.push(`EMPTY PITFALLS: 'nbrowser_${verb}' VERB_META has pitfalls:[] — add at least one trap the AI should avoid`);
}
for (const verb of Object.keys(policy)) {
if (!dispatched.includes(verb)) errors.push(`STALE policy entry 'nbrowser_${verb}' — not dispatched in sw.js`);
}
if (errors.length) { console.error('guard-coverage FAILED:\n ' + errors.join('\n ')); process.exit(1); }
console.log(`guard-coverage OK: ${dispatched.length} verbs classified, ${Object.values(policy).filter((c) => c === 'mutating').length} mutating verbs gated, ${dispatched.filter((v) => policy[v] !== 'alias').length} verbs with non-empty hint + pitfalls`);