@tangle-network/browser-agent-driver 0.30.0 → 0.31.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/dist/cli-ack-patch.d.ts +39 -0
- package/dist/cli-ack-patch.d.ts.map +1 -0
- package/dist/cli-ack-patch.js +47 -0
- package/dist/cli-ack-patch.js.map +1 -0
- package/dist/cli-design-audit.d.ts +12 -0
- package/dist/cli-design-audit.d.ts.map +1 -1
- package/dist/cli-design-audit.js +88 -0
- package/dist/cli-design-audit.js.map +1 -1
- package/dist/cli-jobs.d.ts +13 -0
- package/dist/cli-jobs.d.ts.map +1 -0
- package/dist/cli-jobs.js +262 -0
- package/dist/cli-jobs.js.map +1 -0
- package/dist/cli-patterns.d.ts +26 -0
- package/dist/cli-patterns.d.ts.map +1 -0
- package/dist/cli-patterns.js +49 -0
- package/dist/cli-patterns.js.map +1 -0
- package/dist/cli-reports.d.ts +12 -0
- package/dist/cli-reports.d.ts.map +1 -0
- package/dist/cli-reports.js +97 -0
- package/dist/cli-reports.js.map +1 -0
- package/dist/cli.js +29 -1
- package/dist/cli.js.map +1 -1
- package/dist/design/audit/attribution/aggregate.d.ts +16 -0
- package/dist/design/audit/attribution/aggregate.d.ts.map +1 -0
- package/dist/design/audit/attribution/aggregate.js +81 -0
- package/dist/design/audit/attribution/aggregate.js.map +1 -0
- package/dist/design/audit/attribution/store.d.ts +36 -0
- package/dist/design/audit/attribution/store.d.ts.map +1 -0
- package/dist/design/audit/attribution/store.js +108 -0
- package/dist/design/audit/attribution/store.js.map +1 -0
- package/dist/design/audit/attribution/types.d.ts +13 -0
- package/dist/design/audit/attribution/types.d.ts.map +1 -0
- package/dist/design/audit/attribution/types.js +10 -0
- package/dist/design/audit/attribution/types.js.map +1 -0
- package/dist/design/audit/classify-ensemble.d.ts +46 -0
- package/dist/design/audit/classify-ensemble.d.ts.map +1 -0
- package/dist/design/audit/classify-ensemble.js +207 -0
- package/dist/design/audit/classify-ensemble.js.map +1 -0
- package/dist/design/audit/ethics/check.d.ts +59 -0
- package/dist/design/audit/ethics/check.d.ts.map +1 -0
- package/dist/design/audit/ethics/check.js +137 -0
- package/dist/design/audit/ethics/check.js.map +1 -0
- package/dist/design/audit/ethics/loader.d.ts +21 -0
- package/dist/design/audit/ethics/loader.d.ts.map +1 -0
- package/dist/design/audit/ethics/loader.js +207 -0
- package/dist/design/audit/ethics/loader.js.map +1 -0
- package/dist/design/audit/ethics/rules/finance.yaml +37 -0
- package/dist/design/audit/ethics/rules/kids.yaml +37 -0
- package/dist/design/audit/ethics/rules/legal.yaml +35 -0
- package/dist/design/audit/ethics/rules/medical.yaml +36 -0
- package/dist/design/audit/evaluate.d.ts.map +1 -1
- package/dist/design/audit/evaluate.js +4 -1
- package/dist/design/audit/evaluate.js.map +1 -1
- package/dist/design/audit/first-principles-mode.d.ts +42 -0
- package/dist/design/audit/first-principles-mode.d.ts.map +1 -0
- package/dist/design/audit/first-principles-mode.js +77 -0
- package/dist/design/audit/first-principles-mode.js.map +1 -0
- package/dist/design/audit/modality/android.d.ts +14 -0
- package/dist/design/audit/modality/android.d.ts.map +1 -0
- package/dist/design/audit/modality/android.js +18 -0
- package/dist/design/audit/modality/android.js.map +1 -0
- package/dist/design/audit/modality/html.d.ts +22 -0
- package/dist/design/audit/modality/html.d.ts.map +1 -0
- package/dist/design/audit/modality/html.js +51 -0
- package/dist/design/audit/modality/html.js.map +1 -0
- package/dist/design/audit/modality/index.d.ts +8 -0
- package/dist/design/audit/modality/index.d.ts.map +1 -0
- package/dist/design/audit/modality/index.js +15 -0
- package/dist/design/audit/modality/index.js.map +1 -0
- package/dist/design/audit/modality/ios.d.ts +16 -0
- package/dist/design/audit/modality/ios.d.ts.map +1 -0
- package/dist/design/audit/modality/ios.js +19 -0
- package/dist/design/audit/modality/ios.js.map +1 -0
- package/dist/design/audit/modality/types.d.ts +9 -0
- package/dist/design/audit/modality/types.d.ts.map +1 -0
- package/dist/design/audit/modality/types.js +9 -0
- package/dist/design/audit/modality/types.js.map +1 -0
- package/dist/design/audit/patches/index.d.ts +8 -0
- package/dist/design/audit/patches/index.d.ts.map +1 -0
- package/dist/design/audit/patches/index.js +5 -0
- package/dist/design/audit/patches/index.js.map +1 -0
- package/dist/design/audit/patches/parse.d.ts +29 -0
- package/dist/design/audit/patches/parse.d.ts.map +1 -0
- package/dist/design/audit/patches/parse.js +153 -0
- package/dist/design/audit/patches/parse.js.map +1 -0
- package/dist/design/audit/patches/render.d.ts +20 -0
- package/dist/design/audit/patches/render.d.ts.map +1 -0
- package/dist/design/audit/patches/render.js +55 -0
- package/dist/design/audit/patches/render.js.map +1 -0
- package/dist/design/audit/patches/severity-enforcement.d.ts +23 -0
- package/dist/design/audit/patches/severity-enforcement.d.ts.map +1 -0
- package/dist/design/audit/patches/severity-enforcement.js +42 -0
- package/dist/design/audit/patches/severity-enforcement.js.map +1 -0
- package/dist/design/audit/patches/validate.d.ts +34 -0
- package/dist/design/audit/patches/validate.d.ts.map +1 -0
- package/dist/design/audit/patches/validate.js +53 -0
- package/dist/design/audit/patches/validate.js.map +1 -0
- package/dist/design/audit/patterns/match.d.ts +24 -0
- package/dist/design/audit/patterns/match.d.ts.map +1 -0
- package/dist/design/audit/patterns/match.js +48 -0
- package/dist/design/audit/patterns/match.js.map +1 -0
- package/dist/design/audit/patterns/mine.d.ts +31 -0
- package/dist/design/audit/patterns/mine.d.ts.map +1 -0
- package/dist/design/audit/patterns/mine.js +35 -0
- package/dist/design/audit/patterns/mine.js.map +1 -0
- package/dist/design/audit/patterns/store.d.ts +14 -0
- package/dist/design/audit/patterns/store.d.ts.map +1 -0
- package/dist/design/audit/patterns/store.js +53 -0
- package/dist/design/audit/patterns/store.js.map +1 -0
- package/dist/design/audit/patterns/types.d.ts +53 -0
- package/dist/design/audit/patterns/types.d.ts.map +1 -0
- package/dist/design/audit/patterns/types.js +13 -0
- package/dist/design/audit/patterns/types.js.map +1 -0
- package/dist/design/audit/pipeline.d.ts +12 -0
- package/dist/design/audit/pipeline.d.ts.map +1 -1
- package/dist/design/audit/pipeline.js +65 -3
- package/dist/design/audit/pipeline.js.map +1 -1
- package/dist/design/audit/rubric/anchor-loader.d.ts +44 -0
- package/dist/design/audit/rubric/anchor-loader.d.ts.map +1 -0
- package/dist/design/audit/rubric/anchor-loader.js +210 -0
- package/dist/design/audit/rubric/anchor-loader.js.map +1 -0
- package/dist/design/audit/rubric/anchors/blog.yaml +33 -0
- package/dist/design/audit/rubric/anchors/dashboard.yaml +35 -0
- package/dist/design/audit/rubric/anchors/docs.yaml +35 -0
- package/dist/design/audit/rubric/anchors/ecommerce.yaml +33 -0
- package/dist/design/audit/rubric/anchors/marketing.yaml +34 -0
- package/dist/design/audit/rubric/anchors/saas-app.yaml +38 -0
- package/dist/design/audit/rubric/anchors/social.yaml +33 -0
- package/dist/design/audit/rubric/anchors/tool.yaml +33 -0
- package/dist/design/audit/rubric/anchors/utility.yaml +33 -0
- package/dist/design/audit/rubric/fragments/audience-clinician.md +42 -0
- package/dist/design/audit/rubric/fragments/audience-developer.md +40 -0
- package/dist/design/audit/rubric/fragments/audience-kids.md +35 -0
- package/dist/design/audit/rubric/fragments/audience-vulnerability-minor-facing.md +37 -0
- package/dist/design/audit/rubric/fragments/first-principles.md +65 -0
- package/dist/design/audit/rubric/fragments/modality-mobile.md +39 -0
- package/dist/design/audit/rubric/fragments/modality-tablet.md +35 -0
- package/dist/design/audit/rubric/fragments/regulatory-coppa.md +32 -0
- package/dist/design/audit/rubric/fragments/regulatory-gdpr.md +33 -0
- package/dist/design/audit/rubric/fragments/regulatory-hipaa.md +36 -0
- package/dist/design/audit/rubric/loader.d.ts +26 -6
- package/dist/design/audit/rubric/loader.d.ts.map +1 -1
- package/dist/design/audit/rubric/loader.js +45 -26
- package/dist/design/audit/rubric/loader.js.map +1 -1
- package/dist/design/audit/rubric/rollup-weights.d.ts +25 -0
- package/dist/design/audit/rubric/rollup-weights.d.ts.map +1 -0
- package/dist/design/audit/rubric/rollup-weights.js +51 -0
- package/dist/design/audit/rubric/rollup-weights.js.map +1 -0
- package/dist/design/audit/types.d.ts +28 -0
- package/dist/design/audit/types.d.ts.map +1 -1
- package/dist/design/audit/v2/build-result.d.ts +47 -0
- package/dist/design/audit/v2/build-result.d.ts.map +1 -0
- package/dist/design/audit/v2/build-result.js +163 -0
- package/dist/design/audit/v2/build-result.js.map +1 -0
- package/dist/design/audit/v2/score.d.ts +49 -0
- package/dist/design/audit/v2/score.d.ts.map +1 -0
- package/dist/design/audit/v2/score.js +211 -0
- package/dist/design/audit/v2/score.js.map +1 -0
- package/dist/design/audit/v2/types.d.ts +431 -0
- package/dist/design/audit/v2/types.d.ts.map +1 -0
- package/dist/design/audit/v2/types.js +26 -0
- package/dist/design/audit/v2/types.js.map +1 -0
- package/dist/discover/index.d.ts +16 -0
- package/dist/discover/index.d.ts.map +1 -0
- package/dist/discover/index.js +25 -0
- package/dist/discover/index.js.map +1 -0
- package/dist/discover/wayback.d.ts +49 -0
- package/dist/discover/wayback.d.ts.map +1 -0
- package/dist/discover/wayback.js +123 -0
- package/dist/discover/wayback.js.map +1 -0
- package/dist/jobs/anti-bot.d.ts +19 -0
- package/dist/jobs/anti-bot.d.ts.map +1 -0
- package/dist/jobs/anti-bot.js +64 -0
- package/dist/jobs/anti-bot.js.map +1 -0
- package/dist/jobs/cost-estimate.d.ts +12 -0
- package/dist/jobs/cost-estimate.d.ts.map +1 -0
- package/dist/jobs/cost-estimate.js +21 -0
- package/dist/jobs/cost-estimate.js.map +1 -0
- package/dist/jobs/cost-history.d.ts +19 -0
- package/dist/jobs/cost-history.d.ts.map +1 -0
- package/dist/jobs/cost-history.js +42 -0
- package/dist/jobs/cost-history.js.map +1 -0
- package/dist/jobs/index.d.ts +31 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +37 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/orchestrator.d.ts +42 -0
- package/dist/jobs/orchestrator.d.ts.map +1 -0
- package/dist/jobs/orchestrator.js +282 -0
- package/dist/jobs/orchestrator.js.map +1 -0
- package/dist/jobs/queue.d.ts +45 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +114 -0
- package/dist/jobs/queue.js.map +1 -0
- package/dist/jobs/retry.d.ts +36 -0
- package/dist/jobs/retry.d.ts.map +1 -0
- package/dist/jobs/retry.js +77 -0
- package/dist/jobs/retry.js.map +1 -0
- package/dist/jobs/store.d.ts +31 -0
- package/dist/jobs/store.d.ts.map +1 -0
- package/dist/jobs/store.js +92 -0
- package/dist/jobs/store.js.map +1 -0
- package/dist/jobs/types.d.ts +106 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +13 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/reports/aggregate.d.ts +38 -0
- package/dist/reports/aggregate.d.ts.map +1 -0
- package/dist/reports/aggregate.js +145 -0
- package/dist/reports/aggregate.js.map +1 -0
- package/dist/reports/index.d.ts +21 -0
- package/dist/reports/index.d.ts.map +1 -0
- package/dist/reports/index.js +15 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/narrate.d.ts +19 -0
- package/dist/reports/narrate.d.ts.map +1 -0
- package/dist/reports/narrate.js +40 -0
- package/dist/reports/narrate.js.map +1 -0
- package/dist/reports/templates.d.ts +43 -0
- package/dist/reports/templates.d.ts.map +1 -0
- package/dist/reports/templates.js +200 -0
- package/dist/reports/templates.js.map +1 -0
- package/dist/reports/tokens.d.ts +77 -0
- package/dist/reports/tokens.d.ts.map +1 -0
- package/dist/reports/tokens.js +88 -0
- package/dist/reports/tokens.js.map +1 -0
- package/dist/reports/tools.d.ts +76 -0
- package/dist/reports/tools.d.ts.map +1 -0
- package/dist/reports/tools.js +205 -0
- package/dist/reports/tools.js.map +1 -0
- package/dist/reports/types.d.ts +51 -0
- package/dist/reports/types.d.ts.map +1 -0
- package/dist/reports/types.js +9 -0
- package/dist/reports/types.js.map +1 -0
- package/package.json +2 -1
package/dist/cli-jobs.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bad jobs` — declarative comparative-audit jobs.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
* bad jobs create --spec <file.json> # mints a job from a JSON spec, runs it
|
|
6
|
+
* bad jobs status <jobId> [--json] # show a job's current state
|
|
7
|
+
* bad jobs list [--json] # recent jobs
|
|
8
|
+
* bad jobs estimate --spec <file.json> # pre-flight cost estimate, no execution
|
|
9
|
+
*
|
|
10
|
+
* The spec file is JSON (no yaml dep). See `JobSpec` in src/jobs/types.ts.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import chalk from 'chalk';
|
|
15
|
+
import { cliError } from './cli-ui.js';
|
|
16
|
+
import { discoverTargets } from './discover/index.js';
|
|
17
|
+
function die(msg) {
|
|
18
|
+
cliError(msg);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
import { createJob, runJob, loadJob, listJobs, estimateCost, } from './jobs/index.js';
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = {};
|
|
24
|
+
for (let i = 0; i < argv.length; i++) {
|
|
25
|
+
const a = argv[i];
|
|
26
|
+
if (a === '--spec')
|
|
27
|
+
out.spec = argv[++i];
|
|
28
|
+
else if (a === '--json')
|
|
29
|
+
out.json = true;
|
|
30
|
+
else if (a === '--yes' || a === '-y')
|
|
31
|
+
out.yes = true;
|
|
32
|
+
else if (a === '--max-iterations')
|
|
33
|
+
out.maxIterations = Number(argv[++i]);
|
|
34
|
+
else if (!a.startsWith('-') && !out.jobId)
|
|
35
|
+
out.jobId = a;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function readSpec(specPath) {
|
|
40
|
+
if (!fs.existsSync(specPath))
|
|
41
|
+
die(`spec file not found: ${specPath}`);
|
|
42
|
+
const raw = fs.readFileSync(specPath, 'utf-8');
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(raw);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
die(`spec file is not valid JSON: ${err.message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function runJobsCli(args) {
|
|
51
|
+
const sub = args[0];
|
|
52
|
+
const rest = args.slice(1);
|
|
53
|
+
const opts = parseArgs(rest);
|
|
54
|
+
if (sub === 'list')
|
|
55
|
+
return cmdList(opts);
|
|
56
|
+
if (sub === 'status')
|
|
57
|
+
return cmdStatus(opts);
|
|
58
|
+
if (sub === 'estimate')
|
|
59
|
+
return cmdEstimate(opts);
|
|
60
|
+
if (sub === 'create')
|
|
61
|
+
return cmdCreate(opts);
|
|
62
|
+
if (sub === 'resume')
|
|
63
|
+
return cmdResume(opts);
|
|
64
|
+
if (sub === 'orchestrate')
|
|
65
|
+
return cmdOrchestrate(opts);
|
|
66
|
+
die(`Unknown subcommand: ${sub}. Use create | list | status | estimate | resume | orchestrate.`);
|
|
67
|
+
}
|
|
68
|
+
function cmdList(opts) {
|
|
69
|
+
const entries = listJobs();
|
|
70
|
+
if (opts.json) {
|
|
71
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (entries.length === 0) {
|
|
75
|
+
console.log(chalk.dim('No jobs yet. Try `bad jobs create --spec <file>`.'));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (const e of entries.slice(0, 50)) {
|
|
79
|
+
const status = e.status === 'completed' ? chalk.green(e.status)
|
|
80
|
+
: e.status === 'failed' || e.status === 'cancelled' ? chalk.red(e.status)
|
|
81
|
+
: e.status === 'partial' ? chalk.yellow(e.status)
|
|
82
|
+
: chalk.dim(e.status);
|
|
83
|
+
console.log(` ${e.jobId} ${status} targets=${e.targetCount} ${chalk.dim(e.createdAt)} ${e.label ?? ''}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function cmdStatus(opts) {
|
|
87
|
+
if (!opts.jobId)
|
|
88
|
+
die('jobId is required: bad jobs status <jobId>');
|
|
89
|
+
const job = loadJob(opts.jobId);
|
|
90
|
+
if (!job)
|
|
91
|
+
die(`job not found: ${opts.jobId}`);
|
|
92
|
+
if (opts.json) {
|
|
93
|
+
console.log(JSON.stringify(job, null, 2));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const ok = job.results.filter(r => r.status === 'ok').length;
|
|
97
|
+
const failed = job.results.filter(r => r.status === 'failed').length;
|
|
98
|
+
console.log(` ${chalk.bold(job.jobId)} ${chalk.dim(job.status)}`);
|
|
99
|
+
if (job.spec.label)
|
|
100
|
+
console.log(` label: ${job.spec.label}`);
|
|
101
|
+
console.log(` targets: ${job.targets.length} · ok: ${ok} · failed: ${failed}`);
|
|
102
|
+
console.log(` cost: $${job.totalCostUSD.toFixed(2)}`);
|
|
103
|
+
console.log(` created: ${job.createdAt}`);
|
|
104
|
+
if (job.completedAt)
|
|
105
|
+
console.log(` completed: ${job.completedAt}`);
|
|
106
|
+
}
|
|
107
|
+
async function cmdEstimate(opts) {
|
|
108
|
+
if (!opts.spec)
|
|
109
|
+
die('--spec is required for estimate');
|
|
110
|
+
const spec = readSpec(opts.spec);
|
|
111
|
+
const targets = await discoverTargets(spec.discover);
|
|
112
|
+
const { computePerAuditFromHistory } = await import('./jobs/cost-history.js');
|
|
113
|
+
const adaptive = computePerAuditFromHistory();
|
|
114
|
+
const est = estimateCost(spec, targets.length, adaptive.perAuditUSD);
|
|
115
|
+
if (opts.json) {
|
|
116
|
+
console.log(JSON.stringify({ spec, ...est, costSource: adaptive.source, jobsObserved: adaptive.jobsObserved }, null, 2));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
console.log(` Targets: ${est.targetCount}`);
|
|
120
|
+
console.log(` Per-audit: $${est.perAuditUSD.toFixed(2)} ${chalk.dim(`(${adaptive.source}${adaptive.source === 'history' ? `, n=${adaptive.targetsObserved}` : ''})`)}`);
|
|
121
|
+
console.log(` Estimated total: $${est.estimatedTotalUSD.toFixed(2)}`);
|
|
122
|
+
if (est.exceedsCap && spec.maxCostUSD !== undefined) {
|
|
123
|
+
console.log(chalk.yellow(` ⚠ exceeds cap of $${spec.maxCostUSD.toFixed(2)}`));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function cmdCreate(opts) {
|
|
127
|
+
if (!opts.spec)
|
|
128
|
+
die('--spec is required: bad jobs create --spec <file.json>');
|
|
129
|
+
const spec = readSpec(opts.spec);
|
|
130
|
+
const targets = await discoverTargets(spec.discover);
|
|
131
|
+
if (targets.length === 0)
|
|
132
|
+
die('discover yielded zero targets — check your URLs / wayback range');
|
|
133
|
+
const est = estimateCost(spec, targets.length);
|
|
134
|
+
console.log(` Targets discovered: ${targets.length}`);
|
|
135
|
+
console.log(` Estimated cost: $${est.estimatedTotalUSD.toFixed(2)}`);
|
|
136
|
+
if (est.exceedsCap && spec.maxCostUSD !== undefined) {
|
|
137
|
+
die(`Estimated cost $${est.estimatedTotalUSD.toFixed(2)} exceeds maxCostUSD $${spec.maxCostUSD.toFixed(2)}. Raise the cap or shrink the job.`);
|
|
138
|
+
}
|
|
139
|
+
const job = createJob(spec, targets);
|
|
140
|
+
console.log(` Created job ${chalk.bold(job.jobId)}`);
|
|
141
|
+
const auditFn = await buildAuditFn(spec);
|
|
142
|
+
await runJob(job, { auditFn });
|
|
143
|
+
const final = loadJob(job.jobId);
|
|
144
|
+
console.log(` Status: ${chalk.bold(final?.status ?? 'unknown')} · ok: ${final?.results.filter(r => r.status === 'ok').length ?? 0}/${final?.targets.length ?? 0} · $${final?.totalCostUSD.toFixed(2)}`);
|
|
145
|
+
}
|
|
146
|
+
async function cmdResume(opts) {
|
|
147
|
+
if (!opts.jobId)
|
|
148
|
+
die('jobId is required: bad jobs resume <jobId>');
|
|
149
|
+
const job = loadJob(opts.jobId);
|
|
150
|
+
if (!job)
|
|
151
|
+
die(`job not found: ${opts.jobId}`);
|
|
152
|
+
const remaining = job.targets.filter(t => {
|
|
153
|
+
const key = t.snapshotUrl ?? t.url;
|
|
154
|
+
return !job.results.some(r => (r.snapshotUrl ?? r.url) === key && (r.status === 'ok' || r.status === 'skipped'));
|
|
155
|
+
});
|
|
156
|
+
if (remaining.length === 0) {
|
|
157
|
+
console.log(chalk.green(` Nothing to resume — all ${job.targets.length} targets already completed or skipped.`));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
console.log(` Resuming job ${chalk.bold(job.jobId)} · ${remaining.length}/${job.targets.length} targets remain`);
|
|
161
|
+
const auditFn = await buildAuditFn(job.spec);
|
|
162
|
+
await runJob(job, { auditFn, resume: true });
|
|
163
|
+
const final = loadJob(job.jobId);
|
|
164
|
+
console.log(` Status: ${chalk.bold(final?.status ?? 'unknown')} · ok: ${final?.results.filter(r => r.status === 'ok').length ?? 0}/${final?.targets.length ?? 0}`);
|
|
165
|
+
}
|
|
166
|
+
async function cmdOrchestrate(opts) {
|
|
167
|
+
if (!opts.spec)
|
|
168
|
+
die('--spec is required: bad jobs orchestrate --spec <file.json>');
|
|
169
|
+
const spec = readSpec(opts.spec);
|
|
170
|
+
const targets = await discoverTargets(spec.discover);
|
|
171
|
+
if (targets.length === 0)
|
|
172
|
+
die('discover yielded zero targets — check your URLs / wayback range');
|
|
173
|
+
const est = estimateCost(spec, targets.length);
|
|
174
|
+
console.log(` Targets discovered: ${targets.length}`);
|
|
175
|
+
console.log(` Estimated cost: $${est.estimatedTotalUSD.toFixed(2)}`);
|
|
176
|
+
if (est.exceedsCap && spec.maxCostUSD !== undefined) {
|
|
177
|
+
die(`Estimated cost $${est.estimatedTotalUSD.toFixed(2)} exceeds maxCostUSD $${spec.maxCostUSD.toFixed(2)}`);
|
|
178
|
+
}
|
|
179
|
+
const job = createJob(spec, targets);
|
|
180
|
+
console.log(` Created job ${chalk.bold(job.jobId)} (orchestrator mode)`);
|
|
181
|
+
const auditFn = await buildAuditFn(spec);
|
|
182
|
+
const { orchestrateJob } = await import('./jobs/orchestrator.js');
|
|
183
|
+
await orchestrateJob(job, { auditFn, verbose: true, maxIterations: opts.maxIterations });
|
|
184
|
+
const final = loadJob(job.jobId);
|
|
185
|
+
console.log(` Status: ${chalk.bold(final?.status ?? 'unknown')} · ok: ${final?.results.filter(r => r.status === 'ok').length ?? 0}/${final?.targets.length ?? 0} · $${final?.totalCostUSD.toFixed(2)}`);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Wire the runner to the design-audit pipeline. Imported lazily so `bad jobs
|
|
189
|
+
* list` doesn't pull in Playwright. Each target gets its own output dir so
|
|
190
|
+
* we can deterministically locate `report.json` after the audit returns.
|
|
191
|
+
*/
|
|
192
|
+
async function buildAuditFn(_spec) {
|
|
193
|
+
const { runDesignAudit, extractDesignTokens } = await import('./cli-design-audit.js');
|
|
194
|
+
const { detectBlock } = await import('./jobs/anti-bot.js');
|
|
195
|
+
let counter = 0;
|
|
196
|
+
return async (target, opts) => {
|
|
197
|
+
const url = target.snapshotUrl ?? target.url;
|
|
198
|
+
counter += 1;
|
|
199
|
+
const slug = `${slugify(url)}-${Date.now()}-${counter}`;
|
|
200
|
+
const outputDir = path.join('audit-results', 'jobs', slug);
|
|
201
|
+
await runDesignAudit({
|
|
202
|
+
url,
|
|
203
|
+
pages: opts?.pages ?? 1,
|
|
204
|
+
output: outputDir,
|
|
205
|
+
json: true,
|
|
206
|
+
headless: opts?.headless ?? true,
|
|
207
|
+
audience: opts?.audience?.join(','),
|
|
208
|
+
audienceVulnerability: opts?.audienceVulnerability?.join(','),
|
|
209
|
+
modality: opts?.modality,
|
|
210
|
+
regulatoryContext: opts?.regulatoryContext?.join(','),
|
|
211
|
+
skipEthics: opts?.skipEthics,
|
|
212
|
+
});
|
|
213
|
+
const reportJson = path.resolve(outputDir, 'report.json');
|
|
214
|
+
if (!fs.existsSync(reportJson)) {
|
|
215
|
+
throw new Error(`audit completed but report.json missing at ${reportJson}`);
|
|
216
|
+
}
|
|
217
|
+
const data = JSON.parse(fs.readFileSync(reportJson, 'utf-8'));
|
|
218
|
+
const page = data.pages?.[0];
|
|
219
|
+
const rollupScore = page?.auditResultV2?.rollup?.score ?? page?.rollup?.score ?? page?.score;
|
|
220
|
+
const pageType = page?.auditResultV2?.classification?.type ?? page?.classification?.type;
|
|
221
|
+
// Anti-bot / blocked-page detection. When fired, runOne records skipped.
|
|
222
|
+
const blockedReason = detectBlock(data) ?? undefined;
|
|
223
|
+
let tokensPath;
|
|
224
|
+
// Skip token extraction on blocked pages — there's no real DOM to mine.
|
|
225
|
+
if (opts?.extractTokens && !blockedReason) {
|
|
226
|
+
try {
|
|
227
|
+
const tokensDir = path.join(outputDir, 'tokens');
|
|
228
|
+
const { tokens } = await extractDesignTokens({ url, headless: opts?.headless ?? true, outputDir: tokensDir });
|
|
229
|
+
tokensPath = path.resolve(tokensDir, 'tokens.json');
|
|
230
|
+
// extractDesignTokens persists its own files; ensure tokens.json exists at the canonical path,
|
|
231
|
+
// and stamp it with our schemaVersion so future readers can refuse incompatible shapes.
|
|
232
|
+
const tokensWithVersion = { schemaVersion: 1, ...tokens };
|
|
233
|
+
if (!fs.existsSync(tokensPath)) {
|
|
234
|
+
fs.writeFileSync(tokensPath, JSON.stringify(tokensWithVersion, null, 2));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// Re-stamp existing file with schemaVersion if missing.
|
|
238
|
+
const existing = JSON.parse(fs.readFileSync(tokensPath, 'utf-8'));
|
|
239
|
+
if (typeof existing.schemaVersion !== 'number') {
|
|
240
|
+
fs.writeFileSync(tokensPath, JSON.stringify({ schemaVersion: 1, ...existing }, null, 2));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
// Token extraction is additive — never let it fail the parent audit.
|
|
246
|
+
console.warn(` ${chalk.dim('tokens:')} extraction failed for ${url}: ${err.message}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
runId: outputDir, // The output dir is the de-facto runId for jobs.
|
|
251
|
+
resultPath: reportJson,
|
|
252
|
+
rollupScore,
|
|
253
|
+
pageType,
|
|
254
|
+
tokensPath,
|
|
255
|
+
blockedReason,
|
|
256
|
+
};
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function slugify(url) {
|
|
260
|
+
return url.replace(/^https?:\/\//, '').replace(/[^a-z0-9]+/gi, '-').replace(/^-|-$/g, '').slice(0, 60).toLowerCase();
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=cli-jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-jobs.js","sourceRoot":"","sources":["../src/cli-jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 5 — `bad patterns` subcommand surface.
|
|
3
|
+
*
|
|
4
|
+
* Provides pattern query and inspection via CLI. Mining runs as a periodic
|
|
5
|
+
* Cloudflare Worker cron in production; locally it reads from ~/.bad/patterns/.
|
|
6
|
+
*
|
|
7
|
+
* bad patterns query [--category <cat>] [--page-type <type>] [--weak-dimension <dim>]
|
|
8
|
+
* bad patterns show <patternId>
|
|
9
|
+
* bad patterns mine [--dir <path>]
|
|
10
|
+
*/
|
|
11
|
+
import type { Dimension, PageType } from './design/audit/v2/types.js';
|
|
12
|
+
export interface PatternsQueryOptions {
|
|
13
|
+
category?: string;
|
|
14
|
+
pageType?: PageType;
|
|
15
|
+
weakDimension?: Dimension;
|
|
16
|
+
minApplications?: number;
|
|
17
|
+
minSuccessRate?: number;
|
|
18
|
+
json?: boolean;
|
|
19
|
+
dir?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function runPatternsQuery(opts: PatternsQueryOptions): Promise<void>;
|
|
22
|
+
export declare function runPatternsShow(patternId: string, opts?: {
|
|
23
|
+
json?: boolean;
|
|
24
|
+
dir?: string;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=cli-patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-patterns.d.ts","sourceRoot":"","sources":["../src/cli-patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAErE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BhF;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnH"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 5 — `bad patterns` subcommand surface.
|
|
3
|
+
*
|
|
4
|
+
* Provides pattern query and inspection via CLI. Mining runs as a periodic
|
|
5
|
+
* Cloudflare Worker cron in production; locally it reads from ~/.bad/patterns/.
|
|
6
|
+
*
|
|
7
|
+
* bad patterns query [--category <cat>] [--page-type <type>] [--weak-dimension <dim>]
|
|
8
|
+
* bad patterns show <patternId>
|
|
9
|
+
* bad patterns mine [--dir <path>]
|
|
10
|
+
*/
|
|
11
|
+
import { queryPatterns, loadPatterns } from './design/audit/patterns/store.js';
|
|
12
|
+
export async function runPatternsQuery(opts) {
|
|
13
|
+
const query = {
|
|
14
|
+
category: opts.category,
|
|
15
|
+
pageType: opts.pageType,
|
|
16
|
+
weakDimension: opts.weakDimension,
|
|
17
|
+
minApplications: opts.minApplications,
|
|
18
|
+
minSuccessRate: opts.minSuccessRate,
|
|
19
|
+
};
|
|
20
|
+
const patterns = await queryPatterns(query, opts.dir);
|
|
21
|
+
if (patterns.length === 0) {
|
|
22
|
+
console.log('No patterns found. The pattern library is empty until fleet data accumulates (Layer 5 cold-start).');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (opts.json) {
|
|
26
|
+
console.log(JSON.stringify(patterns, null, 2));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
for (const p of patterns) {
|
|
30
|
+
console.log(`\n[${p.patternId}] ${p.scaffold.description}`);
|
|
31
|
+
console.log(` Category: ${p.category} | Type: ${p.classification.type}`);
|
|
32
|
+
console.log(` Fleet: N=${p.fleetEvidence.applications} tenants=${p.fleetEvidence.sampleTenants} success=${(p.fleetEvidence.successRate * 100).toFixed(0)}%`);
|
|
33
|
+
console.log(` Key decisions: ${p.scaffold.keyDecisions.join('; ')}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function runPatternsShow(patternId, opts = {}) {
|
|
37
|
+
const all = await loadPatterns(opts.dir);
|
|
38
|
+
const pattern = all.find(p => p.patternId === patternId);
|
|
39
|
+
if (!pattern) {
|
|
40
|
+
console.error(`Pattern ${patternId} not found.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
if (opts.json) {
|
|
44
|
+
console.log(JSON.stringify(pattern, null, 2));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log(JSON.stringify(pattern, null, 2));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=cli-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-patterns.js","sourceRoot":"","sources":["../src/cli-patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAa9E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAA0B;IAC/D,MAAM,KAAK,GAAiB;QAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,cAAc,EAAE,IAAI,CAAC,cAAc;KACpC,CAAA;IACD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAErD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,oGAAoG,CAAC,CAAA;QACjH,OAAM;IACR,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAC9C,OAAM;IACR,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;QAC3D,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,YAAY,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAA;QACzE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,aAAa,CAAC,YAAY,YAAY,CAAC,CAAC,aAAa,CAAC,aAAa,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAC7J,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB,EAAE,OAAyC,EAAE;IAClG,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;IACxD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,WAAW,SAAS,aAAa,CAAC,CAAA;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAC7C,OAAM;IACR,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAC/C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bad reports generate` — produce a markdown artifact from a job's results.
|
|
3
|
+
*
|
|
4
|
+
* bad reports generate --job <id> --template <leaderboard|longitudinal|batch-comparison>
|
|
5
|
+
* [--out <file>] [--top <N>] [--by-type <type>] [--buckets 10,100,200]
|
|
6
|
+
* [--narrate] [--context "...one-line context for the LLM..."]
|
|
7
|
+
*
|
|
8
|
+
* The report is the deterministic body. `--narrate` prepends an LLM exec
|
|
9
|
+
* summary; without it, the artifact is pure data.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runReportsCli(args: string[]): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=cli-reports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-reports.d.ts","sourceRoot":"","sources":["../src/cli-reports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAoDH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CjE"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bad reports generate` — produce a markdown artifact from a job's results.
|
|
3
|
+
*
|
|
4
|
+
* bad reports generate --job <id> --template <leaderboard|longitudinal|batch-comparison>
|
|
5
|
+
* [--out <file>] [--top <N>] [--by-type <type>] [--buckets 10,100,200]
|
|
6
|
+
* [--narrate] [--context "...one-line context for the LLM..."]
|
|
7
|
+
*
|
|
8
|
+
* The report is the deterministic body. `--narrate` prepends an LLM exec
|
|
9
|
+
* summary; without it, the artifact is pure data.
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
import { cliError } from './cli-ui.js';
|
|
14
|
+
import { loadJob } from './jobs/index.js';
|
|
15
|
+
function die(msg) {
|
|
16
|
+
cliError(msg);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
import { aggregateJob, renderLeaderboard, renderLongitudinal, renderBatchComparison, renderBrandEvolution, renderJobHeader, narrateReport, } from './reports/index.js';
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const out = {};
|
|
22
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23
|
+
const a = argv[i];
|
|
24
|
+
if (a === '--job')
|
|
25
|
+
out.job = argv[++i];
|
|
26
|
+
else if (a === '--template')
|
|
27
|
+
out.template = argv[++i];
|
|
28
|
+
else if (a === '--out')
|
|
29
|
+
out.out = argv[++i];
|
|
30
|
+
else if (a === '--top')
|
|
31
|
+
out.top = Number(argv[++i]);
|
|
32
|
+
else if (a === '--by-type')
|
|
33
|
+
out.byType = argv[++i];
|
|
34
|
+
else if (a === '--buckets')
|
|
35
|
+
out.buckets = argv[++i].split(',').map(s => Number(s.trim())).filter(n => Number.isFinite(n));
|
|
36
|
+
else if (a === '--narrate')
|
|
37
|
+
out.narrate = true;
|
|
38
|
+
else if (a === '--context')
|
|
39
|
+
out.context = argv[++i];
|
|
40
|
+
else if (a === '--json')
|
|
41
|
+
out.json = true;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
const TEMPLATES = new Set(['leaderboard', 'longitudinal', 'batch-comparison', 'brand-evolution']);
|
|
46
|
+
export async function runReportsCli(args) {
|
|
47
|
+
const sub = args[0];
|
|
48
|
+
if (sub !== 'generate')
|
|
49
|
+
die(`Unknown subcommand: ${sub}. Use generate.`);
|
|
50
|
+
const opts = parseArgs(args.slice(1));
|
|
51
|
+
if (!opts.job)
|
|
52
|
+
die('--job is required');
|
|
53
|
+
if (!opts.template)
|
|
54
|
+
die('--template is required (leaderboard | longitudinal | batch-comparison)');
|
|
55
|
+
if (!TEMPLATES.has(opts.template))
|
|
56
|
+
die(`Unknown template: ${opts.template}. Valid: ${[...TEMPLATES].join(', ')}`);
|
|
57
|
+
const job = loadJob(opts.job);
|
|
58
|
+
if (!job)
|
|
59
|
+
die(`job not found: ${opts.job}`);
|
|
60
|
+
const rows = aggregateJob(job);
|
|
61
|
+
let body;
|
|
62
|
+
if (opts.template === 'leaderboard') {
|
|
63
|
+
body = renderLeaderboard(rows, { topN: opts.top, byType: opts.byType, buckets: opts.buckets });
|
|
64
|
+
}
|
|
65
|
+
else if (opts.template === 'longitudinal') {
|
|
66
|
+
body = renderLongitudinal(rows);
|
|
67
|
+
}
|
|
68
|
+
else if (opts.template === 'brand-evolution') {
|
|
69
|
+
body = renderBrandEvolution(job);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
body = renderBatchComparison(rows);
|
|
73
|
+
}
|
|
74
|
+
const header = renderJobHeader(job) + '\n\n---\n\n';
|
|
75
|
+
let final = header + body;
|
|
76
|
+
if (opts.narrate) {
|
|
77
|
+
try {
|
|
78
|
+
const { Brain } = await import('./brain/index.js');
|
|
79
|
+
const brain = new Brain();
|
|
80
|
+
final = await narrateReport(final, { brain, context: opts.context });
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.warn(chalk.yellow(`narrate failed, falling back to deterministic body: ${err.message}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (opts.out) {
|
|
87
|
+
fs.writeFileSync(opts.out, final, 'utf-8');
|
|
88
|
+
console.log(` Report written → ${opts.out}`);
|
|
89
|
+
}
|
|
90
|
+
else if (opts.json) {
|
|
91
|
+
console.log(JSON.stringify({ jobId: job.jobId, template: opts.template, markdown: final }, null, 2));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(final);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=cli-reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-reports.js","sourceRoot":"","sources":["../src/cli-reports.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -77,6 +77,19 @@ async function main() {
|
|
|
77
77
|
loadLocalEnvFiles(process.cwd());
|
|
78
78
|
setCliVersion(readCliVersion());
|
|
79
79
|
setInvocation(process.argv.slice(2)[0] || 'unknown', process.argv.slice(2));
|
|
80
|
+
// Subcommand groups with their own arg shape — dispatch before the strict
|
|
81
|
+
// parent parser (which only knows the run/design-audit/auth/showcase flags).
|
|
82
|
+
const subArgs = process.argv.slice(2);
|
|
83
|
+
if (subArgs[0] === 'jobs') {
|
|
84
|
+
const { runJobsCli } = await import('./cli-jobs.js');
|
|
85
|
+
await runJobsCli(subArgs.slice(1));
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
if (subArgs[0] === 'reports') {
|
|
89
|
+
const { runReportsCli } = await import('./cli-reports.js');
|
|
90
|
+
await runReportsCli(subArgs.slice(1));
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
80
93
|
const { values, positionals } = parseArgs({
|
|
81
94
|
allowPositionals: true,
|
|
82
95
|
allowNegative: true,
|
|
@@ -123,6 +136,15 @@ async function main() {
|
|
|
123
136
|
reproducibility: { type: 'boolean' },
|
|
124
137
|
'rubrics-dir': { type: 'string' },
|
|
125
138
|
'audit-passes': { type: 'string' },
|
|
139
|
+
// Layer 7 — domain ethics gate. --skip-ethics bypasses the rollup floor
|
|
140
|
+
// for testing scenarios; --ethics-rules-dir overrides the builtin rule set.
|
|
141
|
+
'skip-ethics': { type: 'boolean' },
|
|
142
|
+
'ethics-rules-dir': { type: 'string' },
|
|
143
|
+
// Layer 6 / 7 — audience predicate hints. Comma-separated.
|
|
144
|
+
audience: { type: 'string' },
|
|
145
|
+
'regulatory-context': { type: 'string' },
|
|
146
|
+
'audience-vulnerability': { type: 'string' },
|
|
147
|
+
modality: { type: 'string' },
|
|
126
148
|
// bad view
|
|
127
149
|
port: { type: 'string' },
|
|
128
150
|
'no-open': { type: 'boolean' },
|
|
@@ -296,6 +318,12 @@ async function main() {
|
|
|
296
318
|
reproducibility: values.reproducibility,
|
|
297
319
|
rubricsDir: values['rubrics-dir'],
|
|
298
320
|
auditPasses: values['audit-passes'],
|
|
321
|
+
skipEthics: values['skip-ethics'],
|
|
322
|
+
ethicsRulesDir: values['ethics-rules-dir'],
|
|
323
|
+
audience: values.audience,
|
|
324
|
+
regulatoryContext: values['regulatory-context'],
|
|
325
|
+
audienceVulnerability: values['audience-vulnerability'],
|
|
326
|
+
modality: values.modality,
|
|
299
327
|
});
|
|
300
328
|
process.exit(0);
|
|
301
329
|
}
|
|
@@ -489,7 +517,7 @@ async function main() {
|
|
|
489
517
|
}
|
|
490
518
|
}
|
|
491
519
|
if (command !== 'run' && command !== 'attach') {
|
|
492
|
-
cliError(`Unknown command: ${command}. Use "run", "attach", "preview", "runs", "view", "share", "chrome-debug", "design-audit", "showcase", or "
|
|
520
|
+
cliError(`Unknown command: ${command}. Use "run", "attach", "preview", "runs", "view", "share", "chrome-debug", "design-audit", "showcase", "auth", "jobs", or "reports".`);
|
|
493
521
|
process.exit(1);
|
|
494
522
|
}
|
|
495
523
|
// Validate inputs
|