thumbgate 1.37.1 → 1.37.3

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 (47) hide show
  1. package/.agents/skills/article-syndication-pipeline/SKILL.md +37 -0
  2. package/.agents/skills/ci-gha-buildkite-patterns-not-clone/SKILL.md +72 -0
  3. package/.agents/skills/cobble-hot-store-compare-not-clone/SKILL.md +80 -0
  4. package/.agents/skills/colab-compute-honesty-not-clone/SKILL.md +70 -0
  5. package/.agents/skills/comet-session-logger/SKILL.md +59 -0
  6. package/.agents/skills/datadog-llm-obs-compare-not-clone/SKILL.md +75 -0
  7. package/.agents/skills/deeppattern-discipline-honesty-not-clone/SKILL.md +73 -0
  8. package/.agents/skills/thumbgate-board-loop/SKILL.md +72 -0
  9. package/.agents/skills/thumbgate-daily-discoveries/SKILL.md +57 -0
  10. package/.agents/skills/token-shunt-honesty-not-clone/SKILL.md +67 -0
  11. package/.agents/skills/typesafe-typed-questions-not-clone/SKILL.md +86 -0
  12. package/.claude-plugin/plugin.json +1 -1
  13. package/.well-known/mcp/server-card.json +1 -1
  14. package/adapters/claude/.mcp.json +2 -2
  15. package/adapters/forge/forge.yaml +3 -3
  16. package/adapters/future-agi/.mcp.json +1 -1
  17. package/adapters/future-agi/config.toml +1 -1
  18. package/adapters/future-agi/opencode.json +1 -1
  19. package/adapters/herdr/herdr-plugin.toml +2 -2
  20. package/adapters/mcp/server-stdio.js +1 -1
  21. package/adapters/opencode/opencode.json +1 -1
  22. package/bin/cli.js +257 -0
  23. package/config/gate-templates.json +96 -0
  24. package/package.json +55 -12
  25. package/public/blog/2026-09-23-datadog-llm-obs-four-practices.html +42 -0
  26. package/public/index.html +2 -2
  27. package/public/install.html +7 -7
  28. package/public/numbers.html +2 -2
  29. package/scripts/ci-gha-buildkite-patterns.js +393 -0
  30. package/scripts/cli-schema.js +90 -0
  31. package/scripts/cobble-hot-store-split.js +600 -0
  32. package/scripts/colab-compute-honesty.js +281 -0
  33. package/scripts/deeppattern-discipline-honesty.js +431 -0
  34. package/scripts/gates-engine.js +16 -5
  35. package/scripts/install-thumbgate-daily-publish-launchd.sh +83 -0
  36. package/scripts/llm-obs-honesty.js +478 -0
  37. package/scripts/thumbgate-board-loop.js +432 -0
  38. package/scripts/thumbgate-daily-discoveries-publish.js +413 -0
  39. package/scripts/thumbgate-daily-discoveries-publish.sh +18 -0
  40. package/scripts/token-shunt-honesty.js +502 -0
  41. package/scripts/typesafe-typed-questions.js +1138 -0
  42. package/server.json +2 -2
  43. package/skills/article-syndication-pipeline/SKILL.md +37 -0
  44. package/skills/comet-session-logger/SKILL.md +59 -0
  45. package/skills/thumbgate-daily-discoveries/SKILL.md +57 -0
  46. package/src/index.js +10 -0
  47. package/src/integrations/ideabrowser-connector.js +190 -0
@@ -0,0 +1,393 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Buildkite pipeline FORMAT steal onto GitHub Actions — not a clone.
6
+ *
7
+ * Sources (public docs, 2026-09):
8
+ * https://buildkite.com/docs/pipelines/best-practices/pipeline-design-and-structure
9
+ * https://buildkite.com/docs/pipelines/configure/annotations
10
+ * https://buildkite.com/docs/pipelines/configure/dependencies
11
+ *
12
+ * Transfers onto existing GHA rails:
13
+ * 1. first-fail step identity — name the first failed job/step before logs
14
+ * 2. fail-fast / cancel-in-progress — PR concurrency; never cancel main
15
+ * 3. depends_on honesty — `needs:` is wait; continue-on-error only on non-required
16
+ * 4. skip conditions — path/event filters must not skip merge_group required checks
17
+ * 5. annotations — GITHUB_STEP_SUMMARY, not Buildkite annotation APIs
18
+ *
19
+ * Does NOT add Buildkite Pipelines, agents, Test Engine, auto-quarantine,
20
+ * Package Registries, or a second required CI vendor.
21
+ */
22
+
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+
26
+ const SOURCE_DESIGN = 'https://buildkite.com/docs/pipelines/best-practices/pipeline-design-and-structure';
27
+ const SOURCE_ANNOTATIONS = 'https://buildkite.com/docs/pipelines/configure/annotations';
28
+
29
+ const REQUIRED_GHA_CONTEXTS = Object.freeze([
30
+ 'test',
31
+ 'audit',
32
+ 'Verify changeset',
33
+ 'Analyze JavaScript',
34
+ 'CodeQL',
35
+ 'Socket Security: Project Report',
36
+ 'Socket Security: Pull Request Alerts',
37
+ 'GitGuardian Security Checks',
38
+ ]);
39
+
40
+ const CLONE_RE = /\b(buildkite\.yml|buildkite-agent|test engine auto-?quarantine|pipelines saas|hosted mac agents|buildkite mcp)\b/i;
41
+ const MIGRATE_RE = /\b(migrate (this )?(repo )?to buildkite|replace github actions with buildkite|add buildkite as (a )?required check)\b/i;
42
+
43
+ const RAIL_MAP = Object.freeze([
44
+ {
45
+ buildkite: 'Step is the diagnosis unit; first failed step before logs',
46
+ githubActions: 'gh run view --json jobs → first failed job.steps[].name; never --log-failed first',
47
+ },
48
+ {
49
+ buildkite: 'fail-fast cancels remaining jobs; fast checks before slow suites',
50
+ githubActions: 'concurrency cancel-in-progress on PRs; never cancel main; ci-scope deps/web/full',
51
+ },
52
+ {
53
+ buildkite: 'depends_on / wait; continue_on_failure only for annotations after a fail',
54
+ githubActions: 'jobs.<id>.needs; continue-on-error only on non-required drift monitors',
55
+ },
56
+ {
57
+ buildkite: 'skip / if / branches skip unnecessary work',
58
+ githubActions: 'paths: + ci-scope; merge_group and main stay full required checks',
59
+ },
60
+ {
61
+ buildkite: 'build annotations summarize failures',
62
+ githubActions: 'GITHUB_STEP_SUMMARY from --annotate; no Buildkite annotation API',
63
+ },
64
+ {
65
+ buildkite: 'control plane vs compute (SaaS schedules, you run agents)',
66
+ githubActions: 'GitHub is the control plane; ubuntu-latest is compute; do not add Buildkite agents',
67
+ },
68
+ ]);
69
+
70
+ function parseArgs(argv = process.argv.slice(2)) {
71
+ const options = {
72
+ json: false,
73
+ strict: false,
74
+ mapOnly: false,
75
+ annotate: false,
76
+ cloneBuildkite: false,
77
+ migrate: false,
78
+ rerunQueued: false,
79
+ quarantine: false,
80
+ jobsJson: '',
81
+ workflow: '',
82
+ required: REQUIRED_GHA_CONTEXTS.slice(),
83
+ };
84
+ for (const arg of argv) {
85
+ if (arg === '--json') options.json = true;
86
+ else if (arg === '--strict') options.strict = true;
87
+ else if (arg === '--map-only') options.mapOnly = true;
88
+ else if (arg === '--annotate' || arg === '--annotate-job') options.annotate = true;
89
+ else if (arg === '--clone-buildkite') options.cloneBuildkite = true;
90
+ else if (arg === '--migrate' || arg === '--migrate-to-buildkite') options.migrate = true;
91
+ else if (arg === '--rerun-queued') options.rerunQueued = true;
92
+ else if (arg === '--quarantine') options.quarantine = true;
93
+ else if (arg.startsWith('--jobs-json=')) options.jobsJson = arg.slice('--jobs-json='.length);
94
+ else if (arg.startsWith('--workflow=')) options.workflow = arg.slice('--workflow='.length);
95
+ else if (arg.startsWith('--required=')) {
96
+ options.required = arg.slice('--required='.length).split(',').map((s) => s.trim()).filter(Boolean);
97
+ }
98
+ }
99
+ return options;
100
+ }
101
+
102
+ function loadJson(filePath) {
103
+ if (!filePath) return null;
104
+ const abs = path.resolve(filePath);
105
+ return JSON.parse(fs.readFileSync(abs, 'utf8'));
106
+ }
107
+
108
+ function firstFailedStep(jobs = []) {
109
+ const list = Array.isArray(jobs) ? jobs : [];
110
+ for (const job of list) {
111
+ const jobConclusion = String(job.conclusion || job.status || '').toLowerCase();
112
+ const steps = Array.isArray(job.steps) ? job.steps : [];
113
+ for (const step of steps) {
114
+ const stepConclusion = String(step.conclusion || '').toLowerCase();
115
+ if (stepConclusion === 'failure' || stepConclusion === 'timed_out' || stepConclusion === 'cancelled') {
116
+ return {
117
+ job: job.name || job.id || 'unknown-job',
118
+ step: step.name || 'unknown-step',
119
+ conclusion: step.conclusion,
120
+ number: step.number == null ? null : step.number,
121
+ };
122
+ }
123
+ }
124
+ if (jobConclusion === 'failure' || jobConclusion === 'timed_out') {
125
+ return {
126
+ job: job.name || job.id || 'unknown-job',
127
+ step: null,
128
+ conclusion: job.conclusion,
129
+ number: null,
130
+ };
131
+ }
132
+ }
133
+ return null;
134
+ }
135
+
136
+ function missingRequiredContexts(jobs = [], required = REQUIRED_GHA_CONTEXTS) {
137
+ const names = new Set();
138
+ for (const job of Array.isArray(jobs) ? jobs : []) {
139
+ const n = String(job.name || '');
140
+ if (n) names.add(n);
141
+ const ctx = String(job.context || '');
142
+ if (ctx) names.add(ctx);
143
+ }
144
+ return required.filter((need) => {
145
+ const needle = need.toLowerCase();
146
+ for (const have of names) {
147
+ if (have.toLowerCase() === needle || have.toLowerCase().startsWith(needle.toLowerCase())) {
148
+ return false;
149
+ }
150
+ }
151
+ return true;
152
+ });
153
+ }
154
+
155
+ function auditWorkflowText(yaml = '') {
156
+ const text = String(yaml || '');
157
+ const findings = [];
158
+ if (!/^\s*concurrency:\s*$/m.test(text) && !/\nconcurrency:\s*\n/.test(text)) {
159
+ findings.push({
160
+ id: 'missing_concurrency',
161
+ message: 'Workflow has no concurrency group (Buildkite concurrency_group analog).',
162
+ });
163
+ }
164
+ if (/cancel-in-progress:\s*true\s*$/m.test(text) && !/refs\/heads\/main/.test(text)) {
165
+ findings.push({
166
+ id: 'cancel_main',
167
+ message: 'cancel-in-progress: true without excluding main — Buildkite fail-fast must not cancel the trunk build.',
168
+ });
169
+ }
170
+ if (CLONE_RE.test(text) || /uses:\s*buildkite\//i.test(text)) {
171
+ findings.push({
172
+ id: 'clone_buildkite',
173
+ message: 'Workflow vendors Buildkite agents/actions. Keep GitHub Actions native.',
174
+ });
175
+ }
176
+ return findings;
177
+ }
178
+
179
+ function auditWorkflowFile(filePath) {
180
+ if (!filePath) return [];
181
+ const abs = path.resolve(filePath);
182
+ if (!fs.existsSync(abs)) {
183
+ return [{ id: 'workflow_missing', message: `Workflow not found: ${filePath}` }];
184
+ }
185
+ return auditWorkflowText(fs.readFileSync(abs, 'utf8'));
186
+ }
187
+
188
+ function renderAnnotation(firstFail, extraLines = []) {
189
+ const lines = [
190
+ '## First failed step (Buildkite FORMAT on GitHub Actions)',
191
+ '',
192
+ 'Do not dump logs first. Name the red step, then re-run that command locally.',
193
+ 'Do not `gh run rerun` a queued job. Do not add Buildkite as a required check.',
194
+ '',
195
+ ];
196
+ if (firstFail) {
197
+ lines.push(`- Job: \`${firstFail.job}\``);
198
+ if (firstFail.step) lines.push(`- Step: \`${firstFail.step}\``);
199
+ if (firstFail.conclusion) lines.push(`- Conclusion: \`${firstFail.conclusion}\``);
200
+ } else {
201
+ lines.push('- No failed step in the provided jobs JSON (scroll the Actions UI for the first red step).');
202
+ }
203
+ for (const line of extraLines) lines.push(line);
204
+ lines.push('');
205
+ return `${lines.join('\n')}\n`;
206
+ }
207
+
208
+ function writeStepSummary(markdown) {
209
+ const summaryPath = process.env.GITHUB_STEP_SUMMARY;
210
+ if (!summaryPath) return false;
211
+ fs.appendFileSync(summaryPath, markdown);
212
+ return true;
213
+ }
214
+
215
+ function buildCiGhaBuildkitePatternsReport(args = {}) {
216
+ if (args.mapOnly) {
217
+ return {
218
+ name: 'thumbgate-ci-gha-buildkite-patterns',
219
+ ok: true,
220
+ status: 'ready',
221
+ source: { design: SOURCE_DESIGN, annotations: SOURCE_ANNOTATIONS },
222
+ clone: false,
223
+ vendor: 'github-actions',
224
+ requiredContexts: REQUIRED_GHA_CONTEXTS,
225
+ firstFail: null,
226
+ missingRequired: [],
227
+ findings: [],
228
+ railMap: RAIL_MAP,
229
+ annotationWritten: false,
230
+ note: 'FORMAT steal only. Not affiliated with Buildkite. Public repo stays on GHA.',
231
+ };
232
+ }
233
+ const findings = [];
234
+ const jobsPayload = args.jobsJson ? loadJson(args.jobsJson) : null;
235
+ const jobs = Array.isArray(jobsPayload)
236
+ ? jobsPayload
237
+ : (jobsPayload && Array.isArray(jobsPayload.jobs) ? jobsPayload.jobs : []);
238
+
239
+ if (args.cloneBuildkite) {
240
+ findings.push({
241
+ id: 'clone_buildkite',
242
+ message: 'Refuse Buildkite Pipelines / agents / Test Engine SKU. Steal FORMAT onto GitHub Actions only.',
243
+ });
244
+ }
245
+ if (args.migrate || MIGRATE_RE.test(String(args.claim || ''))) {
246
+ findings.push({
247
+ id: 'migrate_vendor',
248
+ message: 'This public repo stays on GitHub-hosted ubuntu-latest. Do not migrate to Buildkite.',
249
+ });
250
+ }
251
+ if (args.rerunQueued) {
252
+ findings.push({
253
+ id: 'rerun_queued',
254
+ message: 'Never gh run rerun a queued job (no-op / burns minutes). Wait for Actions to drain.',
255
+ });
256
+ }
257
+ if (args.quarantine) {
258
+ findings.push({
259
+ id: 'auto_quarantine',
260
+ message: 'Refuse Test Engine auto-quarantine. First fail is a real regression until proven otherwise.',
261
+ });
262
+ }
263
+
264
+ const firstFail = jobs.length ? firstFailedStep(jobs) : null;
265
+ const missing = jobs.length ? missingRequiredContexts(jobs, args.required || REQUIRED_GHA_CONTEXTS) : [];
266
+ if (missing.length) {
267
+ findings.push({
268
+ id: 'missing_required',
269
+ message: `Required GHA contexts absent: ${missing.join(', ')}. Check githubstatus.com Actions before blaming code.`,
270
+ missing,
271
+ });
272
+ }
273
+
274
+ const workflowFindings = args.workflow ? auditWorkflowFile(args.workflow) : [];
275
+ findings.push(...workflowFindings);
276
+
277
+ let annotationWritten = false;
278
+ let annotation = '';
279
+ if (args.annotate) {
280
+ annotation = renderAnnotation(firstFail);
281
+ annotationWritten = writeStepSummary(annotation);
282
+ }
283
+
284
+ const ok = findings.length === 0;
285
+ return {
286
+ name: 'thumbgate-ci-gha-buildkite-patterns',
287
+ ok,
288
+ status: ok ? 'ready' : 'fail',
289
+ source: { design: SOURCE_DESIGN, annotations: SOURCE_ANNOTATIONS },
290
+ clone: false,
291
+ vendor: 'github-actions',
292
+ requiredContexts: args.required || REQUIRED_GHA_CONTEXTS,
293
+ firstFail,
294
+ missingRequired: missing,
295
+ findings,
296
+ railMap: RAIL_MAP,
297
+ annotationWritten,
298
+ annotation: args.annotate ? annotation : undefined,
299
+ note: 'FORMAT steal only. Not affiliated with Buildkite. Public repo stays on GHA.',
300
+ };
301
+ }
302
+
303
+ function formatCiGhaBuildkitePatternsReport(report) {
304
+ const lines = [];
305
+ lines.push(`# ${report.name} status=${report.status}`);
306
+ lines.push(`vendor: ${report.vendor} clone: ${report.clone}`);
307
+ if (report.firstFail) {
308
+ lines.push(`first_fail: job=${report.firstFail.job} step=${report.firstFail.step || '(job)'} conclusion=${report.firstFail.conclusion}`);
309
+ } else {
310
+ lines.push('first_fail: (none)');
311
+ }
312
+ if (report.missingRequired && report.missingRequired.length) {
313
+ lines.push(`missing_required: ${report.missingRequired.join(', ')}`);
314
+ }
315
+ if (report.findings.length) {
316
+ lines.push('findings:');
317
+ for (const f of report.findings) lines.push(`- ${f.id}: ${f.message}`);
318
+ } else {
319
+ lines.push('findings: (none)');
320
+ }
321
+ lines.push('rail_map:');
322
+ for (const row of report.railMap) {
323
+ lines.push(`- BK: ${row.buildkite}`);
324
+ lines.push(` GHA: ${row.githubActions}`);
325
+ }
326
+ lines.push(report.note);
327
+ return `${lines.join('\n')}\n`;
328
+ }
329
+
330
+ function printHelp() {
331
+ process.stdout.write(`Usage: node scripts/ci-gha-buildkite-patterns.js [flags]
332
+
333
+ Buildkite pipeline FORMAT on GitHub Actions. Does not add Buildkite.
334
+
335
+ --json JSON report
336
+ --map-only Rail map only (always ok)
337
+ --jobs-json=path Parse gh run view --json jobs (or {jobs:[...]})
338
+ --workflow=path Audit a workflow YAML
339
+ --annotate Append first-fail block to GITHUB_STEP_SUMMARY
340
+ --strict Exit 1 unless ready
341
+ --clone-buildkite Refuse SKU clone
342
+ --migrate Refuse vendor migration
343
+ --rerun-queued Refuse gh run rerun of queued jobs
344
+ --quarantine Refuse Test Engine auto-quarantine
345
+ `);
346
+ }
347
+
348
+ function runCli(argv = process.argv.slice(2)) {
349
+ if (argv.includes('--help') || argv.includes('-h')) {
350
+ printHelp();
351
+ return 0;
352
+ }
353
+ const args = parseArgs(argv);
354
+ const report = args.mapOnly
355
+ ? {
356
+ name: 'thumbgate-ci-gha-buildkite-patterns',
357
+ ok: true,
358
+ status: 'ready',
359
+ source: { design: SOURCE_DESIGN, annotations: SOURCE_ANNOTATIONS },
360
+ clone: false,
361
+ vendor: 'github-actions',
362
+ requiredContexts: REQUIRED_GHA_CONTEXTS,
363
+ firstFail: null,
364
+ missingRequired: [],
365
+ findings: [],
366
+ railMap: RAIL_MAP,
367
+ annotationWritten: false,
368
+ note: 'FORMAT steal only. Not affiliated with Buildkite. Public repo stays on GHA.',
369
+ }
370
+ : buildCiGhaBuildkitePatternsReport(args);
371
+ if (args.json) process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
372
+ else process.stdout.write(formatCiGhaBuildkitePatternsReport(report));
373
+ if (args.strict && report.status !== 'ready') return 1;
374
+ if (report.status === 'fail') return 1;
375
+ return 0;
376
+ }
377
+
378
+ module.exports = {
379
+ REQUIRED_GHA_CONTEXTS,
380
+ RAIL_MAP,
381
+ parseArgs,
382
+ firstFailedStep,
383
+ missingRequiredContexts,
384
+ auditWorkflowText,
385
+ renderAnnotation,
386
+ buildCiGhaBuildkitePatternsReport,
387
+ formatCiGhaBuildkitePatternsReport,
388
+ runCli,
389
+ };
390
+
391
+ if (path.resolve(process.argv[1] || '') === path.resolve(__filename)) {
392
+ process.exitCode = runCli();
393
+ }
@@ -475,6 +475,96 @@ const CLI_COMMANDS = [
475
475
  ],
