@tech-leads-club/harness-toolkit 0.10.6 → 0.11.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/README.md +6 -4
- package/bin/tlc-cli.ts +60 -1
- package/capabilities/catalog.json +18 -1
- package/dist/compact-before.mjs +79 -78
- package/dist/doctor.mjs +83 -82
- package/dist/init-project.mjs +86 -85
- package/dist/install-runtime.mjs +80 -79
- package/dist/lessons-cli.mjs +82 -81
- package/dist/new-provider.mjs +126 -0
- package/dist/obs-cli.mjs +83 -82
- package/dist/prompt-submit.mjs +79 -78
- package/dist/refresh-model-prices.mjs +80 -79
- package/dist/response-after.mjs +80 -79
- package/dist/run.mjs +79 -78
- package/dist/session-end.mjs +85 -84
- package/dist/session-start.mjs +87 -86
- package/dist/shim.mjs +81 -80
- package/dist/ship-gate.mjs +79 -78
- package/dist/stop.mjs +86 -85
- package/dist/subagent-start.mjs +79 -78
- package/dist/subagent-stop.mjs +80 -79
- package/dist/support.mjs +84 -83
- package/dist/tlc-cli.mjs +225 -97
- package/dist/tool-after.mjs +80 -79
- package/dist/tool-before.mjs +82 -81
- package/dist/tool-failure.mjs +79 -78
- package/dist/uninstall-runtime.mjs +3 -3
- package/docs/architecture.md +16 -3
- package/docs/concepts.md +11 -0
- package/docs/log.md +4 -0
- package/docs/providers/claude-code.md +42 -21
- package/docs/providers/cursor.md +23 -7
- package/docs/troubleshooting.md +1 -0
- package/package.json +1 -1
- package/schema.json +12 -0
- package/skills/harness-init/references/capabilities.md +1 -0
- package/src/contracts/capabilities.ts +8 -1
- package/src/contracts/decision.ts +2 -1
- package/src/core/core.facade.ts +6 -0
- package/src/core/floor/floor.catalog.ts +5 -0
- package/src/core/floor/floor.paths.ts +17 -1
- package/src/core/floor/floor.policy-surface.ts +26 -9
- package/src/core/floor/floor.service.ts +37 -5
- package/src/core/policy/policy.defaults.ts +3 -0
- package/src/core/policy/policy.loader.ts +1 -0
- package/src/core/policy/policy.types.ts +4 -0
- package/src/core/secret-scan/secret-scan.service.ts +96 -0
- package/src/core/secret-scan/secret-scan.store.ts +56 -0
- package/src/entrypoints/run.ts +3 -1
- package/src/entrypoints/tool-after.ts +20 -0
- package/src/entrypoints/tool-before.ts +1 -0
- package/src/providers/claude/claude.capabilities.ts +3 -1
- package/src/providers/claude/claude.inbound.ts +37 -22
- package/src/providers/claude/claude.outbound.ts +4 -0
- package/src/providers/claude/claude.wiring.ts +4 -0
- package/src/providers/claude/index.ts +2 -1
- package/src/providers/cursor/cursor.capabilities.ts +3 -1
- package/src/providers/cursor/cursor.inbound.ts +1 -1
- package/src/providers/cursor/cursor.outbound.ts +9 -0
- package/src/providers/cursor/cursor.wiring.ts +9 -1
- package/src/providers/cursor/index.ts +2 -1
- package/src/providers/provider.degrade.ts +19 -0
- package/src/providers/provider.port.ts +1 -0
- package/tools/new-provider.ts +251 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import{createRequire as Z}from"node:module";var W=Z(import.meta.url);import{existsSync as $,mkdirSync as q,writeFileSync as C}from"node:fs";import{dirname as X,join as H}from"node:path";import{fileURLToPath as L}from"node:url";var Y=H(X(L(import.meta.url)),".."),V=/[\s/\\]/,k=new Set(["index","provider"]);function x(B){if(B.length===0)return{ok:!1,reason:"provider name must not be empty"};if(V.test(B))return{ok:!1,reason:"provider name must not contain whitespace or a slash"};if(k.has(B.toLowerCase()))return{ok:!1,reason:`"${B}" is a reserved name`};return{ok:!0}}function K(B){return B.length===0?B:`${B[0]?.toUpperCase()}${B.slice(1)}`}function M(B){return`// why: always false until real detection logic replaces it, so the provider stays inert.
|
|
2
|
+
export function detect${K(B)}(_raw: unknown): boolean {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
`}function T(B){return`import type { HarnessEventKind, ProviderCapabilities } from "../../contracts/index.ts";
|
|
6
|
+
|
|
7
|
+
export function ${B}Capabilities(): ProviderCapabilities {
|
|
8
|
+
return {
|
|
9
|
+
enforcesHooks: true,
|
|
10
|
+
askSupportedOn: [],
|
|
11
|
+
sessionEnv: false,
|
|
12
|
+
nativeLoopCounter: false,
|
|
13
|
+
dedicatedShellEvent: false,
|
|
14
|
+
toolInputRewrite: false,
|
|
15
|
+
// why: a placeholder, deliberately not a real HarnessEventKind — fails assertSatisfiesContract until replaced.
|
|
16
|
+
toolOutputRewriteOn: ["TODO-fill-in-real-capabilities" as unknown as HarnessEventKind],
|
|
17
|
+
contextAtToolBefore: false,
|
|
18
|
+
contextAtToolAfter: false,
|
|
19
|
+
contextAtStop: false,
|
|
20
|
+
sessionStartContextReliable: false,
|
|
21
|
+
toolOutputAtAfter: false,
|
|
22
|
+
usageInPayload: false,
|
|
23
|
+
effortSignal: false,
|
|
24
|
+
thoughtEvent: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
`}function U(B){return`import type { ProviderPolicyDefaults } from "../../contracts/index.ts";
|
|
28
|
+
|
|
29
|
+
export function ${B}PolicyDefaults(): ProviderPolicyDefaults {
|
|
30
|
+
return {
|
|
31
|
+
blockedPatterns: [],
|
|
32
|
+
minEffort: null,
|
|
33
|
+
untrustedTools: [],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
`}function w(B){return`import type { HarnessEvent, HarnessEventKind } from "../../contracts/index.ts";
|
|
37
|
+
|
|
38
|
+
// why: empty until this host's own hook names are mapped, so every payload falls through to null.
|
|
39
|
+
export const EVENT_KIND_BY_HOOK: Record<string, HarnessEventKind> = {};
|
|
40
|
+
|
|
41
|
+
/** Never throws on a malformed payload — returns null instead. */
|
|
42
|
+
export function ${B}ToEvent(_raw: Record<string, unknown>): HarnessEvent | null {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
`}function z(B){return`import type { ProviderWiring, RuntimePaths } from "../../contracts/index.ts";
|
|
46
|
+
|
|
47
|
+
// why: a placeholder path, until the real file this provider's host reads hooks from is named.
|
|
48
|
+
const WIRING_TARGET = "TODO: replace with the real wiring target path";
|
|
49
|
+
|
|
50
|
+
export function ${B}WiringTargets(): string[] {
|
|
51
|
+
return [WIRING_TARGET];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// why: an empty entries list, until this adapter's real hook entries replace it (see claude.wiring.ts's ENTRY_SPECS shape).
|
|
55
|
+
export function ${B}Wiring(_runtime: RuntimePaths): ProviderWiring {
|
|
56
|
+
return { target: WIRING_TARGET, strategy: "replace", entries: [] };
|
|
57
|
+
}
|
|
58
|
+
`}function A(B){return`import type { Decision, HarnessEvent, Rendered } from "../../contracts/index.ts";
|
|
59
|
+
|
|
60
|
+
// why: an unconditional abstain, until this host's real hook response schema replaces it.
|
|
61
|
+
export function ${B}Render(_decision: Decision, _event: HarnessEvent): Rendered {
|
|
62
|
+
return { stdout: null, exitCode: 0 };
|
|
63
|
+
}
|
|
64
|
+
`}function D(B){let G=K(B);return`import type { ProviderPort } from "../provider.port.ts";
|
|
65
|
+
import { ${B}Capabilities } from "./${B}.capabilities.ts";
|
|
66
|
+
import { detect${G} } from "./${B}.detect.ts";
|
|
67
|
+
import { ${B}ToEvent } from "./${B}.inbound.ts";
|
|
68
|
+
import { ${B}Render } from "./${B}.outbound.ts";
|
|
69
|
+
import { ${B}PolicyDefaults } from "./${B}.policy-defaults.ts";
|
|
70
|
+
import { ${B}Wiring, ${B}WiringTargets } from "./${B}.wiring.ts";
|
|
71
|
+
|
|
72
|
+
// why: assembled here so \`tlc harness new-provider\` has one ProviderPort to import into provider.registry.ts.
|
|
73
|
+
export const ${B}Provider: ProviderPort = {
|
|
74
|
+
name: "${B}",
|
|
75
|
+
detect: detect${G},
|
|
76
|
+
capabilities: ${B}Capabilities,
|
|
77
|
+
policyDefaults: ${B}PolicyDefaults,
|
|
78
|
+
toEvent: ${B}ToEvent,
|
|
79
|
+
render: ${B}Render,
|
|
80
|
+
wiring: ${B}Wiring,
|
|
81
|
+
wiringTargets: ${B}WiringTargets,
|
|
82
|
+
};
|
|
83
|
+
`}function F(B){let G=K(B),I=new Date().toISOString().slice(0,10);return`---
|
|
84
|
+
type: Provider
|
|
85
|
+
title: "${G} provider"
|
|
86
|
+
description: "The ${G} adapter — capability descriptor, event mapping, and wiring target."
|
|
87
|
+
tags: [provider, ${B}]
|
|
88
|
+
timestamp: "${I}"
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
# ${G} provider
|
|
92
|
+
|
|
93
|
+
Source: \`src/providers/${B}/\`.
|
|
94
|
+
|
|
95
|
+
## Detection
|
|
96
|
+
|
|
97
|
+
TODO: describe \`${B}.detect.ts\`'s real detection rule.
|
|
98
|
+
|
|
99
|
+
## Capability descriptor
|
|
100
|
+
|
|
101
|
+
\`${B}.capabilities.ts\`:
|
|
102
|
+
|
|
103
|
+
<!-- generated:capabilities -->
|
|
104
|
+
|
|
105
|
+
<!-- /generated -->
|
|
106
|
+
|
|
107
|
+
## Policy defaults
|
|
108
|
+
|
|
109
|
+
TODO: describe \`${B}.policy-defaults.ts\`'s defaults.
|
|
110
|
+
|
|
111
|
+
## Event mapping
|
|
112
|
+
|
|
113
|
+
\`${B}.inbound.ts\` maps ${G}'s own hook names to \`HarnessEventKind\`:
|
|
114
|
+
|
|
115
|
+
<!-- generated:event-mapping -->
|
|
116
|
+
|
|
117
|
+
<!-- /generated -->
|
|
118
|
+
|
|
119
|
+
## Wiring target
|
|
120
|
+
|
|
121
|
+
TODO: describe \`${B}.wiring.ts\`'s wiring target and strategy.
|
|
122
|
+
|
|
123
|
+
## See also
|
|
124
|
+
|
|
125
|
+
- [/providers/index.md](/providers/index.md)
|
|
126
|
+
`}function N(B){let G=H("src","providers",B);return[{path:H(G,`${B}.detect.ts`),content:M(B)},{path:H(G,`${B}.capabilities.ts`),content:T(B)},{path:H(G,`${B}.policy-defaults.ts`),content:U(B)},{path:H(G,`${B}.inbound.ts`),content:w(B)},{path:H(G,`${B}.wiring.ts`),content:z(B)},{path:H(G,`${B}.outbound.ts`),content:A(B)},{path:H(G,"index.ts"),content:D(B)},{path:H("docs","providers",`${B}.md`),content:F(B)}]}function P(B,G=Y){let I=x(B);if(!I.ok)return I;let J=H(G,"src","providers",B);if($(J))return{ok:!1,reason:`${H("src","providers",B)} already exists`};for(let O of N(B)){let Q=H(G,O.path);q(X(Q),{recursive:!0}),C(Q,O.content,"utf8")}return{ok:!0}}function R(B,G=Y){let I=B[0];if(!I){console.error("usage: node tools/dev/new-provider.ts <name>"),process.exitCode=1;return}let J=P(I,G);if(!J.ok){console.error(`new-provider: refusing — ${J.reason}`),process.exitCode=1;return}console.log(`new-provider: scaffolded src/providers/${I}/ and docs/providers/${I}.md`)}if(W.main==W.module)R(process.argv.slice(2));export{x as validateProviderName,N as scaffoldFiles,P as scaffold,R as main};
|