@mjasnikovs/pi-task 0.40.12 → 0.40.14
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.
|
@@ -44,9 +44,18 @@ export function isExcerptInContent(excerpt, content) {
|
|
|
44
44
|
return false;
|
|
45
45
|
return normaliseWhitespace(content).includes(ne);
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
47
|
+
/**
|
|
48
|
+
* Tokens that are not source text and not evidence of invention either: the
|
|
49
|
+
* child's own elision marks, and the provenance tag the PROMPT gave it.
|
|
50
|
+
*
|
|
51
|
+
* `buildExtractionPrompt` wraps the identity as `<package>aeson@2.2.5.1</package>`,
|
|
52
|
+
* and re-run 5 caught a child quoting that back inside an otherwise verbatim
|
|
53
|
+
* excerpt — the only absent word in 24 unverified excerpts across three runs. A
|
|
54
|
+
* complete lowercase element is the whole rule; `Vec<String>` does not start with
|
|
55
|
+
* `<` and `<T>` has no closing tag, so neither is excused.
|
|
56
|
+
*/
|
|
49
57
|
const ELISION = /^(?:\.{3}|\u2026|\/\/\s*\.{3})$/;
|
|
58
|
+
const PROMPT_TAG = /^<([a-z_]+)>[^<]*<\/\1>$/;
|
|
50
59
|
/**
|
|
51
60
|
* Cover the excerpt with the longest runs the source actually contains, greedily.
|
|
52
61
|
*
|
|
@@ -67,7 +76,7 @@ function coverBySource(normalisedExcerpt, normalisedContent) {
|
|
|
67
76
|
run++;
|
|
68
77
|
}
|
|
69
78
|
if (run === 0) {
|
|
70
|
-
if (!ELISION.test(words[i]))
|
|
79
|
+
if (!ELISION.test(words[i]) && !PROMPT_TAG.test(words[i]))
|
|
71
80
|
absent.push(words[i]);
|
|
72
81
|
i++;
|
|
73
82
|
}
|
|
@@ -22,14 +22,24 @@ export interface RetrieveOptions {
|
|
|
22
22
|
contentBudget?: number;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* How many chunks a retrieval returns
|
|
26
|
-
* project source gets 50.
|
|
25
|
+
* How many chunks a retrieval returns. Both corpora get 50, and that is measured.
|
|
27
26
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* The package limit was 8 and nothing recorded why it differed from project
|
|
28
|
+
* source's 50. Measured both ways, over every recorded query, on the two things
|
|
29
|
+
* that can be measured:
|
|
30
|
+
*
|
|
31
|
+
* retrieval — does a chunk DEFINE the queried symbol? 91/101 -> 97/101,
|
|
32
|
+
* monotone to 50 and flat at 100, p = 0.0703
|
|
33
|
+
* answers — does the extraction child answer at all? 67/94 -> 79/94,
|
|
34
|
+
* only-8 3, only-50 15, McNemar exact p = 0.0075
|
|
35
|
+
*
|
|
36
|
+
* Abstention on the replay corpus falls 29% to 16%. The cost is +70% of retrieved
|
|
37
|
+
* text, and `RETRIEVE_CONTENT_BUDGET` still bounds it — at 8 only 6 of 74 calls
|
|
38
|
+
* reached that budget, so two thirds of it was never spent.
|
|
39
|
+
*
|
|
40
|
+
* Changing either is still a retrieval-policy change, not a tidy-up.
|
|
31
41
|
*/
|
|
32
|
-
export declare const PACKAGE_RETRIEVE_LIMIT =
|
|
42
|
+
export declare const PACKAGE_RETRIEVE_LIMIT = 50;
|
|
33
43
|
export declare const PROJECT_RETRIEVE_LIMIT = 50;
|
|
34
44
|
/** Character budget for the assembled chunk text. The same for both corpora. */
|
|
35
45
|
export declare const RETRIEVE_CONTENT_BUDGET = 24000;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* How many chunks a retrieval returns
|
|
3
|
-
* project source gets 50.
|
|
2
|
+
* How many chunks a retrieval returns. Both corpora get 50, and that is measured.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The package limit was 8 and nothing recorded why it differed from project
|
|
5
|
+
* source's 50. Measured both ways, over every recorded query, on the two things
|
|
6
|
+
* that can be measured:
|
|
7
|
+
*
|
|
8
|
+
* retrieval — does a chunk DEFINE the queried symbol? 91/101 -> 97/101,
|
|
9
|
+
* monotone to 50 and flat at 100, p = 0.0703
|
|
10
|
+
* answers — does the extraction child answer at all? 67/94 -> 79/94,
|
|
11
|
+
* only-8 3, only-50 15, McNemar exact p = 0.0075
|
|
12
|
+
*
|
|
13
|
+
* Abstention on the replay corpus falls 29% to 16%. The cost is +70% of retrieved
|
|
14
|
+
* text, and `RETRIEVE_CONTENT_BUDGET` still bounds it — at 8 only 6 of 74 calls
|
|
15
|
+
* reached that budget, so two thirds of it was never spent.
|
|
16
|
+
*
|
|
17
|
+
* Changing either is still a retrieval-policy change, not a tidy-up.
|
|
8
18
|
*/
|
|
9
|
-
export const PACKAGE_RETRIEVE_LIMIT =
|
|
19
|
+
export const PACKAGE_RETRIEVE_LIMIT = 50;
|
|
10
20
|
export const PROJECT_RETRIEVE_LIMIT = 50;
|
|
11
21
|
/** Character budget for the assembled chunk text. The same for both corpora. */
|
|
12
22
|
export const RETRIEVE_CONTENT_BUDGET = 24_000;
|
|
@@ -210,6 +220,16 @@ function definitionChunk(cache, opts, name) {
|
|
|
210
220
|
* declaration per chunk, so the short chunk carrying the name IS its declaration and
|
|
211
221
|
* the long ones are the prose that merely mentions it.
|
|
212
222
|
*/
|
|
223
|
+
/** The chunk without the `// path` / `-- path` line the indexer prepends. */
|
|
224
|
+
function chunkBody(content) {
|
|
225
|
+
return content.replace(/^(?:\/\/|--)[^\n]*\n/, '');
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* A chunk that only declares a MODULE. `pub mod serve;` is shorter than the
|
|
229
|
+
* function it contains and wins smallest-first, while being neither the value nor
|
|
230
|
+
* the type this hop exists to find.
|
|
231
|
+
*/
|
|
232
|
+
const MODULE_DECL_RE = /^(?:#\[[^\n]*\]\s*)*(?:pub(?:\s*\([^)]*\))?\s+|export\s+|declare\s+)*(?:mod|module|namespace)\s+[A-Za-z_][\w']*\s*;?\s*$/;
|
|
213
233
|
function valueChunk(cache, opts, name) {
|
|
214
234
|
const rows = cache.db
|
|
215
235
|
.prepare(`SELECT file_path, kind, content, 0 AS rank FROM chunks
|
|
@@ -219,7 +239,14 @@ function valueChunk(cache, opts, name) {
|
|
|
219
239
|
// LIKE has no word boundary, so `decodeFile` matches `decodeFileStrict` — the
|
|
220
240
|
// wrong declaration, and the exact confusion these runs keep producing.
|
|
221
241
|
const whole = new RegExp(`(?<![A-Za-z0-9_])${escapeRe(name)}(?![A-Za-z0-9_])`);
|
|
222
|
-
|
|
242
|
+
// Over the BODY, never the `// path` line the indexer prepends. Every chunk
|
|
243
|
+
// from `src/serve/mod.rs` carries "serve" in that line, so smallest-first
|
|
244
|
+
// handed axum's `serve` a 50-byte `pub struct TapIo` from a neighbouring file
|
|
245
|
+
// — the name was in the header and nowhere else.
|
|
246
|
+
const row = rows.find(r => {
|
|
247
|
+
const text = chunkBody(r.content);
|
|
248
|
+
return whole.test(text) && !MODULE_DECL_RE.test(text);
|
|
249
|
+
});
|
|
223
250
|
if (!row)
|
|
224
251
|
return null;
|
|
225
252
|
return { filePath: row.file_path, kind: row.kind, content: row.content, rank: row.rank };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.14",
|
|
4
4
|
"description": "Deterministic task planning and spec-orchestration for local models — crash-safe /task pipelines with verify/enforce gates, a real-time remote web view, and web/docs/fetch/worker subagent tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|