gpu-container 0.1.3__tar.gz → 0.1.4__tar.gz

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 (98) hide show
  1. gpu_container-0.1.4/.claude/hooks/pre-tool-use.mjs +30 -0
  2. gpu_container-0.1.4/.claude/role-os/tool-contracts.json +639 -0
  3. gpu_container-0.1.4/.claude/settings.json +15 -0
  4. {gpu_container-0.1.3 → gpu_container-0.1.4}/.github/workflows/release.yml +12 -0
  5. {gpu_container-0.1.3 → gpu_container-0.1.4}/CHANGELOG.md +8 -0
  6. {gpu_container-0.1.3 → gpu_container-0.1.4}/PKG-INFO +1 -1
  7. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/__init__.py +1 -1
  8. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/bin/gpu-container.js +4 -4
  9. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/package.json +3 -2
  10. {gpu_container-0.1.3 → gpu_container-0.1.4}/pyproject.toml +1 -1
  11. {gpu_container-0.1.3 → gpu_container-0.1.4}/.dockerignore +0 -0
  12. {gpu_container-0.1.3 → gpu_container-0.1.4}/.github/workflows/ci.yml +0 -0
  13. {gpu_container-0.1.3 → gpu_container-0.1.4}/.github/workflows/pages.yml +0 -0
  14. {gpu_container-0.1.3 → gpu_container-0.1.4}/.gitignore +0 -0
  15. {gpu_container-0.1.3 → gpu_container-0.1.4}/Dockerfile +0 -0
  16. {gpu_container-0.1.3 → gpu_container-0.1.4}/LICENSE +0 -0
  17. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.es.md +0 -0
  18. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.fr.md +0 -0
  19. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.hi.md +0 -0
  20. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.it.md +0 -0
  21. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.ja.md +0 -0
  22. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.md +0 -0
  23. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.pt-BR.md +0 -0
  24. {gpu_container-0.1.3 → gpu_container-0.1.4}/README.zh.md +0 -0
  25. {gpu_container-0.1.3 → gpu_container-0.1.4}/RELEASE_ASSESSMENT.md +0 -0
  26. {gpu_container-0.1.3 → gpu_container-0.1.4}/SCORECARD.md +0 -0
  27. {gpu_container-0.1.3 → gpu_container-0.1.4}/SECURITY.md +0 -0
  28. {gpu_container-0.1.3 → gpu_container-0.1.4}/SHIP_GATE.md +0 -0
  29. {gpu_container-0.1.3 → gpu_container-0.1.4}/assets/logo.png +0 -0
  30. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/architecture.md +0 -0
  31. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/cli.md +0 -0
  32. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/constraints.md +0 -0
  33. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/decisions/0001-per-expert-cache-build-vs-upstream.md +0 -0
  34. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/derisk-concentration.md +0 -0
  35. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/feasibility.md +0 -0
  36. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/features.md +0 -0
  37. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/moe-lane-architecture.md +0 -0
  38. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/prior-art.md +0 -0
  39. {gpu_container-0.1.3 → gpu_container-0.1.4}/docs/quickstart.md +0 -0
  40. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/__main__.py +0 -0
  41. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/errors.py +0 -0
  42. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/__init__.py +0 -0
  43. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/activation.py +0 -0
  44. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/calibration.py +0 -0
  45. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/calibration_seed.json +0 -0
  46. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/cli.py +0 -0
  47. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/concentration_cli.py +0 -0
  48. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/placement.py +0 -0
  49. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/receipt.py +0 -0
  50. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/planner/receipt_cli.py +0 -0
  51. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/__init__.py +0 -0
  52. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/baseline.py +0 -0
  53. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/cli.py +0 -0
  54. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/cuda_bench.py +0 -0
  55. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/hardware.py +0 -0
  56. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/model.py +0 -0
  57. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/nvme_bench.py +0 -0
  58. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/profiler/schema.py +0 -0
  59. {gpu_container-0.1.3 → gpu_container-0.1.4}/gpu_container/watchdog.py +0 -0
  60. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/LICENSE +0 -0
  61. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.es.md +0 -0
  62. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.fr.md +0 -0
  63. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.hi.md +0 -0
  64. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.it.md +0 -0
  65. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.ja.md +0 -0
  66. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.md +0 -0
  67. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.pt-BR.md +0 -0
  68. {gpu_container-0.1.3 → gpu_container-0.1.4}/npm/README.zh.md +0 -0
  69. {gpu_container-0.1.3 → gpu_container-0.1.4}/scripts/gen_calibration_seed.py +0 -0
  70. {gpu_container-0.1.3 → gpu_container-0.1.4}/scripts/ingest_sweep.py +0 -0
  71. {gpu_container-0.1.3 → gpu_container-0.1.4}/scripts/verify.py +0 -0
  72. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/astro.config.mjs +0 -0
  73. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/package-lock.json +0 -0
  74. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/package.json +0 -0
  75. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/cli.md +0 -0
  76. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/derisk.md +0 -0
  77. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/getting-started.md +0 -0
  78. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/index.md +0 -0
  79. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/moe-lane.md +0 -0
  80. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/reference.md +0 -0
  81. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content/docs/handbook/safety.md +0 -0
  82. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/content.config.ts +0 -0
  83. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/pages/index.astro +0 -0
  84. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/site-config.ts +0 -0
  85. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/styles/global.css +0 -0
  86. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/src/styles/starlight-custom.css +0 -0
  87. {gpu_container-0.1.3 → gpu_container-0.1.4}/site/tsconfig.json +0 -0
  88. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_activation.py +0 -0
  89. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_calibration.py +0 -0
  90. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_concentration_cli.py +0 -0
  91. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_dispatch.py +0 -0
  92. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_errors.py +0 -0
  93. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_measure.py +0 -0
  94. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_planner.py +0 -0
  95. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_profiler.py +0 -0
  96. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_receipt_trace.py +0 -0
  97. {gpu_container-0.1.3 → gpu_container-0.1.4}/tests/test_watchdog.py +0 -0
  98. {gpu_container-0.1.3 → gpu_container-0.1.4}/watchdog.example.json +0 -0
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Wedge #1 PreToolUse hook — Tool-Call Conformance ADVISORY (deterministic floor; advisory + fail-open).
4
+ * gpu-container is a Python repo with no role-os dependency, so the floor is imported from the sibling
5
+ * role-os checkout by ABSOLUTE path (rig-specific: E:/AI/role-os). This reads
6
+ * .claude/role-os/tool-contracts.json from the session cwd, runs the schema + computable contract floor
7
+ * against the proposed call, and — only when the floor PROVES a violation — injects an advisory into context
8
+ * via the Claude Code hook protocol ({hookSpecificOutput:{hookEventName:"PreToolUse", additionalContext}}).
9
+ * It NEVER blocks (always exit 0) and NEVER throws — any error (incl. a missing role-os checkout) is a
10
+ * silent no-op, because a hook must not break a tool call.
11
+ */
12
+ import { readFileSync } from "node:fs";
13
+ import { pathToFileURL } from "node:url";
14
+
15
+ const ROLE_OS_HOOKS = "E:/AI/role-os/src/hooks.mjs"; // rig-specific sibling checkout
16
+
17
+ let input = {};
18
+ try { input = JSON.parse(readFileSync(0, "utf-8").toString() || "{}"); } catch { /* no stdin */ }
19
+
20
+ try {
21
+ const { conformanceAdvisory } = await import(pathToFileURL(ROLE_OS_HOOKS).href);
22
+ const note = conformanceAdvisory(input.cwd || process.cwd(), input.tool_name || "", input.tool_input);
23
+ if (note) {
24
+ console.log(JSON.stringify({
25
+ hookSpecificOutput: { hookEventName: "PreToolUse", additionalContext: note },
26
+ }));
27
+ }
28
+ } catch { /* role-os checkout not present, or internal error -> no-op (never block a tool call) */ }
29
+
30
+ process.exit(0);
@@ -0,0 +1,639 @@
1
+ {
2
+ "Read": {
3
+ "contract": "Read a file from the local filesystem. file_path must be an absolute path. 'limit' is the number of lines to read and must be a positive integer (> 0). 'offset' is the 0-based line to start reading from and must be non-negative (>= 0).",
4
+ "params": [
5
+ {
6
+ "name": "file_path",
7
+ "type": "string",
8
+ "required": true
9
+ },
10
+ {
11
+ "name": "limit",
12
+ "type": "number",
13
+ "required": false
14
+ },
15
+ {
16
+ "name": "offset",
17
+ "type": "number",
18
+ "required": false
19
+ },
20
+ {
21
+ "name": "pages",
22
+ "type": "string",
23
+ "required": false
24
+ }
25
+ ],
26
+ "constraints": [
27
+ {
28
+ "kind": "cmp",
29
+ "op": "gt",
30
+ "left": "limit",
31
+ "right": 0
32
+ },
33
+ {
34
+ "kind": "cmp",
35
+ "op": "ge",
36
+ "left": "offset",
37
+ "right": 0
38
+ }
39
+ ]
40
+ },
41
+ "Edit": {
42
+ "contract": "Exact string replacement in a file. file_path, old_string, and new_string are all required strings. old_string must be DIFFERENT from new_string (replacing a string with itself is a no-op and is rejected). replace_all is an optional boolean.",
43
+ "params": [
44
+ {
45
+ "name": "file_path",
46
+ "type": "string",
47
+ "required": true
48
+ },
49
+ {
50
+ "name": "old_string",
51
+ "type": "string",
52
+ "required": true
53
+ },
54
+ {
55
+ "name": "new_string",
56
+ "type": "string",
57
+ "required": true
58
+ },
59
+ {
60
+ "name": "replace_all",
61
+ "type": "boolean",
62
+ "required": false
63
+ }
64
+ ],
65
+ "constraints": [
66
+ {
67
+ "kind": "cmp",
68
+ "op": "ne",
69
+ "left": "old_string",
70
+ "right": {
71
+ "field": "new_string"
72
+ }
73
+ }
74
+ ]
75
+ },
76
+ "Write": {
77
+ "contract": "Write (overwrite) a file on the local filesystem. Both file_path (an absolute path) and content are required strings. No computable relational contract beyond the schema floor.",
78
+ "params": [
79
+ {
80
+ "name": "file_path",
81
+ "type": "string",
82
+ "required": true
83
+ },
84
+ {
85
+ "name": "content",
86
+ "type": "string",
87
+ "required": true
88
+ }
89
+ ],
90
+ "constraints": []
91
+ },
92
+ "Bash": {
93
+ "contract": "Execute a bash command. 'command' is required. 'timeout' is in milliseconds and must not exceed 600000 (10 minutes); it must also be non-negative. run_in_background and dangerouslyDisableSandbox are optional booleans.",
94
+ "params": [
95
+ {
96
+ "name": "command",
97
+ "type": "string",
98
+ "required": true
99
+ },
100
+ {
101
+ "name": "description",
102
+ "type": "string",
103
+ "required": false
104
+ },
105
+ {
106
+ "name": "timeout",
107
+ "type": "number",
108
+ "required": false,
109
+ "max": 600000
110
+ },
111
+ {
112
+ "name": "run_in_background",
113
+ "type": "boolean",
114
+ "required": false
115
+ },
116
+ {
117
+ "name": "dangerouslyDisableSandbox",
118
+ "type": "boolean",
119
+ "required": false
120
+ }
121
+ ],
122
+ "constraints": [
123
+ {
124
+ "kind": "cmp",
125
+ "op": "ge",
126
+ "left": "timeout",
127
+ "right": 0
128
+ }
129
+ ]
130
+ },
131
+ "PowerShell": {
132
+ "contract": "Execute a PowerShell command. 'command' is required. 'timeout' is in milliseconds and must not exceed 600000 (10 minutes); it must also be non-negative. run_in_background and dangerouslyDisableSandbox are optional booleans.",
133
+ "params": [
134
+ {
135
+ "name": "command",
136
+ "type": "string",
137
+ "required": true
138
+ },
139
+ {
140
+ "name": "description",
141
+ "type": "string",
142
+ "required": false
143
+ },
144
+ {
145
+ "name": "timeout",
146
+ "type": "number",
147
+ "required": false,
148
+ "max": 600000
149
+ },
150
+ {
151
+ "name": "run_in_background",
152
+ "type": "boolean",
153
+ "required": false
154
+ },
155
+ {
156
+ "name": "dangerouslyDisableSandbox",
157
+ "type": "boolean",
158
+ "required": false
159
+ }
160
+ ],
161
+ "constraints": [
162
+ {
163
+ "kind": "cmp",
164
+ "op": "ge",
165
+ "left": "timeout",
166
+ "right": 0
167
+ }
168
+ ]
169
+ },
170
+ "Grep": {
171
+ "contract": "ripgrep content search. 'pattern' is required. 'output_mode' must be one of content|files_with_matches|count. The numeric context fields -A, -B, -C, and context are line counts and must be non-negative (>= 0). head_limit and offset are also non-negative integers (>= 0).",
172
+ "params": [
173
+ {
174
+ "name": "pattern",
175
+ "type": "string",
176
+ "required": true
177
+ },
178
+ {
179
+ "name": "path",
180
+ "type": "string",
181
+ "required": false
182
+ },
183
+ {
184
+ "name": "glob",
185
+ "type": "string",
186
+ "required": false
187
+ },
188
+ {
189
+ "name": "type",
190
+ "type": "string",
191
+ "required": false
192
+ },
193
+ {
194
+ "name": "output_mode",
195
+ "type": "string",
196
+ "required": false,
197
+ "enum": [
198
+ "content",
199
+ "files_with_matches",
200
+ "count"
201
+ ]
202
+ },
203
+ {
204
+ "name": "-A",
205
+ "type": "number",
206
+ "required": false
207
+ },
208
+ {
209
+ "name": "-B",
210
+ "type": "number",
211
+ "required": false
212
+ },
213
+ {
214
+ "name": "-C",
215
+ "type": "number",
216
+ "required": false
217
+ },
218
+ {
219
+ "name": "-n",
220
+ "type": "boolean",
221
+ "required": false
222
+ },
223
+ {
224
+ "name": "-i",
225
+ "type": "boolean",
226
+ "required": false
227
+ },
228
+ {
229
+ "name": "-o",
230
+ "type": "boolean",
231
+ "required": false
232
+ },
233
+ {
234
+ "name": "multiline",
235
+ "type": "boolean",
236
+ "required": false
237
+ },
238
+ {
239
+ "name": "head_limit",
240
+ "type": "number",
241
+ "required": false
242
+ },
243
+ {
244
+ "name": "offset",
245
+ "type": "number",
246
+ "required": false
247
+ },
248
+ {
249
+ "name": "context",
250
+ "type": "number",
251
+ "required": false
252
+ }
253
+ ],
254
+ "constraints": [
255
+ {
256
+ "kind": "cmp",
257
+ "op": "ge",
258
+ "left": "-A",
259
+ "right": 0
260
+ },
261
+ {
262
+ "kind": "cmp",
263
+ "op": "ge",
264
+ "left": "-B",
265
+ "right": 0
266
+ },
267
+ {
268
+ "kind": "cmp",
269
+ "op": "ge",
270
+ "left": "-C",
271
+ "right": 0
272
+ },
273
+ {
274
+ "kind": "cmp",
275
+ "op": "ge",
276
+ "left": "context",
277
+ "right": 0
278
+ },
279
+ {
280
+ "kind": "cmp",
281
+ "op": "ge",
282
+ "left": "head_limit",
283
+ "right": 0
284
+ },
285
+ {
286
+ "kind": "cmp",
287
+ "op": "ge",
288
+ "left": "offset",
289
+ "right": 0
290
+ }
291
+ ]
292
+ },
293
+ "Glob": {
294
+ "contract": "Fast file pattern matching. 'pattern' is required (e.g. **/*.ts). 'path' is an optional directory to search in. No computable relational contract beyond the schema floor.",
295
+ "params": [
296
+ {
297
+ "name": "pattern",
298
+ "type": "string",
299
+ "required": true
300
+ },
301
+ {
302
+ "name": "path",
303
+ "type": "string",
304
+ "required": false
305
+ }
306
+ ],
307
+ "constraints": []
308
+ },
309
+ "AskUserQuestion": {
310
+ "contract": "Ask the user between 1 and 4 questions. 'questions' is a required array whose length must be >= 1 and <= 4.",
311
+ "params": [
312
+ {
313
+ "name": "questions",
314
+ "type": "array",
315
+ "required": true
316
+ }
317
+ ],
318
+ "constraints": [
319
+ {
320
+ "kind": "cmp",
321
+ "op": "ge",
322
+ "left": {
323
+ "len": "questions"
324
+ },
325
+ "right": 1
326
+ },
327
+ {
328
+ "kind": "cmp",
329
+ "op": "le",
330
+ "left": {
331
+ "len": "questions"
332
+ },
333
+ "right": 4
334
+ }
335
+ ]
336
+ },
337
+ "ToolSearch": {
338
+ "contract": "Fetch deferred tool schemas. 'query' is required. 'max_results' is an optional result-count hint (the real schema enforces no min/integer bound). No computable relational contract beyond the schema floor.",
339
+ "params": [
340
+ {
341
+ "name": "query",
342
+ "type": "string",
343
+ "required": true
344
+ },
345
+ {
346
+ "name": "max_results",
347
+ "type": "number",
348
+ "required": false
349
+ }
350
+ ],
351
+ "constraints": []
352
+ },
353
+ "Skill": {
354
+ "contract": "Invoke a skill by exact name. 'skill' is required. 'args' is optional. No computable relational contract beyond the schema floor.",
355
+ "params": [
356
+ {
357
+ "name": "skill",
358
+ "type": "string",
359
+ "required": true
360
+ },
361
+ {
362
+ "name": "args",
363
+ "type": "string",
364
+ "required": false
365
+ }
366
+ ],
367
+ "constraints": []
368
+ },
369
+ "Agent": {
370
+ "contract": "Launch a subagent. description, prompt, and subagent_type are required. 'model' (when provided) must be one of sonnet|opus|haiku. 'isolation' (when provided) must be 'worktree'. IMPORTANT: subagent_type is an OPEN set — custom agent types are allowed — so do NOT add a membership constraint on subagent_type; that is genuinely-semantic, not computable.",
371
+ "params": [
372
+ {
373
+ "name": "description",
374
+ "type": "string",
375
+ "required": true
376
+ },
377
+ {
378
+ "name": "prompt",
379
+ "type": "string",
380
+ "required": true
381
+ },
382
+ {
383
+ "name": "subagent_type",
384
+ "type": "string",
385
+ "required": true
386
+ },
387
+ {
388
+ "name": "model",
389
+ "type": "string",
390
+ "required": false,
391
+ "enum": [
392
+ "sonnet",
393
+ "opus",
394
+ "haiku"
395
+ ]
396
+ },
397
+ {
398
+ "name": "isolation",
399
+ "type": "string",
400
+ "required": false,
401
+ "enum": [
402
+ "worktree"
403
+ ]
404
+ },
405
+ {
406
+ "name": "run_in_background",
407
+ "type": "boolean",
408
+ "required": false
409
+ }
410
+ ],
411
+ "constraints": []
412
+ },
413
+ "mcp__ollama-intern__ollama_chat": {
414
+ "contract": "Chat with the local model. 'messages' is a required, NON-EMPTY array of {role,content} (length >= 1). model and system are optional strings.",
415
+ "params": [
416
+ {
417
+ "name": "messages",
418
+ "type": "array",
419
+ "required": true
420
+ },
421
+ {
422
+ "name": "model",
423
+ "type": "string",
424
+ "required": false
425
+ },
426
+ {
427
+ "name": "system",
428
+ "type": "string",
429
+ "required": false
430
+ }
431
+ ],
432
+ "constraints": [
433
+ {
434
+ "kind": "cmp",
435
+ "op": "ge",
436
+ "left": {
437
+ "len": "messages"
438
+ },
439
+ "right": 1
440
+ }
441
+ ]
442
+ },
443
+ "mcp__ollama-intern__ollama_classify": {
444
+ "contract": "Single-label classification. 'labels' is required. Provide EXACTLY ONE of 'text', 'source_path', or 'items' (the input source — exactly one must be present). 'threshold' is a confidence floor in [0,1]. 'per_file_max_chars' is in [1000,200000]. allow_none, frame, model are optional.",
445
+ "params": [
446
+ {
447
+ "name": "labels",
448
+ "required": true
449
+ },
450
+ {
451
+ "name": "text",
452
+ "type": "string",
453
+ "required": false
454
+ },
455
+ {
456
+ "name": "source_path",
457
+ "type": "string",
458
+ "required": false
459
+ },
460
+ {
461
+ "name": "items",
462
+ "type": "array",
463
+ "required": false
464
+ },
465
+ {
466
+ "name": "threshold",
467
+ "type": "number",
468
+ "required": false
469
+ },
470
+ {
471
+ "name": "allow_none",
472
+ "type": "boolean",
473
+ "required": false
474
+ },
475
+ {
476
+ "name": "frame",
477
+ "type": "string",
478
+ "required": false
479
+ },
480
+ {
481
+ "name": "model",
482
+ "type": "string",
483
+ "required": false
484
+ },
485
+ {
486
+ "name": "per_file_max_chars",
487
+ "type": "integer",
488
+ "required": false
489
+ }
490
+ ],
491
+ "constraints": [
492
+ {
493
+ "kind": "present",
494
+ "fields": [
495
+ "text",
496
+ "source_path",
497
+ "items"
498
+ ],
499
+ "count": 1
500
+ },
501
+ {
502
+ "kind": "cmp",
503
+ "op": "ge",
504
+ "left": "threshold",
505
+ "right": 0
506
+ },
507
+ {
508
+ "kind": "cmp",
509
+ "op": "le",
510
+ "left": "threshold",
511
+ "right": 1
512
+ },
513
+ {
514
+ "kind": "cmp",
515
+ "op": "ge",
516
+ "left": "per_file_max_chars",
517
+ "right": 1000
518
+ },
519
+ {
520
+ "kind": "cmp",
521
+ "op": "le",
522
+ "left": "per_file_max_chars",
523
+ "right": 200000
524
+ }
525
+ ]
526
+ },
527
+ "mcp__ollama-intern__ollama_corpus_search": {
528
+ "contract": "Concept search over a named corpus. 'corpus' and 'query' are required strings. 'mode' (when provided) must be one of semantic|lexical|hybrid|fact|title_path. 'top_k' is an integer in [1,100]. 'preview_chars' is an integer in [0,500].",
529
+ "params": [
530
+ {
531
+ "name": "corpus",
532
+ "type": "string",
533
+ "required": true
534
+ },
535
+ {
536
+ "name": "query",
537
+ "type": "string",
538
+ "required": true
539
+ },
540
+ {
541
+ "name": "mode",
542
+ "type": "string",
543
+ "required": false,
544
+ "enum": [
545
+ "semantic",
546
+ "lexical",
547
+ "hybrid",
548
+ "fact",
549
+ "title_path"
550
+ ]
551
+ },
552
+ {
553
+ "name": "top_k",
554
+ "type": "integer",
555
+ "required": false
556
+ },
557
+ {
558
+ "name": "preview_chars",
559
+ "type": "integer",
560
+ "required": false
561
+ },
562
+ {
563
+ "name": "explain",
564
+ "type": "boolean",
565
+ "required": false
566
+ },
567
+ {
568
+ "name": "filter",
569
+ "type": "object",
570
+ "required": false
571
+ }
572
+ ],
573
+ "constraints": [
574
+ {
575
+ "kind": "cmp",
576
+ "op": "ge",
577
+ "left": "top_k",
578
+ "right": 1
579
+ },
580
+ {
581
+ "kind": "cmp",
582
+ "op": "le",
583
+ "left": "top_k",
584
+ "right": 100
585
+ },
586
+ {
587
+ "kind": "cmp",
588
+ "op": "ge",
589
+ "left": "preview_chars",
590
+ "right": 0
591
+ },
592
+ {
593
+ "kind": "cmp",
594
+ "op": "le",
595
+ "left": "preview_chars",
596
+ "right": 500
597
+ }
598
+ ]
599
+ },
600
+ "mcp__ollama-intern__ollama_summarize_fast": {
601
+ "contract": "Summarize short text. 'text' is required. 'max_words' is the target length and is an integer in [10,400]. frame and model are optional.",
602
+ "params": [
603
+ {
604
+ "name": "text",
605
+ "type": "string",
606
+ "required": true
607
+ },
608
+ {
609
+ "name": "max_words",
610
+ "type": "integer",
611
+ "required": false
612
+ },
613
+ {
614
+ "name": "frame",
615
+ "type": "string",
616
+ "required": false
617
+ },
618
+ {
619
+ "name": "model",
620
+ "type": "string",
621
+ "required": false
622
+ }
623
+ ],
624
+ "constraints": [
625
+ {
626
+ "kind": "cmp",
627
+ "op": "ge",
628
+ "left": "max_words",
629
+ "right": 10
630
+ },
631
+ {
632
+ "kind": "cmp",
633
+ "op": "le",
634
+ "left": "max_words",
635
+ "right": 400
636
+ }
637
+ ]
638
+ }
639
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node .claude/hooks/pre-tool-use.mjs"
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -152,6 +152,18 @@ jobs:
152
152
  echo "::error::release tag ${TAG} does not match npm/package.json version ${PKG}"
153
153
  exit 1
154
154
  fi
155
+ # The launcher bin pins the version + tag it downloads binaries for. Gate it too:
156
+ # without this, a version bump that forgets bin/gpu-container.js would publish a
157
+ # launcher that fetches the PREVIOUS release's binaries/checksums while every other
158
+ # gate stays green (npm/package.json already matches the tag). Caught in v0.1.4 preflight.
159
+ if ! grep -q "version: \"${TAG}\"" npm/bin/gpu-container.js; then
160
+ echo "::error::npm/bin/gpu-container.js version literal does not match ${TAG}"
161
+ exit 1
162
+ fi
163
+ if ! grep -q "tag: \"v${TAG}\"" npm/bin/gpu-container.js; then
164
+ echo "::error::npm/bin/gpu-container.js tag literal does not match v${TAG}"
165
+ exit 1
166
+ fi
155
167
 
156
168
  - uses: actions/setup-node@v4
157
169
  with:
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [0.1.4] - 2026-06-08
9
+
10
+ ### Fixed
11
+ - **npm provenance source link** now resolves to the launcher's `npm/` subdirectory — added `repository.directory: "npm"` to the launcher `package.json`. Cosmetic only: the 0.1.3 attestation was already valid (`npm audit signatures` passes); this points npm's provenance "source" link at the real package folder instead of the repo root.
12
+
13
+ ### Changed
14
+ - **Release pipeline** now verifies the launcher's pinned binary `version` + `tag` (`npm/bin/gpu-container.js`) match the release tag before publishing — closing a gap where bumping the package version alone could publish a launcher that downloads the *previous* release's binaries (CI stayed green because it only gated `pyproject.toml` + `npm/package.json`).
15
+
8
16
  ## [0.1.3] - 2026-06-04
9
17
 
10
18
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gpu-container
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Model-aware inference memory-placement planner for single-GPU rigs — profile, plan, prove.
5
5
  Author-email: mcp-tool-shop <64996768+mcp-tool-shop@users.noreply.github.com>
6
6
  License-Expression: MIT
@@ -6,4 +6,4 @@ grounds the measurement methodology lives in the docker-knowledge KB
6
6
  (readouts/docker-knowledge), seeded by the feasibility study-swarm.
7
7
  """
8
8
 
9
- __version__ = "0.1.3"
9
+ __version__ = "0.1.4"
@@ -5,14 +5,14 @@
5
5
  // the release-asset names from convention, downloads the platform binary from the gpu-container
6
6
  // GitHub Release, verifies its SHA256 against checksums-<version>.txt, caches it, and runs it with
7
7
  // full arg passthrough.
8
- // binary: gpu-container-0.1.3-linux-x64
9
- // checksums: checksums-0.1.3.txt
8
+ // binary: gpu-container-0.1.4-linux-x64
9
+ // checksums: checksums-0.1.4.txt
10
10
  process.env.MCPTOOLSHOP_LAUNCH_CONFIG = JSON.stringify({
11
11
  toolName: "gpu-container",
12
12
  owner: "mcp-tool-shop-org",
13
13
  repo: "gpu-container",
14
- version: "0.1.3",
15
- tag: "v0.1.3",
14
+ version: "0.1.4",
15
+ tag: "v0.1.4",
16
16
  });
17
17
 
18
18
  require("@mcptoolshop/npm-launcher/bin/mcptoolshop-launch.js");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpu-container",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "gpu-container — model-aware inference memory-placement planner for single-GPU rigs. Zero-prerequisite npx install via a verified binary launcher.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
@@ -32,7 +32,8 @@
32
32
  "author": "mcp-tool-shop",
33
33
  "repository": {
34
34
  "type": "git",
35
- "url": "git+https://github.com/mcp-tool-shop-org/gpu-container.git"
35
+ "url": "git+https://github.com/mcp-tool-shop-org/gpu-container.git",
36
+ "directory": "npm"
36
37
  },
37
38
  "homepage": "https://github.com/mcp-tool-shop-org/gpu-container"
38
39
  }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "gpu-container"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "Model-aware inference memory-placement planner for single-GPU rigs — profile, plan, prove."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes