provared 0.2.0 → 0.4.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/CHANGELOG.md +324 -0
- package/README.md +134 -653
- package/bin/provared-check.mjs +39 -2
- package/docs/guide.md +745 -0
- package/docs/threat-model.md +16 -7
- package/package.json +25 -2
- package/page/index.html +1 -1
- package/page/style.css +3 -0
- package/spec/provared-format.md +30 -7
- package/src/dev.d.ts +54 -0
- package/src/dev.js +123 -0
- package/src/guard.js +73 -5
- package/src/recorder.js +12 -2
- package/src/signatures.js +7 -0
- package/src/types.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,329 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 (14 October 2026)
|
|
4
|
+
|
|
5
|
+
- **The command-line checker counts the keys it was given.** With two
|
|
6
|
+
passkeys named, its summary said "yes: the passkey you trust"; it now
|
|
7
|
+
says "the passkeys you trust", and "the recorders you expect" where
|
|
8
|
+
more than one recorder is named; the same key named twice counts once.
|
|
9
|
+
Only the words change; tests hold them. The guide gives the fingerprint
|
|
10
|
+
of the checking page built as one file for this version, which changed
|
|
11
|
+
because the checker it holds, and the page itself, changed.
|
|
12
|
+
- **The README's count of review rounds is brought up to date: 40.** The
|
|
13
|
+
25 recorded by version 0.3.0, and 15 since: three of the library's
|
|
14
|
+
changes of 11 to 13 October (the seal rule, then a narrow review of four
|
|
15
|
+
commits and a check of its fixes), three of the signing page, six of the
|
|
16
|
+
recorder beside Claude Code, two of the record page's book in a release,
|
|
17
|
+
and one of the asynchronous reads below. Each reviewer is a fresh
|
|
18
|
+
session given the code, the documents and a brief of what to look at;
|
|
19
|
+
the README now says so, and that a fault may be stated as a limit rather
|
|
20
|
+
than fixed.
|
|
21
|
+
- **The two framework packages require version 0.4.0**, so that an
|
|
22
|
+
agent behind either goes on after its book is sealed (below).
|
|
23
|
+
`provared-langchain` becomes 0.1.1, which also carries the keywords,
|
|
24
|
+
the homepage and the mark added on 10 and 11 October.
|
|
25
|
+
`pydantic-ai-provared` 0.1.0 is its first version; its README already
|
|
26
|
+
gave the command to install it. Both are published separately, on the
|
|
27
|
+
Python Package Index.
|
|
28
|
+
- **The LangChain and Pydantic AI packages read the stub writer safely
|
|
29
|
+
from asynchronous code**: `await middleware.snapshot()` and
|
|
30
|
+
`await capability.snapshot()` give the book and the cancellations the
|
|
31
|
+
writer holds, waiting in a thread of their own. The READMEs said to
|
|
32
|
+
read it with `asyncio.to_thread(writer.snapshot)`; but in the event
|
|
33
|
+
loop's shared threads such a read waits for the action in progress,
|
|
34
|
+
and enough of them at once leave no shared thread for a tool that
|
|
35
|
+
needs one, so the tool and the reads wait for ever. Found while
|
|
36
|
+
building a package for another framework; checked by an independent
|
|
37
|
+
reviewer, and a test in each package fails without it.
|
|
38
|
+
- **A proposed action dated by text gets a plain refusal.** The check
|
|
39
|
+
before acting took a time given as text, or a number or a Date that
|
|
40
|
+
gives no time, to the catch-all "the checker met something it did not
|
|
41
|
+
expect" (`check-failed`). It now answers `bad-field`: "when: must be a
|
|
42
|
+
number of milliseconds, or a Date" (the stub writer's own words), or
|
|
43
|
+
"when: does not give a time" (new words, for a number such as Infinity,
|
|
44
|
+
a Date that is not a time, or a Date wrapped in a Proxy). In Python a
|
|
45
|
+
datetime counts as dated only where its time zone gives an offset, as
|
|
46
|
+
Python's own rule for an "aware" time says. Nothing that was allowed is
|
|
47
|
+
refused, and nothing that was refused is allowed. The stub writer
|
|
48
|
+
answers in the same words: its "before" and "act" took a Date wrapped
|
|
49
|
+
in a Proxy to a plain TypeError, and now answer "when: does not give a
|
|
50
|
+
time", as the check before acting does; its "record", which does not
|
|
51
|
+
ask first, took any time that gives none to a plain "Invalid time
|
|
52
|
+
value" error, and now refuses it with `bad-field` in those words. In
|
|
53
|
+
both languages; the shared test file for the check before acting gains
|
|
54
|
+
two cases, and in the stub writer's scenarios the one step that hands in
|
|
55
|
+
a time of Infinity changes its words, and the one step that records an
|
|
56
|
+
action at a time outside the range of times changes its answer. Tests
|
|
57
|
+
in both languages hold a Date in a Proxy and, in Python, a time zone
|
|
58
|
+
that gives no offset.
|
|
59
|
+
- **A record's signature of the wrong length is invalid on every
|
|
60
|
+
device.** An Ed25519 signature is 64 bytes, an ML-DSA-87 signature 4,627
|
|
61
|
+
and an SLH-DSA-SHA2-256s signature 29,792 (RFC 8032, FIPS 204, FIPS 205).
|
|
62
|
+
One of another length can never check, and a device that has the method
|
|
63
|
+
already said "invalid"; a device without it said "not checked on this
|
|
64
|
+
device". Now every device says "invalid", for every signature of a
|
|
65
|
+
record, the passkey's Ed25519 signature on a slip among them. So, on a
|
|
66
|
+
device without SLH-DSA, a seal whose third signature is cut short or
|
|
67
|
+
empty is a problem, not something the check before acting goes on
|
|
68
|
+
without. The signature inside a time-stamp from a service is not
|
|
69
|
+
covered: on a device without its method a time-stamp is not checked,
|
|
70
|
+
whatever its length, and is not counted. A third signature of the right
|
|
71
|
+
length that would not check is still not seen on a device without
|
|
72
|
+
SLH-DSA. The format description states the rule in section 3.9 and
|
|
73
|
+
what it means for a seal in section 20; the list of threats says that a
|
|
74
|
+
third signature of the right length is not seen there. In both
|
|
75
|
+
languages; the shared test files for a whole book and for the check
|
|
76
|
+
before acting gain a case each, and tests in both languages hold each
|
|
77
|
+
method's length, shorter and longer, with the method and without it.
|
|
78
|
+
- **The check before acting goes on without a seal's third signature, and
|
|
79
|
+
says so** (decision F-106; this changes choice 66 of the draft). Found on
|
|
80
|
+
11 October 2026: a device that cannot check SLH-DSA-SHA2-256s, which is
|
|
81
|
+
every Python stub writer (and so the LangChain and Pydantic AI packages)
|
|
82
|
+
and every browser, was refused every action as soon as its book held a
|
|
83
|
+
seal, because the check allowed nothing unless every signature in the
|
|
84
|
+
record so far had been checked on that device. Now, where the only
|
|
85
|
+
signatures not checked are the third ones of seals whose first two were
|
|
86
|
+
checked there, and nothing else was left unchecked, the check goes on and
|
|
87
|
+
its answer carries `notChecked: ['SLH-DSA-SHA2-256s']`. Any other
|
|
88
|
+
signature left unchecked still refuses everything, and the full checker's
|
|
89
|
+
answers are unchanged. In both languages: the shared test file for the
|
|
90
|
+
check before acting gains seven cases with a seal, besides the one with
|
|
91
|
+
a third signature cut short counted above (found missing by two
|
|
92
|
+
independent reviews, which showed that weaker rules passed every test:
|
|
93
|
+
the last case, a permission and a seal alone on a device without
|
|
94
|
+
ML-DSA-87, holds the rule that the seal's ML-DSA-87 signature must have
|
|
95
|
+
been checked), and the shared test file for the stub writer's scenarios
|
|
96
|
+
is remade. Tests in both languages hold the same rule.
|
|
97
|
+
- **The signing page names the agent's keys by the fingerprint of their
|
|
98
|
+
key set** before the passkey is asked, worked out by the library's own
|
|
99
|
+
`keySetFingerprint` (as a recorder's key set is named), and asks the
|
|
100
|
+
person to compare it with the one the agent's software printed when it
|
|
101
|
+
made its keys: a link, or a permission pasted from elsewhere, could
|
|
102
|
+
carry someone else's keys under a familiar name. Keys that are not a
|
|
103
|
+
key set are refused there, in the library's own words. A test holds the
|
|
104
|
+
page's words against the library's fingerprint.
|
|
105
|
+
- **The signing page fills itself from a link, and shows everything a
|
|
106
|
+
link could slip in before the passkey is asked.** A link to
|
|
107
|
+
prova.red/sign/ may hold a starting permission after "#"; that part
|
|
108
|
+
stays in the browser and is never sent to a server. A link that cannot
|
|
109
|
+
be read leaves the page's own starting point and says why; a second
|
|
110
|
+
link opened in the same tab fills the page again. Because a link can
|
|
111
|
+
name anything, the page now shows, besides the agent's key-set
|
|
112
|
+
fingerprint (above): each service's keys by the fingerprint of their key
|
|
113
|
+
set, as a checker names them (keys that are not a key set are refused,
|
|
114
|
+
in the library's own words); and the agent's software statement, marked
|
|
115
|
+
as the person's statement and not proof of what runs. Shown inside
|
|
116
|
+
another page, it offers nothing to sign or cancel, since another site
|
|
117
|
+
could frame it filled from a link of its choosing. It now has a content
|
|
118
|
+
security policy that lets it load only its own scripts and style sheet
|
|
119
|
+
and send nothing anywhere; the message of the commit that added the
|
|
120
|
+
link said its policy was unchanged, but the page had none. Tests hold
|
|
121
|
+
each point. Checked by an independent reviewer over three rounds.
|
|
122
|
+
- **The recorder beside Claude Code is a package of its own,
|
|
123
|
+
`provared-claude-code` 0.1.0** (published separately, on npm), in
|
|
124
|
+
`integrations/claude-code/`, in place of the recorder of 10 October.
|
|
125
|
+
`init` makes the keys, writes the hooks and prints a link to the signing
|
|
126
|
+
page filled in with a starting permission; `use` puts the signed
|
|
127
|
+
permission in place; `renew` takes a new permission while the recorder
|
|
128
|
+
runs, with no moment in which a call finds it gone. A permission from a
|
|
129
|
+
passkey the recorder has not trusted before is taken only with
|
|
130
|
+
`--new-passkey`, and the passkeys it trusts are kept in
|
|
131
|
+
`trusted-passkeys.json`. The hooks `init` writes match every tool,
|
|
132
|
+
record calls that failed, and refuse a call where the hook itself fails
|
|
133
|
+
(`"onFailure": "block"`). A command is named by reading its line three
|
|
134
|
+
ways (as a shell splits it, from every known program's name, and with
|
|
135
|
+
the first version's patterns), and the strictest name counts; a line
|
|
136
|
+
handed to a shell, to `eval`, `iex` or `Invoke-Expression`, and the
|
|
137
|
+
command `find -exec` runs are read the same way. A call allowed under
|
|
138
|
+
one permission and taken while a renewal switched to the next is
|
|
139
|
+
recorded under the one it was allowed under, and the stub of a call that
|
|
140
|
+
was taken is always written. `keys` and `init` print the fingerprint of
|
|
141
|
+
the agent's key set, which the signing page asks the person to compare;
|
|
142
|
+
`seal` shows the recorder's error. Checked by an independent reviewer in
|
|
143
|
+
six rounds; each fault found is a test (57 in all).
|
|
144
|
+
- **The record page's book and the checker's answer are kept in a release
|
|
145
|
+
of the repository, not in the repository itself**: they grow by
|
|
146
|
+
megabytes a day, and GitHub refuses a file over 100 MB.
|
|
147
|
+
`tools/make-record-page.mjs` writes their SHA-256 fingerprints beside
|
|
148
|
+
the page (`site/records/files.sha256`); the site's publishing run
|
|
149
|
+
fetches both from the release "record" and publishes nothing unless each
|
|
150
|
+
matches, and every file the page links is there. Readers see no change.
|
|
151
|
+
The tool now reads the growing book once, into the page's own folder,
|
|
152
|
+
leaving out a last line still being written, so that the page, the
|
|
153
|
+
checker's answer and the fingerprints describe one book (the page of
|
|
154
|
+
14 October said 3,771 receipts above a summary of 3,770 stubs). It
|
|
155
|
+
counts the passkeys that signed the book's permissions from the book,
|
|
156
|
+
and refuses a passkey named to it that signed none. Checked by an
|
|
157
|
+
independent reviewer in two rounds.
|
|
158
|
+
- **What browsers check, tried again on 13 October 2026.** Chrome 155,
|
|
159
|
+
Edge 155 and Brave 155 each offer Ed25519 and ML-DSA (all three
|
|
160
|
+
strengths) to a page and check real signatures made with them; none of
|
|
161
|
+
them offers SLH-DSA. The README, the guide, the list of threats, the
|
|
162
|
+
home page, the worked example and the tool that writes the record page
|
|
163
|
+
now say so; they said, from a try on 12 October, that Chrome 154 did
|
|
164
|
+
not check ML-DSA. No code changes.
|
|
165
|
+
- **The recorder beside Claude Code appends to the book, and no longer
|
|
166
|
+
loses a receipt while another program reads the file.** It wrote the
|
|
167
|
+
whole book to a temporary file and renamed it over the old one; on
|
|
168
|
+
Windows that is refused while anyone holds the file open (an uploader,
|
|
169
|
+
a virus scanner), and the hook then reported "the action was taken and
|
|
170
|
+
is not in the record". Found on 11 October 2026, when a program that
|
|
171
|
+
uploads the book was reading it every two seconds: 7 of one helper's 23
|
|
172
|
+
tool calls were taken and not recorded. A book only grows, so the
|
|
173
|
+
recorder now appends the new lines; where the file does not match the
|
|
174
|
+
book it is replaced, with retries for up to two seconds. A test holds
|
|
175
|
+
the file open while the recorder saves.
|
|
176
|
+
|
|
177
|
+
- 2026-10-11: **one mark everywhere**: a permission slip with a
|
|
178
|
+
signature, white on red (#8f000f), as `site/favicon.svg`, in the
|
|
179
|
+
social preview `site/preview.png` beside the word, as inline SVG in the
|
|
180
|
+
header of every page at prova.red, of the checking page and of the
|
|
181
|
+
signing page (no page makes a request for it), and at the top of the
|
|
182
|
+
README and of the three Python packages' READMEs, which the registries
|
|
183
|
+
show with the next published version. The four colours of the parts stay as they are inside the
|
|
184
|
+
pages. The style sheet gains one rule for the mark and a new version
|
|
185
|
+
number. No code changes.
|
|
186
|
+
- 2026-10-10: **a real record on prova.red**, `tools/make-record-page.mjs`:
|
|
187
|
+
writes `site/records/` from the book that the recorder beside Claude
|
|
188
|
+
Code keeps. It copies the book and its slip beside the page, runs the
|
|
189
|
+
command-line checker with the passkey and the recorder the reader is
|
|
190
|
+
told to trust, keeps the whole answer as a text file, and writes the
|
|
191
|
+
page from what the checker answered: the slip in the checker's own
|
|
192
|
+
words, the counts by day, by kind of action and by tool, the seals,
|
|
193
|
+
any entry outside the permission, the summary exactly as printed, and
|
|
194
|
+
what the check does not show. The page says that a refused call
|
|
195
|
+
leaves no entry and that every receipt is one-sided. It is run again
|
|
196
|
+
each day while the permission lasts; the home page links to it. A
|
|
197
|
+
test runs the tool on the sample record into a folder of its own.
|
|
198
|
+
- 2026-10-10: **the pages at prova.red, the README and the framework
|
|
199
|
+
packages, after the adoption review**: the line under each page's
|
|
200
|
+
title names its reader and then the slogan; "How it is built" on the
|
|
201
|
+
home page is two sentences; the developer page says "the person"
|
|
202
|
+
throughout, names the nearest other projects beside what the
|
|
203
|
+
author found nowhere else, and gives the author's own reason for
|
|
204
|
+
building it; the plain-words page names Article 12 and
|
|
205
|
+
Article 26 of the AI Act, no longer repeats its opening, and asks a
|
|
206
|
+
reader who breaks it to open an issue; every page ends with two
|
|
207
|
+
lines about the author; the README shows the LangChain example; the
|
|
208
|
+
two framework packages gain keywords and a homepage. No code changes.
|
|
209
|
+
- 2026-10-10: **a signing page**, `page/sign.html`, served at
|
|
210
|
+
prova.red/sign/: a person writes a permission as JSON (the agent's
|
|
211
|
+
name and two public keys, the actions, limits, conditions, stated
|
|
212
|
+
rules, with whom, from when until when, and why), sees it in words,
|
|
213
|
+
signs it with a passkey made for the website, and saves the signed
|
|
214
|
+
file; the page shows the passkey's thumbprint and the permission's
|
|
215
|
+
fingerprint. It can also sign a cancellation of a permission signed
|
|
216
|
+
with the same passkey. It uses the library's browser part and
|
|
217
|
+
`render.js`, loads nothing from anywhere else and sends nothing. The
|
|
218
|
+
workflow serves it beside the checking page.
|
|
219
|
+
- 2026-10-10: **the recorder beside Claude Code**, `integrations/claude-code/`:
|
|
220
|
+
a hook that Claude Code runs before and after each tool call, and a
|
|
221
|
+
small service on 127.0.0.1 that holds the stub writer open on one book
|
|
222
|
+
under a slip the person signed. Before a call, the check before acting
|
|
223
|
+
refuses a call outside the slip and Claude Code is told why; after it,
|
|
224
|
+
a stub is written naming the tool and the SHA-256 fingerprint of its
|
|
225
|
+
arguments; the service seals the book on request with the recorder's
|
|
226
|
+
three keys. Tool calls are named from the shared list by the hook,
|
|
227
|
+
not by the agent (a command that removes something is
|
|
228
|
+
`provared.data.delete`; one that publishes is `provared.code.release`);
|
|
229
|
+
tools that only talk to the person are not recorded. The agent's two
|
|
230
|
+
keys and the recorder's three are kept as JSON Web Keys in files the
|
|
231
|
+
person keeps. If the service is not running, a call is refused: no
|
|
232
|
+
record, no action. The folder names a product, as the framework
|
|
233
|
+
packages do; the library names none, and the npm package does not
|
|
234
|
+
hold it. Five tests run the hook as Claude Code runs it.
|
|
235
|
+
- **The tests clean up after themselves.** Nine test files made a
|
|
236
|
+
temporary folder for each run and left it behind; on 13 October 2026
|
|
237
|
+
the computer's temporary folder held about 2,800 of them. A small
|
|
238
|
+
helper, `test/helpers/temp.mjs`, now makes each folder and removes it
|
|
239
|
+
when that test file's tests end. Run with an empty temporary folder,
|
|
240
|
+
the library's tests leave nothing in it.
|
|
241
|
+
|
|
242
|
+
## 0.3.0 (10 October 2026)
|
|
243
|
+
|
|
244
|
+
- 2026-10-10: **a development stand-in for a passkey**, `provared/dev`
|
|
245
|
+
in JavaScript and `provared.dev` in Python, so that a first record can
|
|
246
|
+
be made without a browser: `developmentPasskey` (an ES256 key made in
|
|
247
|
+
memory that returns the three values a passkey returns, for the page
|
|
248
|
+
address `http://localhost`), `developmentSlip` (a slip it signed, with
|
|
249
|
+
new keys for the agent, a book holding the slip, and the stand-in's
|
|
250
|
+
thumbprint for a checker) and `developmentRecorder` (the stub writer
|
|
251
|
+
opened under such a slip, in one call). It is not a passkey and no
|
|
252
|
+
person confirms anything through it, so the issuer's name in every
|
|
253
|
+
slip it signs is made to end with " (development)", whatever name is
|
|
254
|
+
given, and the checker prints that name. The library itself (`provared`)
|
|
255
|
+
does not export it, and the checker does not use it. A first record in
|
|
256
|
+
one file: `examples/first-record.mjs` and
|
|
257
|
+
`python/examples/first_record.py`, each run by a test.
|
|
258
|
+
- 2026-10-10: `provared-check --sample` checks the sample record that
|
|
259
|
+
comes with the library, naming the stand-in passkey, the recorder and
|
|
260
|
+
the time-stamp service it was made with as trusted, and prints their
|
|
261
|
+
fingerprints; with `--json` the result alone. A file or another option
|
|
262
|
+
given with it is refused.
|
|
263
|
+
- 2026-10-10: the README is now a short landing page (install, a first
|
|
264
|
+
record, the four parts, what is only here, what a record does not
|
|
265
|
+
prove, where everything else is), and its former body is
|
|
266
|
+
`docs/guide.md`, unchanged but for the additions above. New:
|
|
267
|
+
`SECURITY.md` (how to report a fault in the security of a record) and
|
|
268
|
+
`CONTRIBUTING.md` (fault reports and other implementations welcome;
|
|
269
|
+
code only under a contributor agreement, whose text is not ready yet).
|
|
270
|
+
`package.json` and `python/pyproject.toml` gain a homepage, keywords
|
|
271
|
+
and a longer description. Version 0.3.0 in both, not yet published.
|
|
272
|
+
- 2026-10-10: the pages at prova.red: the home page's first screen now
|
|
273
|
+
shows the checker's summary and the install lines before the four
|
|
274
|
+
parts, with the plain word first and the short name after ("the
|
|
275
|
+
permission (a Slip)"); a first record of your own, in three commands,
|
|
276
|
+
with the file above and the LangChain package; "what the author found
|
|
277
|
+
nowhere else (October 2026)"; the status promises that every published
|
|
278
|
+
version stays on npm and the Python Package Index. The plain-words page
|
|
279
|
+
says that the 25 rounds of review were by AI reviewers and that no
|
|
280
|
+
person other than the author has reviewed the code yet, gives the date
|
|
281
|
+
from which the EU AI Act's logging duty applies (2 December 2027),
|
|
282
|
+
marks its charity example as invented, and uses "flight recorder" only
|
|
283
|
+
as a description. The developer page shows the code that made the
|
|
284
|
+
sample record and says the same about the reviews. All three pages
|
|
285
|
+
gain preview tags, an icon (`favicon.svg`, four coloured squares) and
|
|
286
|
+
a preview image (`preview.png`, drawn from a small page in a headless
|
|
287
|
+
browser), with the content security policy widened by `img-src 'self'`
|
|
288
|
+
only; `robots.txt` and `sitemap.xml` are added, and the workflow copies
|
|
289
|
+
everything in `site/`. Nothing in the library changes for this.
|
|
290
|
+
- 2026-10-10: the pages for prova.red, in `site/`: what a record
|
|
291
|
+
proves, the command-line checker's own answer for the sample record
|
|
292
|
+
(run on Node.js 24.19), how to try it, what is only here, how it is
|
|
293
|
+
built, where it is, a worked example for developers ("An agent goes
|
|
294
|
+
over its limit, and the record shows where") and "Provared in plain
|
|
295
|
+
words", three minutes for a reader who does not write code, with two
|
|
296
|
+
drawings that follow the sample record. No script, no font, no image,
|
|
297
|
+
no form: each page loads nothing from anywhere and keeps nothing about
|
|
298
|
+
a reader, and says so. The drawings carry their colours as plain SVG
|
|
299
|
+
attributes as well as through the style sheet, and the pages load the
|
|
300
|
+
style sheet under a versioned address, so a browser that kept an
|
|
301
|
+
earlier copy still draws them right. A workflow, `.github/workflows/pages.yml`,
|
|
302
|
+
publishes them with GitHub Pages from the main branch, with the
|
|
303
|
+
checking page at `/check/` (with the library and the sample it loads,
|
|
304
|
+
copied as they are) and built as one file at `/provared-check.html`.
|
|
305
|
+
The four actions it uses are GitHub's own, each pinned to the commit
|
|
306
|
+
of a released version. The site is not published until the domain
|
|
307
|
+
points at it. Nothing in the library, the checker or the package
|
|
308
|
+
changes.
|
|
309
|
+
- 2026-10-08: two small Python packages for agent frameworks, in
|
|
310
|
+
`python/integrations/`, each in a folder of its own, which names its
|
|
311
|
+
framework. Each puts every tool call of an agent behind the stub
|
|
312
|
+
writer with no change to the tools: the check before acting is asked,
|
|
313
|
+
the tool runs only if the slip allows it, and a stub is written; a call
|
|
314
|
+
that is not allowed is not run, and the model is told why. Each checks
|
|
315
|
+
the call as the tool receives it: one must come last among the parts
|
|
316
|
+
that wrap tool calls, and refuses to run otherwise; the other wraps
|
|
317
|
+
each of the agent's own sets of tools, wherever it stands. Each works with ordinary
|
|
318
|
+
and asynchronous agents: the stub writer runs in a thread of its own
|
|
319
|
+
for each call, and cancelling a run cancels a tool that is waiting.
|
|
320
|
+
Each is tested with its framework's own stand-in model, inside the
|
|
321
|
+
examples' guard. An independent review found eight faults in the first
|
|
322
|
+
draft, among them a reviewer's change that got past the slip and
|
|
323
|
+
asynchronous agents that could hang; each is fixed and tested. They use
|
|
324
|
+
only the public interface of the `provared` package, which itself still
|
|
325
|
+
names no product. Not yet published.
|
|
326
|
+
|
|
3
327
|
## 0.2.0 (8 October 2026)
|
|
4
328
|
|
|
5
329
|
- 2026-10-08: version 0.2.0, for the npm package and, for the first
|