476
476
  }),
477
477
 
478
+
479
+ discoveryCommand({
480
+ name: 'board-loop',
481
+ aliases: ['thumbgate-board-loop', 'pr-issue-loop'],
482
+ description: 'Classify+drain Issues/PR wall (BEHIND Dependabot update-branch; never approve)',
483
+ flags: [
484
+ jsonFlag(),
485
+ { name: 'apply', type: 'boolean', description: 'Perform update-branch / pr:manage / comments (default classify-only)' },
486
+ { name: 'max-update-branch', type: 'number', description: 'Max BEHIND PRs to update-branch per tick (default 1)' },
487
+ { name: 'max-pr-manage', type: 'number', description: 'Max READY PRs to submit via pr:manage (default 1)' },
488
+ { name: 'max-comments', type: 'number', description: 'Max needs-rebase / issue comments (default 4)' },
489
+ { name: 'skip-pr', type: 'number', description: 'Skip a PR number (e.g. the one just merged)' },
490
+ ],
491
+ }),
492
+
493
+ discoveryCommand({
494
+ name: 'colab-compute-honesty',
495
+ aliases: ['colab-honesty', 'compute-unit-honesty'],
496
+ description: 'Colab /signup FORMAT steal: Compute Units ≠ dedicated GPU; Subscribe ≠ receipt (does not buy Pro/Pro+ or clone colab-cli)',
497
+ flags: [
498
+ jsonFlag(),
499
+ { name: 'strict', type: 'boolean', description: 'Exit non-zero on fail' },
500
+ { name: 'claim', type: 'string', description: 'Claim to audit' },
501
+ { name: 'plan', type: 'string', description: 'free|payg|pro|proplus|unknown' },
502
+ { name: 'plan-proof', type: 'string', description: 'Live Current-plan receipt, not a Subscribe button' },
503
+ { name: 'snapshot', type: 'string', description: 'Live /signup snapshot JSON' },
504
+ { name: 'map-only', type: 'boolean', description: 'Print Colab → ThumbGate rail map' },
505
+ { name: 'claim-ready', type: 'boolean', description: 'Fail unless compute proof is clean' },
506
+ { name: 'clone-colab', type: 'boolean', description: 'Refuse Colab-runner SKU clone' },
507
+ { name: 'buy-pro', type: 'boolean', description: 'Refuse buying Colab Pro/Pro+/CU' },
508
+ ],
509
+ }),
510
+
511
+ discoveryCommand({
512
+ name: 'ci-gha-buildkite-patterns',
513
+ aliases: ['ci-buildkite-patterns', 'gha-buildkite-honesty', 'first-fail-gha'],
514
+ description: 'Buildkite pipeline FORMAT on GitHub Actions: first-fail step, PR fail-fast, needs:/skip/annotations (does not add Buildkite)',
515
+ flags: [
516
+ jsonFlag(),
517
+ { name: 'strict', type: 'boolean', description: 'Exit non-zero on fail' },
518
+ { name: 'map-only', type: 'boolean', description: 'Print Buildkite → GHA rail map' },
519
+ { name: 'jobs-json', type: 'string', description: 'Path to gh run view --json jobs payload' },
520
+ { name: 'workflow', type: 'string', description: 'Workflow YAML to audit' },
521
+ { name: 'annotate', type: 'boolean', description: 'Append first-fail block to GITHUB_STEP_SUMMARY' },
522
+ { name: 'clone-buildkite', type: 'boolean', description: 'Refuse Buildkite SKU clone' },
523
+ { name: 'migrate', type: 'boolean', description: 'Refuse migrating this repo to Buildkite' },
524
+ ],
525
+ }),
526
+
527
+ discoveryCommand({
528
+ name: 'deeppattern-discipline-honesty',
529
+ aliases: ['deeppattern-honesty', 'layer-check-honesty', 'evidence-closeout-honesty', 'aqg-de-honesty'],
530
+ description: 'DeepPattern FORMAT steal: layer-check + evidence-closeout (does not install AQG/Decision Engine)',
531
+ flags: [
532
+ jsonFlag(),
533
+ { name: 'strict', type: 'boolean', description: 'Exit non-zero on fail' },
534
+ { name: 'claim', type: 'string', description: 'Comparative / substitute claim to layer-check' },
535
+ { name: 'subject-layer', type: 'string', description: 'Subject product layer (default L7)' },
536
+ { name: 'closeout', type: 'string', description: 'Markdown closeout / PR body path' },
537
+ { name: 'closeout-text', type: 'string', description: 'Inline closeout markdown' },
538
+ { name: 'map-only', type: 'boolean', description: 'Print DeepPattern → ThumbGate rail map' },
539
+ { name: 'claim-ready', type: 'boolean', description: 'Fail unless layer-check + closeout are clean' },
540
+ { name: 'clone-deeppattern', type: 'boolean', description: 'Refuse AQG/DE SKU clone' },
541
+ ],
542
+ }),
543
+
544
+ discoveryCommand({
545
+ name: 'typesafe-typed-questions',
546
+ aliases: ['typesafe-hook', 'typed-questions', 'jev-typed-questions'],
547
+ description: 'TypeSafe FORMAT steal: typed noul/choice/score over PreToolUse state, code-owned pass/review/block (does not install typesafe-sdk or clone Jev)',
548
+ flags: [
549
+ jsonFlag(),
550
+ { name: 'strict', type: 'boolean', description: 'Exit non-zero on fail or actionable findings' },
551
+ { name: 'root', type: 'string', description: 'Repo root for relative paths (default cwd)' },
552
+ { name: 'payload', type: 'string', description: 'Path to PreToolUse JSON payload' },
553
+ { name: 'battery', type: 'string', description: 'Path to typed questions JSON' },
554
+ { name: 'tool-name', type: 'string', description: 'Shortcut tool_name' },
555
+ { name: 'command', type: 'string', description: 'Shortcut tool_input.command' },
556
+ { name: 'policy', type: 'string', description: 'strict|permissive route policy' },
557
+ { name: 'map-only', type: 'boolean', description: 'Print TypeSafe → ThumbGate rail map' },
558
+ { name: 'claim-ready', type: 'boolean', description: 'Fail unless code owns the route' },
559
+ { name: 'clone-jev', type: 'boolean', description: 'Refuse TypeSafe/Jev SKU clone' },
560
+ { name: 'use-typesafe-api', type: 'boolean', description: 'Refuse live api.typesafe.ai as the PreToolUse gate' },
561
+ { name: 'live', type: 'boolean', description: 'Shadow battery against System One in one batched POST; code still owns route' },
562
+ { name: 'fan-out-questions', type: 'boolean', description: 'Refuse N single-question HTTP calls (parallel_questions cookbook)' },
563
+ { name: 'llm-adjudicate', type: 'boolean', description: 'Refuse LLM adjudicator (#3690/#3687 parked)' },
564
+ { name: 'model-emitted-verdict', type: 'string', description: 'Refuse a model-emitted pass/review/block' },
565
+ ],
566
+ }),
567
+
478
568
  discoveryCommand({
479
569
  name: 'openui-catalog-compose-honesty',
480
570
  aliases: ['openui-honesty-doctor', 'catalog-compose-honesty', 'repair-before-compose-claim'],