thumbgate 1.34.3 → 1.37.1
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/.agents/skills/cyberstrike-compare-not-clone/SKILL.md +36 -0
- package/.agents/skills/gitlab-sandbox-allowlist-not-trust/SKILL.md +77 -0
- package/.agents/skills/jit-harness-compare-not-clone/SKILL.md +34 -0
- package/.agents/skills/openui-catalog-compose-honesty/SKILL.md +64 -0
- package/.agents/skills/zvec-grep-compare-not-clone/SKILL.md +34 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +1 -0
- package/.well-known/mcp/server-card.json +1 -1
- package/CONTRIBUTING.md +95 -0
- package/README.md +195 -632
- package/THIRD_PARTY_NOTICES.md +89 -0
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/forge/forge.yaml +3 -3
- package/adapters/future-agi/.mcp.json +8 -0
- package/adapters/future-agi/FUTURE_AGI.md +23 -0
- package/adapters/future-agi/config.toml +3 -0
- package/adapters/future-agi/future-agi-bridge.js +9 -0
- package/adapters/future-agi/opencode.json +8 -0
- package/adapters/herdr/herdr-plugin.toml +18 -0
- package/adapters/mcp/server-stdio.js +238 -25
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/workos/WORKOS.md +52 -0
- package/bin/cli.js +373 -5
- package/bin/futureagi-bridge +9 -0
- package/config/gate-templates.json +653 -4
- package/config/gates/actor-critic-audit.json +34 -0
- package/config/gates/default.json +21 -2
- package/config/gates/five-walls-governance.json +34 -0
- package/config/gates/future-agi-guardrails.json +34 -0
- package/config/gates/radware-threat-defense-2026.json +61 -0
- package/config/gates/simatree-data-governance.json +33 -0
- package/config/mcp-allowlists.json +4 -0
- package/config/merge-quality-checks.json +10 -1
- package/config/model-candidates.json +382 -24
- package/config/model-tiers.json +18 -0
- package/config/post-deploy-marketing-pages.json +10 -0
- package/config/progressive/01-wire-only.json +11 -0
- package/config/progressive/02-dashboard-empty-ok.json +10 -0
- package/config/progressive/03-one-lesson.json +10 -0
- package/config/progressive/04-warn-fires.json +11 -0
- package/config/progressive/05-strict-optional.json +11 -0
- package/config/progressive/README.md +15 -0
- package/config/schemas/broker-execution-receipt.schema.json +139 -0
- package/config/schemas/provider-execution-attestation-v1.schema.json +58 -0
- package/conformance/provider-attestation/vectors.json +320 -0
- package/docs/specs/provider-execution-attestation-v1.md +69 -0
- package/openapi/openapi.yaml +15 -0
- package/package.json +401 -147
- package/public/about.html +2 -2
- package/public/ai-malpractice-prevention.html +7 -7
- package/public/blog/a-10-dollar-vps-is-not-a-computer.html +143 -0
- package/public/blog/a-receipt-is-not-world-state.html +388 -0
- package/public/blog/git-at-agent-scale.html +374 -0
- package/public/blog/no-llm-in-the-gate.html +133 -0
- package/public/blog.html +80 -0
- package/public/case-studies.html +16 -1
- package/public/compare.html +28 -0
- package/public/diagnostic.html +216 -7
- package/public/docs/connectors.html +39 -0
- package/public/federal.html +2 -2
- package/public/founders.html +639 -0
- package/public/index.html +87 -9
- package/public/install.html +8 -8
- package/public/learn.html +39 -0
- package/public/numbers.html +2 -2
- package/public/peter.html +310 -0
- package/public/platform-partners.html +119 -0
- package/public/pricing.html +24 -3
- package/public/privacy.html +117 -0
- package/public/pro.html +17 -0
- package/public/support.html +62 -0
- package/public/terms.html +130 -0
- package/public/third-party-notices.html +95 -0
- package/public/yt.html +351 -0
- package/scripts/action-receipts.js +133 -3
- package/scripts/adaptive-governance-arena.js +349 -0
- package/scripts/admin-override.js +205 -0
- package/scripts/agent-action-inventory.js +869 -0
- package/scripts/agent-audit-trace.js +42 -2
- package/scripts/agent-egress-policy.js +1117 -0
- package/scripts/agent-memory-lifecycle.js +141 -2
- package/scripts/agent-operations-planner.js +441 -1
- package/scripts/agent-readiness.js +68 -0
- package/scripts/agent-security-central.js +647 -0
- package/scripts/allowlist-bridge-honesty.js +417 -0
- package/scripts/async-job-runner.js +102 -11
- package/scripts/audit-trail.js +212 -0
- package/scripts/auto-promote-gates.js +178 -27
- package/scripts/billing.js +1 -1
- package/scripts/broker-execution-receipts.js +719 -0
- package/scripts/budget-aware-gates-proof.js +423 -0
- package/scripts/claude-feedback-sync.js +29 -3
- package/scripts/claw-harness-production.js +237 -0
- package/scripts/cli-progress.js +111 -0
- package/scripts/cli-schema.js +163 -1
- package/scripts/codex-runbook-flywheel.js +318 -0
- package/scripts/context-footprint.js +186 -0
- package/scripts/contextfs.js +143 -61
- package/scripts/dashboard-limits.js +27 -0
- package/scripts/dashboard.js +279 -9
- package/scripts/deepseek-v4-runtime-guardrails.js +72 -6
- package/scripts/docker-sandbox-planner.js +18 -0
- package/scripts/double-blind-eval-protocol.js +252 -0
- package/scripts/edotenv-rl-gateway.js +259 -0
- package/scripts/ensure-production-search-corpus.js +162 -0
- package/scripts/eval-holdout.js +311 -0
- package/scripts/feedback-aggregate.js +21 -2
- package/scripts/feedback-loop.js +87 -5
- package/scripts/feedback-quality.js +9 -0
- package/scripts/file-ledger-lock.js +4 -1
- package/scripts/financial-control-plane.js +41 -1
- package/scripts/find-dormant-requires.js +118 -0
- package/scripts/fs-utils.js +84 -8
- package/scripts/gate-stats.js +2 -2
- package/scripts/gates-engine.js +859 -58
- package/scripts/generate-case-study-outreach.js +24 -15
- package/scripts/git-at-scale.js +628 -0
- package/scripts/governance-conflict-audit.js +1650 -0
- package/scripts/governance-difficulty-curriculum.js +328 -0
- package/scripts/graphrag-retrieval.js +275 -0
- package/scripts/gurobi-optimizer.js +324 -0
- package/scripts/gurobi_optimizer.py +485 -0
- package/scripts/harness-selector.js +82 -1
- package/scripts/hidden-entry-points.js +284 -0
- package/scripts/human-escalation.js +199 -1
- package/scripts/hybrid-feedback-context.js +152 -19
- package/scripts/intent-governed-execution.js +602 -0
- package/scripts/intervention-policy.js +123 -20
- package/scripts/jit-harness-compose.js +628 -0
- package/scripts/jsonl-watcher.js +10 -0
- package/scripts/lesson-embedding-index.js +95 -12
- package/scripts/lesson-retrieval.js +105 -19
- package/scripts/local-model-profile.js +19 -2
- package/scripts/mailer/resend-mailer.js +1 -1
- package/scripts/matryoshka-embedding.js +235 -0
- package/scripts/mcp-oauth.js +42 -4
- package/scripts/mcp-session-handles.js +1016 -0
- package/scripts/mcp-wiring-doctor.js +314 -0
- package/scripts/memory-firewall.js +115 -2
- package/scripts/memory-scope-readiness.js +299 -0
- package/scripts/memory-vs-rag-route.js +161 -0
- package/scripts/model-tier-router.js +148 -21
- package/scripts/nvidia-specdecode-al-doctor.js +536 -0
- package/scripts/openui-catalog-compose-honesty.js +593 -0
- package/scripts/operational-integrity.js +19 -1
- package/scripts/override-audit.js +213 -0
- package/scripts/package-manager-honesty-doctor.js +458 -0
- package/scripts/pr-manager.js +63 -1
- package/scripts/prove-herdr-adapter.js +52 -0
- package/scripts/prove-memory-pyramid-and-symbolic-canvas.js +95 -0
- package/scripts/prove-workos.js +73 -0
- package/scripts/provider-attestation-conformance.js +192 -0
- package/scripts/provider-receipt-contract.js +136 -0
- package/scripts/qwen38-max-cost-optimizer.js +401 -0
- package/scripts/radware-threat-defense.js +280 -0
- package/scripts/rag-embedding-identity.js +221 -0
- package/scripts/rag-precision-guardrails.js +112 -2
- package/scripts/remote-feedback-capture.js +159 -0
- package/scripts/research-agent-harness.js +256 -0
- package/scripts/rsi-safety-hillclimb.js +200 -0
- package/scripts/rule-sprawl.js +188 -0
- package/scripts/schedule-manager.js +147 -0
- package/scripts/self-heal.js +8 -0
- package/scripts/session-lease.js +415 -0
- package/scripts/simatree-data-governance.js +347 -0
- package/scripts/slo-alert-engine.js +172 -7
- package/scripts/solver-parity.js +539 -0
- package/scripts/stealth-memory-injection-gate.js +333 -0
- package/scripts/switchyard-router.js +366 -0
- package/scripts/telemetry-analytics.js +84 -27
- package/scripts/temporal-decay-weighting.js +138 -0
- package/scripts/test-all.js +165 -0
- package/scripts/token-savings.js +42 -0
- package/scripts/tool-kpi-tracker.js +108 -5
- package/scripts/tool-registry.js +193 -5
- package/scripts/universal-claim-evaluator.js +14 -2
- package/scripts/vector-store.js +279 -9
- package/scripts/workflow-notebook.js +391 -0
- package/scripts/workflow-sentinel.js +111 -12
- package/scripts/workos-production-guard.js +260 -0
- package/scripts/workspace-search-route.js +515 -0
- package/server.json +2 -2
- package/src/agent-identity-boundary.js +76 -0
- package/src/agent-retrieval-cache.js +155 -0
- package/src/alert-noise-ledger.js +502 -0
- package/src/api/server.js +802 -185
- package/src/git-fast-cache.js +220 -0
- package/src/git-wal-sync.js +156 -0
- package/src/hash-anchored-edit.js +82 -0
- package/src/hermes-platform-protocol.js +475 -0
- package/src/hermes-sync-plane.js +241 -0
- package/src/index.js +30 -1
- package/src/iso42001-compliance-guard.js +97 -0
- package/src/latency-budget.js +244 -0
- package/src/mcp-writeguard.js +316 -0
- package/src/miminions-adapter.js +106 -0
- package/src/pipeline-compass.js +104 -0
- package/src/ppl-alert-pipeline.js +284 -0
- package/src/rendezvous-router.js +90 -0
- package/src/security-questionnaire.js +195 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Claw Harness Production Readiness — ThumbGate steal of the Microsoft Agent
|
|
5
|
+
* Framework "Making your claw production-ready" harness pattern
|
|
6
|
+
* (devblogs.microsoft.com/agent-framework, Part 4, Wes Steyn).
|
|
7
|
+
*
|
|
8
|
+
* The article's four production axes, mapped onto ThumbGate claw governance:
|
|
9
|
+
*
|
|
10
|
+
* 1. Define once, host many. The article splits one agent factory across
|
|
11
|
+
* three thin hosts (console / hosted / evals) so every host runs the
|
|
12
|
+
* SAME agent. -> buildHarness(host): one capability manifest, three
|
|
13
|
+
* postures. No subtly different copies.
|
|
14
|
+
*
|
|
15
|
+
* 2. Governance screens prompts AND responses. Purview blocks disallowed
|
|
16
|
+
* content, replaces it with a policy message, and logs the interaction
|
|
17
|
+
* for audit. -> screenContent(): deterministic pattern screen over the
|
|
18
|
+
* same two directions, opt-in per host, with an append-only audit trail.
|
|
19
|
+
*
|
|
20
|
+
* 3. Hosted builds turn off risky capabilities. The article disables file
|
|
21
|
+
* access and shell on the hosted container (exfiltration/tampering/
|
|
22
|
+
* persistence risk, "even behind a deny-list"); file access only via an
|
|
23
|
+
* external governed store; CodeAct only inside an externally sandboxed
|
|
24
|
+
* container. -> the hosted posture encodes exactly those defaults.
|
|
25
|
+
*
|
|
26
|
+
* 4. Evals on every change. Local function evaluators (fast, free,
|
|
27
|
+
* CI-runnable) plus gated hosted evals; results feed the tuning loop.
|
|
28
|
+
* -> runLocalEvals(): plain-function evaluators returning
|
|
29
|
+
* { passed, total, failures }. No hosted dependency required.
|
|
30
|
+
*
|
|
31
|
+
* Honesty: this is deterministic policy logic. It does not run Azure,
|
|
32
|
+
* Foundry, or Purview; it encodes their risk decisions as enforceable
|
|
33
|
+
* manifests ThumbGate can gate on.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const HOSTS = Object.freeze(['console', 'hosted', 'evals']);
|
|
37
|
+
|
|
38
|
+
const PAN_PATTERN = /\b(?:\d[ -]?){13,16}\b/;
|
|
39
|
+
const SECRET_PATTERNS = Object.freeze([
|
|
40
|
+
{ id: 'aws-key', re: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
41
|
+
{ id: 'private-key-block', re: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/ },
|
|
42
|
+
{ id: 'ghp-token', re: /\bghp_[A-Za-z0-9]{36}\b/ },
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build the capability manifest for one host posture. One definition,
|
|
47
|
+
* three hosts — the article's core structural move.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} host console | hosted | evals
|
|
50
|
+
* @param {object} opts { fileStore?: string, codeActSandboxed?: boolean }
|
|
51
|
+
*/
|
|
52
|
+
function buildHarness(host, opts) {
|
|
53
|
+
if (!HOSTS.includes(host)) {
|
|
54
|
+
return { error: `unknown host "${host}" — expected one of ${HOSTS.join(', ')}` };
|
|
55
|
+
}
|
|
56
|
+
const o = opts || {};
|
|
57
|
+
const base = {
|
|
58
|
+
host,
|
|
59
|
+
source: new URL('https://devblogs.microsoft.com/agent-framework/agent-harness-making-your-claw-production-ready/').href,
|
|
60
|
+
telemetry: { spans: true, tokenMetrics: true, export: host === 'hosted' ? 'auto' : 'manual' },
|
|
61
|
+
governance: { screenPrompts: true, screenResponses: true, audit: true },
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (host === 'hosted') {
|
|
65
|
+
// The article's deliberate divergence: shell and container-disk file
|
|
66
|
+
// access are OFF in a shared hosted environment.
|
|
67
|
+
return {
|
|
68
|
+
...base,
|
|
69
|
+
capabilities: {
|
|
70
|
+
shell: false,
|
|
71
|
+
fileAccess: o.fileStore ? 'external-store' : false,
|
|
72
|
+
fileStore: o.fileStore || null,
|
|
73
|
+
codeAct: o.codeActSandboxed ? 'sandboxed-container' : false,
|
|
74
|
+
backgroundAgents: true,
|
|
75
|
+
},
|
|
76
|
+
notes: [
|
|
77
|
+
'shell disabled on hosted posture (exfiltration/tampering/persistence risk)',
|
|
78
|
+
o.fileStore
|
|
79
|
+
? 'file access allowed ONLY through the external governed store'
|
|
80
|
+
: 'container-disk file access denied; supply a governed file store to enable',
|
|
81
|
+
o.codeActSandboxed
|
|
82
|
+
? 'codeAct allowed: externally sandboxed container'
|
|
83
|
+
: 'codeAct disabled: not externally sandboxed',
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (host === 'evals') {
|
|
89
|
+
return {
|
|
90
|
+
...base,
|
|
91
|
+
capabilities: {
|
|
92
|
+
shell: false,
|
|
93
|
+
fileAccess: false,
|
|
94
|
+
codeAct: false,
|
|
95
|
+
backgroundAgents: false,
|
|
96
|
+
},
|
|
97
|
+
notes: ['evals posture: deterministic checks only; no side-effecting capabilities'],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// console: the development posture — capabilities on, telemetry wired by hand
|
|
102
|
+
return {
|
|
103
|
+
...base,
|
|
104
|
+
capabilities: {
|
|
105
|
+
shell: true,
|
|
106
|
+
fileAccess: true,
|
|
107
|
+
codeAct: true,
|
|
108
|
+
backgroundAgents: true,
|
|
109
|
+
},
|
|
110
|
+
notes: ['console posture: full capabilities; wire your OTLP exporter yourself'],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Governance screen (the Purview analog): check one prompt or response
|
|
116
|
+
* against deterministic patterns. Blocked content is replaced with a policy
|
|
117
|
+
* message and the interaction is recorded for audit.
|
|
118
|
+
*
|
|
119
|
+
* @param {string} text
|
|
120
|
+
* @param {object} ctx { direction: 'prompt'|'response', audit?: Array }
|
|
121
|
+
*/
|
|
122
|
+
function screenContent(text, ctx) {
|
|
123
|
+
const direction = ctx && ctx.direction === 'response' ? 'response' : 'prompt';
|
|
124
|
+
const audit = ctx && Array.isArray(ctx.audit) ? ctx.audit : null;
|
|
125
|
+
const s = typeof text === 'string' ? text : '';
|
|
126
|
+
|
|
127
|
+
let hit = null;
|
|
128
|
+
if (PAN_PATTERN.test(s)) hit = { policy: 'pan', reason: 'looks like a card number' };
|
|
129
|
+
if (!hit) {
|
|
130
|
+
for (const p of SECRET_PATTERNS) {
|
|
131
|
+
if (p.re.test(s)) { hit = { policy: p.id, reason: 'credential pattern' }; break; }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const result = hit
|
|
136
|
+
? {
|
|
137
|
+
decision: 'block',
|
|
138
|
+
policy: hit.policy,
|
|
139
|
+
reason: hit.reason,
|
|
140
|
+
replacement: '[BLOCKED BY POLICY: content screened and withheld]',
|
|
141
|
+
direction,
|
|
142
|
+
}
|
|
143
|
+
: { decision: 'pass', direction };
|
|
144
|
+
|
|
145
|
+
if (audit) {
|
|
146
|
+
audit.push({
|
|
147
|
+
at: new Date().toISOString(),
|
|
148
|
+
direction,
|
|
149
|
+
decision: result.decision,
|
|
150
|
+
policy: hit ? hit.policy : null,
|
|
151
|
+
// audit stores metadata, never the screened content itself
|
|
152
|
+
chars: s.length,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Local evals (the article's LocalEvaluator): plain function evaluators,
|
|
160
|
+
* fast, free, CI-runnable. Each evaluator gets { query, response } and
|
|
161
|
+
* returns a boolean.
|
|
162
|
+
*/
|
|
163
|
+
function runLocalEvals(cases, evaluators) {
|
|
164
|
+
const failures = [];
|
|
165
|
+
let passed = 0;
|
|
166
|
+
for (const item of cases || []) {
|
|
167
|
+
for (const ev of evaluators || []) {
|
|
168
|
+
const ok = Boolean(ev.fn({ query: item.query, response: item.response }));
|
|
169
|
+
if (ok) passed += 1;
|
|
170
|
+
else failures.push({ query: item.query, evaluator: ev.name });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const total = (cases || []).length * (evaluators || []).length;
|
|
174
|
+
return { passed, total, failures, passRate: total === 0 ? 1 : passed / total };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Telemetry rollup (the OTel source-name idea): spans in, one summary out.
|
|
179
|
+
*/
|
|
180
|
+
function rollupTelemetry(spans) {
|
|
181
|
+
const tools = new Map();
|
|
182
|
+
let tokens = 0;
|
|
183
|
+
for (const span of spans || []) {
|
|
184
|
+
const name = span.tool || span.name || 'unknown';
|
|
185
|
+
tools.set(name, (tools.get(name) || 0) + 1);
|
|
186
|
+
tokens += Number(span.tokens || 0);
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
spanCount: (spans || []).length,
|
|
190
|
+
tokensTotal: tokens,
|
|
191
|
+
toolCalls: Object.fromEntries(tools),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isCliEntrypoint() {
|
|
196
|
+
return require.main === module;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function main() {
|
|
200
|
+
const audit = [];
|
|
201
|
+
const harnesses = HOSTS.map((h) => buildHarness(h, { fileStore: 'blob://claw-files' }));
|
|
202
|
+
const screens = [
|
|
203
|
+
screenContent('what is my balance?', { direction: 'prompt', audit }),
|
|
204
|
+
screenContent('card 4111 1111 1111 1111 on file', { direction: 'prompt', audit }),
|
|
205
|
+
screenContent('use AKIAIOSFODNN7EXAMPLE for auth', { direction: 'response', audit }),
|
|
206
|
+
];
|
|
207
|
+
const evals = runLocalEvals(
|
|
208
|
+
[
|
|
209
|
+
{ query: 'Value MSFT', response: 'MSFT is valued at $3.2T' },
|
|
210
|
+
{ query: 'Value MSFT', response: 'I cannot say' },
|
|
211
|
+
{ query: 'hello', response: 'hi!' },
|
|
212
|
+
],
|
|
213
|
+
[
|
|
214
|
+
{ name: 'numeric_valuation', fn: ({ query, response }) => !/value msft/i.test(query) || /\d/.test(response) },
|
|
215
|
+
],
|
|
216
|
+
);
|
|
217
|
+
const telemetry = rollupTelemetry([
|
|
218
|
+
{ tool: 'read_file', tokens: 120 },
|
|
219
|
+
{ tool: 'shell', tokens: 40 },
|
|
220
|
+
{ tool: 'shell', tokens: 60 },
|
|
221
|
+
]);
|
|
222
|
+
process.stdout.write(JSON.stringify({
|
|
223
|
+
honesty: 'deterministic policy logic; no Azure/Foundry/Purview runtime involved',
|
|
224
|
+
harnesses, screens, evals, telemetry,
|
|
225
|
+
}, null, 2) + '\n');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (isCliEntrypoint()) main();
|
|
229
|
+
|
|
230
|
+
module.exports = {
|
|
231
|
+
HOSTS,
|
|
232
|
+
buildHarness,
|
|
233
|
+
screenContent,
|
|
234
|
+
runLocalEvals,
|
|
235
|
+
rollupTelemetry,
|
|
236
|
+
isCliEntrypoint,
|
|
237
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight CLI progress for long-running commands (dashboard, cfo, north-star).
|
|
5
|
+
* TTY: spinner on stderr. Non-TTY / THUMBGATE_NO_PROGRESS=1: plain step lines.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
9
|
+
|
|
10
|
+
function isProgressEnabled(stream = process.stderr, env = process.env) {
|
|
11
|
+
if (String(env.THUMBGATE_NO_PROGRESS || '').trim() === '1') return false;
|
|
12
|
+
if (String(env.CI || '').trim()) return false; // avoid noisy CI logs
|
|
13
|
+
return Boolean(stream && stream.isTTY);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createCliProgress(options = {}) {
|
|
17
|
+
const stream = options.stream || process.stderr;
|
|
18
|
+
const env = options.env || process.env;
|
|
19
|
+
const enabled = options.enabled !== undefined
|
|
20
|
+
? Boolean(options.enabled)
|
|
21
|
+
: isProgressEnabled(stream, env);
|
|
22
|
+
|
|
23
|
+
let label = '';
|
|
24
|
+
let frame = 0;
|
|
25
|
+
let timer = null;
|
|
26
|
+
let active = false;
|
|
27
|
+
|
|
28
|
+
function clearLine() {
|
|
29
|
+
if (!enabled || !stream.clearLine) return;
|
|
30
|
+
try {
|
|
31
|
+
stream.clearLine(0);
|
|
32
|
+
stream.cursorTo(0);
|
|
33
|
+
} catch { /* non-TTY fallback */ }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function paint() {
|
|
37
|
+
if (!enabled || !active) return;
|
|
38
|
+
const glyph = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
39
|
+
frame += 1;
|
|
40
|
+
clearLine();
|
|
41
|
+
stream.write(`${glyph} ${label}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function start(nextLabel) {
|
|
45
|
+
label = String(nextLabel || 'Working…');
|
|
46
|
+
active = true;
|
|
47
|
+
if (!enabled) {
|
|
48
|
+
stream.write(`[thumbgate] ${label}\n`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
paint();
|
|
52
|
+
if (timer) clearInterval(timer);
|
|
53
|
+
timer = setInterval(paint, 80);
|
|
54
|
+
if (typeof timer.unref === 'function') timer.unref();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function update(nextLabel) {
|
|
58
|
+
label = String(nextLabel || label);
|
|
59
|
+
if (!enabled) {
|
|
60
|
+
stream.write(`[thumbgate] ${label}\n`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!active) {
|
|
64
|
+
start(label);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
paint();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function stop(finalLabel, { ok = true } = {}) {
|
|
71
|
+
if (timer) {
|
|
72
|
+
clearInterval(timer);
|
|
73
|
+
timer = null;
|
|
74
|
+
}
|
|
75
|
+
const text = finalLabel != null ? String(finalLabel) : label;
|
|
76
|
+
if (!enabled) {
|
|
77
|
+
if (text) stream.write(`[thumbgate] ${text}\n`);
|
|
78
|
+
active = false;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
clearLine();
|
|
82
|
+
if (text) {
|
|
83
|
+
const mark = ok ? '✓' : '✗';
|
|
84
|
+
stream.write(`${mark} ${text}\n`);
|
|
85
|
+
}
|
|
86
|
+
active = false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function succeed(finalLabel) {
|
|
90
|
+
stop(finalLabel, { ok: true });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function fail(finalLabel) {
|
|
94
|
+
stop(finalLabel, { ok: false });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
enabled,
|
|
99
|
+
start,
|
|
100
|
+
update,
|
|
101
|
+
stop,
|
|
102
|
+
succeed,
|
|
103
|
+
fail,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = {
|
|
108
|
+
createCliProgress,
|
|
109
|
+
isProgressEnabled,
|
|
110
|
+
SPINNER_FRAMES,
|
|
111
|
+
};
|
package/scripts/cli-schema.js
CHANGED
|
@@ -158,6 +158,13 @@ const CLI_COMMANDS = [
|
|
|
158
158
|
description: 'Audit runtime isolation, bootstrap context, and permission tier',
|
|
159
159
|
flags: [jsonFlag()],
|
|
160
160
|
}),
|
|
161
|
+
discoveryCommand({
|
|
162
|
+
name: 'security-central',
|
|
163
|
+
aliases: ['security:central', 'agent-security-central'],
|
|
164
|
+
description:
|
|
165
|
+
'Free local Agent Security Central posture report (config drift, privileged coverage, policy variance, audit evidence)',
|
|
166
|
+
flags: [jsonFlag()],
|
|
167
|
+
}),
|
|
161
168
|
discoveryCommand({
|
|
162
169
|
name: 'harness-audit',
|
|
163
170
|
aliases: ['harness'],
|
|
@@ -342,11 +349,31 @@ const CLI_COMMANDS = [
|
|
|
342
349
|
{ name: 'top-k', type: 'number', description: 'Retrieval k used for the baseline and candidate metrics' },
|
|
343
350
|
{ name: 'threshold-change', type: 'boolean', description: 'Mark that vector threshold or top-k routing changed' },
|
|
344
351
|
{ name: 'embedding-finetune', type: 'boolean', description: 'Mark that embedding fine-tuning or replacement is proposed' },
|
|
352
|
+
{ name: 'embedding-model-change', type: 'boolean', description: 'Mark that the embedding provider or model is changing' },
|
|
353
|
+
{ name: 'baseline-provider', type: 'string', description: 'Current embedding provider fingerprint (ollama, gemini, local, …)' },
|
|
354
|
+
{ name: 'new-provider', type: 'string', description: 'Proposed embedding provider fingerprint' },
|
|
355
|
+
{ name: 'baseline-model', type: 'string', description: 'Current embedding model id' },
|
|
356
|
+
{ name: 'new-model', type: 'string', description: 'Proposed embedding model id' },
|
|
357
|
+
{ name: 'baseline-dim', type: 'number', description: 'Current embedding output dimensionality' },
|
|
358
|
+
{ name: 'new-dim', type: 'number', description: 'Proposed Matryoshka/truncated output dimensionality' },
|
|
359
|
+
{ name: 'matryoshka-truncation', type: 'boolean', description: 'Mark that Matryoshka leading-dim truncation is proposed' },
|
|
345
360
|
{ name: 'structural-near-misses', type: 'boolean', description: 'Mark that negation or role-reversal near misses matter' },
|
|
346
361
|
{ name: 'verifier', type: 'boolean', description: 'Mark that a second-stage verifier or reranker is present' },
|
|
347
362
|
{ name: 'latency-ms', type: 'number', description: 'Observed end-to-end retrieval latency after verifier or reranker' },
|
|
348
363
|
{ name: 'latency-budget-ms', type: 'number', description: 'Workflow retrieval latency budget' },
|
|
349
364
|
{ name: 'agentic', type: 'boolean', description: 'Mark that retrieval output can trigger downstream agent actions' },
|
|
365
|
+
{ name: 'hybrid-retrieval', type: 'boolean', description: 'Mark that dense+sparse hybrid retrieval is in use' },
|
|
366
|
+
{ name: 'dense', type: 'boolean', description: 'Mark dense/embedding retrieval is measured' },
|
|
367
|
+
{ name: 'sparse', type: 'boolean', description: 'Mark sparse/keyword retrieval is measured' },
|
|
368
|
+
{ name: 'source-grounding', type: 'boolean', description: 'Mark that source citations are enforced' },
|
|
369
|
+
{ name: 'acl-filter', type: 'boolean', description: 'Mark that access-control filtering is enforced' },
|
|
370
|
+
{ name: 'scale-corpus-documents', type: 'number', description: 'Corpus size used for scale-wall governance' },
|
|
371
|
+
{ name: 'input-tokens', type: 'number', description: 'Input tokens consumed by the operation' },
|
|
372
|
+
{ name: 'output-tokens', type: 'number', description: 'Output tokens generated by the operation' },
|
|
373
|
+
{ name: 'est-cost-usd', type: 'number', description: 'Estimated cost in USD for the operation' },
|
|
374
|
+
{ name: 'model-cost-per-1k', type: 'number', description: 'Cost per 1000 tokens for the model used' },
|
|
375
|
+
{ name: 'cost-delta-percent', type: 'number', description: 'Cost difference percentage if routed to alternative model' },
|
|
376
|
+
{ name: 'recommended-model', type: 'string', description: 'Cost-optimal model recommendation (qwen, claude, gemini, etc.)' },
|
|
350
377
|
],
|
|
351
378
|
}),
|
|
352
379
|
discoveryCommand({
|
|
@@ -417,6 +444,136 @@ const CLI_COMMANDS = [
|
|
|
417
444
|
{ name: 'truncation-failures', type: 'boolean', description: 'Mark that failures may be truncation-related' },
|
|
418
445
|
],
|
|
419
446
|
}),
|
|
447
|
+
|
|
448
|
+
discoveryCommand({
|
|
449
|
+
name: 'allowlist-bridge-honesty',
|
|
450
|
+
aliases: ['gitlab-sandbox-allowlist', 'allowlist-not-trust', 'trust-handoff-honesty'],
|
|
451
|
+
description: 'Audit allowlisted package registries/proxies as hops not trust boundaries (GitLab 2026-09 FORMAT steal; does not clone GitLab Duo)',
|
|
452
|
+
flags: [
|
|
453
|
+
jsonFlag(),
|
|
454
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero on fail' },
|
|
455
|
+
{ name: 'root', type: 'string', description: 'Repo root to scan (default cwd)' },
|
|
456
|
+
{ name: 'allow-hosts', type: 'string', description: 'Comma-separated extra allowlisted hosts' },
|
|
457
|
+
{ name: 'treat-allowlist-as-trust', type: 'boolean', description: 'Fail closed if bridge hosts are treated as trusted' },
|
|
458
|
+
{ name: 'write', type: 'string', description: 'Privileged consumer path to classify as trust-handoff' },
|
|
459
|
+
{ name: 'claimed-contained', type: 'boolean', description: 'Fail if a handoff write is claimed sandbox-contained' },
|
|
460
|
+
{ name: 'evaluate-url', type: 'string', description: 'Probe egress evaluation against the allowlist' },
|
|
461
|
+
{ name: 'clone-gitlab-duo', type: 'boolean', description: 'Refuse GitLab Duo sandbox SKU clone' },
|
|
462
|
+
],
|
|
463
|
+
}),
|
|
464
|
+
|
|
465
|
+
discoveryCommand({
|
|
466
|
+
name: 'package-manager-honesty-doctor',
|
|
467
|
+
aliases: ['pm-honesty-doctor', 'pnpm12-honesty-doctor', 'lockfile-ci-parity-doctor'],
|
|
468
|
+
description: 'Audit lockfile/packageManager/CI install parity and fail-closed package-manager switches (InfoQ pnpm 12 process steal; does not migrate off npm)',
|
|
469
|
+
flags: [
|
|
470
|
+
jsonFlag(),
|
|
471
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero on fail or actionable findings' },
|
|
472
|
+
{ name: 'root', type: 'string', description: 'Repo root to scan (default cwd)' },
|
|
473
|
+
{ name: 'propose-switch', type: 'string', description: 'Fail-closed checklist for switching to npm|pnpm|yarn|bun' },
|
|
474
|
+
{ name: 'allow-ignore-scripts-gaps', type: 'boolean', description: 'Do not warn when CI installs omit --ignore-scripts' },
|
|
475
|
+
],
|
|
476
|
+
}),
|
|
477
|
+
|
|
478
|
+
discoveryCommand({
|
|
479
|
+
name: 'openui-catalog-compose-honesty',
|
|
480
|
+
aliases: ['openui-honesty-doctor', 'catalog-compose-honesty', 'repair-before-compose-claim'],
|
|
481
|
+
description: 'OpenUI FORMAT steal: catalog-compose-only, root-first streaming, repair-before-claim (does not install @openuidev or clone Thesys Gateway)',
|
|
482
|
+
flags: [
|
|
483
|
+
jsonFlag(),
|
|
484
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero on fail or actionable findings' },
|
|
485
|
+
{ name: 'root', type: 'string', description: 'Repo root for relative paths (default cwd)' },
|
|
486
|
+
{ name: 'catalog', type: 'string', description: 'Path to JSON component catalog' },
|
|
487
|
+
{ name: 'stream', type: 'string', description: 'Path to line-oriented compose stream' },
|
|
488
|
+
{ name: 'compose', type: 'string', description: 'Alias for --stream' },
|
|
489
|
+
{ name: 'repair', type: 'boolean', description: 'Include dropped lines and repaired stream text' },
|
|
490
|
+
{ name: 'claim-ready', type: 'boolean', description: 'Fail unless repair is clean (root + zero drops)' },
|
|
491
|
+
],
|
|
492
|
+
}),
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
discoveryCommand({
|
|
496
|
+
name: 'intent-governed-execution',
|
|
497
|
+
aliases: ['governed-intent', 'cyberstrike-governed', 'intent-govern'],
|
|
498
|
+
description: 'Compose CyberStrikeAI intent→governed-execution FORMAT onto existing rails (HITL + evidence memory; does not clone CyberStrike/Eino)',
|
|
499
|
+
flags: [
|
|
500
|
+
jsonFlag(),
|
|
501
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero unless status=ready' },
|
|
502
|
+
{ name: 'intent', type: 'string', description: 'Natural-language intent to govern' },
|
|
503
|
+
{ name: 'task', type: 'string', description: 'Alias for --intent' },
|
|
504
|
+
{ name: 'class', type: 'string', description: 'Force intent class' },
|
|
505
|
+
{ name: 'risk', type: 'string', description: 'Force risk low|medium|high|critical' },
|
|
506
|
+
{ name: 'harness', type: 'string', description: 'Force gate harness' },
|
|
507
|
+
{ name: 'profile', type: 'string', description: 'Force subagent profile' },
|
|
508
|
+
{ name: 'approved', type: 'boolean', description: 'HITL already satisfied (human grant only)' },
|
|
509
|
+
{ name: 'map-only', type: 'boolean', description: 'Print six-step governance map' },
|
|
510
|
+
{ name: 'root', type: 'string', description: 'Repo root to probe' },
|
|
511
|
+
],
|
|
512
|
+
}),
|
|
513
|
+
discoveryCommand({
|
|
514
|
+
name: 'jit-harness-compose',
|
|
515
|
+
aliases: ['jit-compose', 'jit-harness', 'harness-compose'],
|
|
516
|
+
description: 'Compose JIT-Agent four-module harness FORMAT (memory/planning/action/capability) onto existing ThumbGate rails — does not train or download JIT-Agent',
|
|
517
|
+
flags: [
|
|
518
|
+
jsonFlag(),
|
|
519
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero unless status=ready' },
|
|
520
|
+
{ name: 'task', type: 'string', description: 'Task text to classify and compose' },
|
|
521
|
+
{ name: 'query', type: 'string', description: 'Alias for --task' },
|
|
522
|
+
{ name: 'class', type: 'string', description: 'Force task class (code_edit|review|deploy|research|secure|routine|db_write|default)' },
|
|
523
|
+
{ name: 'harness', type: 'string', description: 'Force gate harness name' },
|
|
524
|
+
{ name: 'profile', type: 'string', description: 'Force subagent profile' },
|
|
525
|
+
{ name: 'roles', type: 'string', description: 'Comma-separated switchyard roles' },
|
|
526
|
+
{ name: 'toolName', type: 'string', description: 'Tool-name hint for harness-selector' },
|
|
527
|
+
{ name: 'map-only', type: 'boolean', description: 'Print four-module rail map only' },
|
|
528
|
+
{ name: 'root', type: 'string', description: 'Repo root to probe' },
|
|
529
|
+
],
|
|
530
|
+
}),
|
|
531
|
+
discoveryCommand({
|
|
532
|
+
name: 'workspace-search-route',
|
|
533
|
+
aliases: ['zg-search-route', 'zvec-grep-route', 'search-route'],
|
|
534
|
+
description: 'Route a query to rg/fts/vector/hybrid/graph on existing rails (zg zvec-grep FORMAT steal; does not install @zvec/zvec-grep)',
|
|
535
|
+
flags: [
|
|
536
|
+
jsonFlag(),
|
|
537
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero unless status=ready' },
|
|
538
|
+
{ name: 'root', type: 'string', description: 'Repo root (default cwd)' },
|
|
539
|
+
{ name: 'query', type: 'string', description: 'Query text to classify or execute' },
|
|
540
|
+
{ name: 'route', type: 'string', description: 'Force route: hybrid|fts|vector|rg|graph' },
|
|
541
|
+
{ name: 'rg', type: 'boolean', description: 'Force exact/regex route' },
|
|
542
|
+
{ name: 'fts', type: 'boolean', description: 'Force BM25/lexical route' },
|
|
543
|
+
{ name: 'vector', type: 'boolean', description: 'Force semantic/dense route' },
|
|
544
|
+
{ name: 'hybrid', type: 'boolean', description: 'Force RRF hybrid route' },
|
|
545
|
+
{ name: 'graph', type: 'boolean', description: 'Force Graphify AST route' },
|
|
546
|
+
{ name: 'execute', type: 'boolean', description: 'Run the chosen local rail (best-effort)' },
|
|
547
|
+
{ name: 'limit', type: 'number', description: 'Max hits when executing' },
|
|
548
|
+
{ name: 'force-remote', type: 'boolean', description: 'Request remote embeddings (needs THUMBGATE_ALLOW_REMOTE_EMBED=1)' },
|
|
549
|
+
{ name: 'map-only', type: 'boolean', description: 'Print route map only' },
|
|
550
|
+
],
|
|
551
|
+
}),
|
|
552
|
+
discoveryCommand({
|
|
553
|
+
name: 'nvidia-specdecode-al-doctor',
|
|
554
|
+
aliases: ['specdecode-al-doctor', 'speculative-decoding-al-doctor', 'nvidia-speculative-decoding-doctor'],
|
|
555
|
+
description: 'Check speculative-decoding AL/D evidence: speedup ≤ AL/(1+ρD), attention D=128/G-1, tile alignment — maps to checkpoint-speculative-decoding-acceptance',
|
|
556
|
+
flags: [
|
|
557
|
+
jsonFlag(),
|
|
558
|
+
{ name: 'strict', type: 'boolean', description: 'Exit non-zero on fail or actionable findings' },
|
|
559
|
+
{ name: 'workload', type: 'string', description: 'Workload name' },
|
|
560
|
+
{ name: 'model', type: 'string', description: 'Target model name' },
|
|
561
|
+
{ name: 'speculative-decoding', type: 'boolean', description: 'Mark that a speculation path is active' },
|
|
562
|
+
{ name: 'accept-length', type: 'number', description: 'Measured accept length AL' },
|
|
563
|
+
{ name: 'draft-length', type: 'number', description: 'Draft length D' },
|
|
564
|
+
{ name: 'draft-depth-ratio', type: 'number', description: 'Draft depth ratio ρ = L_draft / L_target' },
|
|
565
|
+
{ name: 'claimed-speedup', type: 'number', description: 'Claimed speedup to compare against AL/(1+ρD)' },
|
|
566
|
+
{ name: 'min-accept-length', type: 'number', description: 'Production AL floor (default 2)' },
|
|
567
|
+
{ name: 'query-heads-per-kv', type: 'number', description: 'Attention group size G' },
|
|
568
|
+
{ name: 'attention-dominated', type: 'boolean', description: 'Apply attention draft-length guidelines' },
|
|
569
|
+
{ name: 'latency-region', type: 'string', description: 'Pareto region hint: low or throughput' },
|
|
570
|
+
{ name: 'model-size', type: 'string', description: 'Target size hint: small, medium, or large' },
|
|
571
|
+
{ name: 'repetitive', type: 'boolean', description: 'Prefer suffix/n-gram draft class' },
|
|
572
|
+
{ name: 'next-accept-length', type: 'number', description: 'AL after raising D (Guideline 4 compare)' },
|
|
573
|
+
{ name: 'next-draft-length', type: 'number', description: 'Candidate larger D (Guideline 4 compare)' },
|
|
574
|
+
{ name: 'cache-coherence-eval', type: 'boolean', description: 'Rollback/coherence evidence present' },
|
|
575
|
+
],
|
|
576
|
+
}),
|
|
420
577
|
discoveryCommand({
|
|
421
578
|
name: 'deepseek-v4-runtime-guardrails',
|
|
422
579
|
aliases: ['sparse-attention-runtime-guardrails', 'deepseek-runtime-guardrails'],
|
|
@@ -434,7 +591,12 @@ const CLI_COMMANDS = [
|
|
|
434
591
|
{ name: 'prefix-cache', type: 'boolean', description: 'Mark that prefix caching is active' },
|
|
435
592
|
{ name: 'cache-coherence-eval', type: 'boolean', description: 'Mark that cache reuse and rollback coherence were evaluated' },
|
|
436
593
|
{ name: 'speculative-decoding', type: 'boolean', description: 'Mark that MTP, EAGLE, or another speculation path is active' },
|
|
437
|
-
{ name: 'accept-length', type: 'number', description: 'Measured speculative decoding accept length' },
|
|
594
|
+
{ name: 'accept-length', type: 'number', description: 'Measured speculative decoding accept length (AL)' },
|
|
595
|
+
{ name: 'draft-length', type: 'number', description: 'Speculative draft length D (tokens proposed per target iteration)' },
|
|
596
|
+
{ name: 'draft-depth-ratio', type: 'number', description: 'Draft depth ratio ρ = L_draft / L_target for AL/(1+ρD) speedup math' },
|
|
597
|
+
{ name: 'claimed-speedup', type: 'number', description: 'Claimed speculation speedup to check against AL/(1+ρD)' },
|
|
598
|
+
{ name: 'query-heads-per-kv', type: 'number', description: 'Attention group size G (query heads per KV head)' },
|
|
599
|
+
{ name: 'attention-dominated', type: 'boolean', description: 'Mark that attention dominates decode (apply D=128/G-1 guidance)' },
|
|
438
600
|
{ name: 'kv-offload', type: 'boolean', description: 'Mark that KV cache offload or capacity extension is active' },
|
|
439
601
|
{ name: 'training', type: 'boolean', description: 'Mark that the rollout feeds RL, DPO, or fine-tuning' },
|
|
440
602
|
{ name: 'rollout-replay', type: 'boolean', description: 'Mark that rollout routing replay is captured' },
|