@taurgis/bonsai 1.0.2 → 1.0.3
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.
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: '
|
|
2
|
+
description: 'Verify current official docs before technical repo changes — inline via the web-research skill for minor research, via the Official Docs Researcher subagent for extensive research.'
|
|
3
3
|
applyTo: '**'
|
|
4
4
|
skills:
|
|
5
5
|
- web-research
|
|
6
6
|
metadata:
|
|
7
|
-
version: '3.
|
|
7
|
+
version: '3.1.0'
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Web Research Requirement
|
|
11
11
|
|
|
12
12
|
## Mandatory Pre-Step
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
14
|
+
- Verify the relevant current official documentation **in the same task** before creating, updating, refactoring, scaffolding, or deleting technical content.
|
|
15
|
+
- Apply what you find — cite official source URLs when the change relies on platform behavior or standards.
|
|
16
|
+
- Research is the requirement; how you run it scales with scope (below). Training-data knowledge never satisfies this — only docs fetched in the current task do.
|
|
17
|
+
|
|
18
|
+
## Choose How to Research by Scope
|
|
19
|
+
|
|
20
|
+
- **Minor research — run it inline.** For a single known page, one platform, or a quick flag/API/version check, the main agent invokes the **web-research** skill directly. A separate subagent is not required.
|
|
21
|
+
- **Extensive research — delegate to a subagent.** For multiple sources or platforms, unfamiliar territory, broad audits, or anything that produces verbose output you do not want in the main context, run the **Official Docs Researcher** subagent and apply its findings.
|
|
22
|
+
- The main agent may always use the **web-research** skill directly — choose the subagent to isolate large research, not because inline research is disallowed.
|
|
23
|
+
- When unsure, start inline and escalate to the subagent once the work spans several sources.
|
|
24
|
+
|
|
25
|
+
## Shared Cache
|
|
26
|
+
|
|
27
|
+
- Both paths use the same freshness-tiered Bonsai cache (data directory or project-local `.bonsai/research/`): it reuses fresh notes, cheaply revalidates stale ones, and re-fetches only on a miss.
|
|
28
|
+
- Re-running on a recent topic is cheap — research the topic rather than skipping it to "save" a fetch.
|
|
17
29
|
|
|
18
30
|
## When Not to Use
|
|
19
31
|
|
|
@@ -23,7 +35,8 @@ metadata:
|
|
|
23
35
|
|
|
24
36
|
## Examples
|
|
25
37
|
|
|
26
|
-
- ✅
|
|
27
|
-
- ✅
|
|
38
|
+
- ✅ Confirming one platform's current flag or frontmatter field before a small edit → run the web-research skill inline.
|
|
39
|
+
- ✅ Comparing conventions across several platforms, or auditing/refactoring source broadly → delegate to the Official Docs Researcher subagent.
|
|
40
|
+
- ✅ Before editing instructions, prompts, agents, skills, workflows, or docs — reading source code does not replace checking current platform guidance.
|
|
28
41
|
- ✅ Include official source URLs when the change references platform behavior or standards.
|
|
29
|
-
- ❌ Don't modify technical content without
|
|
42
|
+
- ❌ Don't modify technical content without researching first, and don't treat cached or training knowledge as equivalent — official guidance evolves and must be verified per task.
|
|
@@ -6,6 +6,9 @@ const ERROR_PAGE_PATTERNS = [
|
|
|
6
6
|
/\bnot\s*found\b/i,
|
|
7
7
|
/there\s*isn'?t\s*a\s*github\s*pages\s*site\s*here/i,
|
|
8
8
|
/site\s*not\s*found/i,
|
|
9
|
+
// Client-rendered (SPA) failure shells that return HTTP 200 but render only an error notice.
|
|
10
|
+
/something\s+went\s+wrong/i,
|
|
11
|
+
/an?\s+error\s+occurred/i,
|
|
9
12
|
];
|
|
10
13
|
/** True when short text reads like an error/soft-404 page rather than real content. */
|
|
11
14
|
export function looksLikeErrorPage(text) {
|
|
@@ -7,6 +7,7 @@ import { evaluateFreshness, getPolicy } from './freshness.js';
|
|
|
7
7
|
import { compressMarkdown } from './compress.js';
|
|
8
8
|
import { estimateTokens } from './token-estimate.js';
|
|
9
9
|
import { fetchRenderedHtml } from './browser.js';
|
|
10
|
+
import { looksLikeErrorPage } from './docs/validate.js';
|
|
10
11
|
function buildMetadata(url, normalizedUrl, cacheKey, fetchResult, extraction, tier, ttl, currentTime, compressed) {
|
|
11
12
|
const contentHash = createHash('sha256').update(extraction.detailedMarkdown).digest('hex');
|
|
12
13
|
const staleAfterTime = new Date(currentTime);
|
|
@@ -51,10 +52,39 @@ function buildMetadata(url, normalizedUrl, cacheKey, fetchResult, extraction, ti
|
|
|
51
52
|
section_heading_path: null,
|
|
52
53
|
};
|
|
53
54
|
}
|
|
55
|
+
// Builds a compact error marker instead of caching a full error page. Subsequent lookups serve this
|
|
56
|
+
// tiny marker (a handful of tokens) instead of re-fetching, and revalidation re-checks it when stale
|
|
57
|
+
// so a transient failure recovers into a real artifact.
|
|
58
|
+
function buildErrorArtifact(url, normalizedUrl, cacheKey, fetchResult, tier, ttl, currentTime, reason) {
|
|
59
|
+
const marker = `Error: ${url} could not be cached — ${reason}. ` +
|
|
60
|
+
'The page returned an error, so its content was not stored; it will be re-fetched when this entry goes stale.';
|
|
61
|
+
const extraction = {
|
|
62
|
+
title: `Error: ${reason}`,
|
|
63
|
+
detailedMarkdown: marker,
|
|
64
|
+
confidence: 'low',
|
|
65
|
+
qualityNotes: [`error: ${reason}`],
|
|
66
|
+
};
|
|
67
|
+
const metadata = buildMetadata(url, normalizedUrl, cacheKey, fetchResult, extraction, tier, ttl, currentTime, marker);
|
|
68
|
+
metadata.extraction_status = 'failed';
|
|
69
|
+
metadata.extraction_confidence = null;
|
|
70
|
+
return {
|
|
71
|
+
metadata,
|
|
72
|
+
summary: extraction.title,
|
|
73
|
+
compressed: marker,
|
|
74
|
+
detailed: marker,
|
|
75
|
+
provenance: `Fetched from ${url} on ${currentTime.toISOString()} (error page; content not cached)`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
54
78
|
/**
|
|
55
79
|
* Helper to construct a ResearchArtifact from a fresh HTML fetch.
|
|
56
80
|
*/
|
|
57
81
|
export function createArtifactFromFetch(url, normalizedUrl, cacheKey, fetchResult, extraction, tier, ttl, currentTime) {
|
|
82
|
+
// A managed platform / SPA can return HTTP 200 but render only a "not found" / "something went
|
|
83
|
+
// wrong" shell. Cache a compact marker for those instead of the full error markdown, so repeat
|
|
84
|
+
// lookups cost a few tokens and revalidation still re-checks the page when the entry goes stale.
|
|
85
|
+
if (looksLikeErrorPage(extraction.detailedMarkdown)) {
|
|
86
|
+
return buildErrorArtifact(url, normalizedUrl, cacheKey, fetchResult, tier, ttl, currentTime, 'page reported an error or was not found');
|
|
87
|
+
}
|
|
58
88
|
const compressed = compressMarkdown(extraction.detailedMarkdown);
|
|
59
89
|
const metadata = buildMetadata(url, normalizedUrl, cacheKey, fetchResult, extraction, tier, ttl, currentTime, compressed);
|
|
60
90
|
return {
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taurgis/bonsai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Bonsai is a standalone local research cache CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"regression:suite": "tsc -b && node testing/regression/run-suite.mjs",
|
|
27
27
|
"regression:promote": "tsc -b && node testing/regression/run-suite.mjs --promote",
|
|
28
28
|
"regression:check": "tsc -b && node testing/regression/run-suite.mjs --strict",
|
|
29
|
+
"nexus:sync": "npx forward-nexus update && npx forward-nexus sync",
|
|
29
30
|
"test": "vitest",
|
|
30
31
|
"test:coverage": "vitest run --coverage",
|
|
31
32
|
"type-check": "tsc --noEmit"
|