@unerr-ai/unerr 0.2.7 → 0.2.8
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 +49 -26
- package/dist/cli.js +40 -41
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
<
|
|
2
|
-
<a href="https://www.unerr.dev/"><img src="https://unerr.dev/icon-wordmark.svg" alt="unerr
|
|
3
|
-
</
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<a href="https://www.unerr.dev/"><img src="https://unerr.dev/icon-wordmark.svg" alt="unerr" width="320" /></a>
|
|
3
|
+
</h1>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<strong>Your AI agent has read your codebase. It
|
|
6
|
+
<strong>Your AI agent has read your codebase. It still can't safely change it.</strong>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
On a large, existing codebase your agent can't hold the whole thing in context — so it breaks callers it never read<br/>
|
|
11
|
+
and rebuilds patterns your team already standardized, even with the rule written down. <strong>unerr is a guardrail<br/>
|
|
12
|
+
your agent reaches over MCP</strong> that, the moment it edits, hands it the live call graph <em>plus the rule you pinned to that<br/>
|
|
13
|
+
exact function</em> — a rule that re-anchors itself when the code moves instead of going stale. So it sees the 24 callers,<br/>
|
|
14
|
+
and the standard it's about to violate, <em>before</em> it touches the function.
|
|
13
15
|
</p>
|
|
14
16
|
|
|
15
17
|
<p align="center">
|
|
@@ -32,38 +34,59 @@
|
|
|
32
34
|
</p>
|
|
33
35
|
|
|
34
36
|
<p align="center">
|
|
35
|
-
<sub>
|
|
36
|
-
|
|
37
|
+
<sub><strong>It nets your context down, not up.</strong> Five separate MCP servers burn ~55K tokens of schemas just to announce themselves;<br/>
|
|
38
|
+
unerr is one runtime whose tools load on demand, and each edit injects a single scoped line — the rule for the entity in front of it.<br/>
|
|
39
|
+
Measured: the agent lands on the right code with <strong>86–90% fewer tokens</strong>, same corpus, same tokenizer, with a fidelity gate<br/>
|
|
40
|
+
that discards any "saving" that lost the answer. <a href="./benchmarks/README.md">See the benchmarks →</a></sub>
|
|
37
41
|
</p>
|
|
38
42
|
|
|
39
43
|
---
|
|
40
44
|
|
|
41
|
-
|
|
45
|
+
<details>
|
|
46
|
+
<summary><strong>Contents</strong></summary>
|
|
47
|
+
|
|
48
|
+
- [Agents read your code. They can't safely change it.](#agents-read-your-code-they-cant-safely-change-it)
|
|
49
|
+
- [The pains this fixes](#the-pains-this-fixes)
|
|
50
|
+
- [What changes when you install it](#what-changes-when-you-install-it)
|
|
51
|
+
- [See it in action](#see-it-in-action)
|
|
52
|
+
- [Quick Start](#quick-start)
|
|
53
|
+
- [Who it's for](#who-its-for)
|
|
54
|
+
- [Why one runtime, not five separate tools](#why-one-runtime-not-five-separate-tools)
|
|
55
|
+
- [How the runtime works](#how-the-runtime-works)
|
|
56
|
+
- [License](#license)
|
|
57
|
+
|
|
58
|
+
</details>
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Agents read your code. They can't safely change it.
|
|
63
|
+
|
|
64
|
+
On a small or greenfield project the agent holds the whole repo in its head and grepping the live code is enough — you don't need us. The wall is the *large, existing, multi-contributor* codebase, and it's the same wall every time: the agent can't fit the whole thing in context, so it acts on the slice it can see and never reads the rest.
|
|
42
65
|
|
|
43
|
-
|
|
66
|
+
So it ships damage that looks locally correct. It changes a signature and breaks the 24 callers it never read. It writes a fourth copy of a registry pattern your team standardized months ago — even with the rule spelled out in `.cursorrules`. Neither shows up as an error. They show up as a senior engineer's afternoon.
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
The knowledge that would have stopped it — who calls this function, which pattern is load-bearing — exists. It's just nowhere the agent can reach *at the moment it edits*: in a call graph it doesn't build, and conventions it was never told.
|
|
46
69
|
|
|
47
|
-
**unerr is the
|
|
70
|
+
**unerr is the guardrail that closes that gap.** One local runtime your agent reaches over MCP, that hands it the call graph and the rules you anchored to each entity the moment it edits — and re-anchors those rules when the code moves, so they never go silently stale. A change that would break 7 call sites is caught before it lands; a standard you set once is enforced every time the agent touches that scope.
|
|
48
71
|
|
|
49
72
|
| The old way | With unerr |
|
|
50
73
|
|---|---|
|
|
51
|
-
| The agent
|
|
52
|
-
|
|
|
53
|
-
| Five single-purpose MCP servers — memory, graph, compressor — that can't reach across each other. | **One runtime** —
|
|
74
|
+
| The agent changes a function without reading its 24 callers — 7 sites break silently. | **Cascade guard** reads the call graph *before* the edit; every caller is on screen first. |
|
|
75
|
+
| The agent ships a fourth copy of a pattern your team standardized — the rule in `.cursorrules` was never honored. | **Anchored rules** surface the standard the moment the agent touches that scope, and re-anchor when the code moves instead of going silently stale. |
|
|
76
|
+
| Five single-purpose MCP servers — memory, graph, compressor — that can't reach across each other. | **One runtime** — cascade guard, convention drift, and a loop breaker (*stops the agent re-trying a fix that already failed twice*) fire on joins no point tool can make. |
|
|
54
77
|
|
|
55
78
|
---
|
|
56
79
|
|
|
57
80
|
## The pains this fixes
|
|
58
81
|
|
|
59
|
-
|
|
82
|
+
If you're maintaining a large, existing codebase, you've hit these — and they get *worse* as the repo grows, not better:
|
|
60
83
|
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
84
|
+
- The agent is sharp for 20 minutes, then writes a second implementation of something you already have, because it never saw the first.
|
|
85
|
+
- You don't trust it to change anything load-bearing. It treats your codebase as a flat string of text — locally correct, globally wrong.
|
|
86
|
+
- It reads a 2,000-line file to find a 5-line function, then still doesn't know that function has 24 callers in six other files.
|
|
87
|
+
- The rule you wrote in `.cursorrules` gets acknowledged, then ignored a few turns later once the context fills up.
|
|
65
88
|
|
|
66
|
-
These aren't four problems. They're one: **your agent acts on
|
|
89
|
+
These aren't four problems. They're one: **your agent acts on a codebase it can't hold in context, with no idea what each change will break or which rule it's about to violate.**
|
|
67
90
|
|
|
68
91
|
---
|
|
69
92
|
|
|
@@ -72,7 +95,7 @@ These aren't four problems. They're one: **your agent acts on your codebase with
|
|
|
72
95
|
| You feel | What unerr does |
|
|
73
96
|
|---|---|
|
|
74
97
|
| **Trust returns.** The agent runs for an hour without you watching. | Every edit is preceded by a graph lookup. All 24 callers are visible *before* it touches the function. Refactors stop rippling silently. |
|
|
75
|
-
| **
|
|
98
|
+
| **Your rules finally get honored.** The standard you set is enforced at the edit, not acknowledged and forgotten once context fills up. | unerr anchors each rule and decision to the file or entity it governs and surfaces it the instant the agent touches that scope — then re-anchors it when the code moves, so it never goes silently stale. Keep your `.cursorrules` and specs; unerr makes sure they're applied. |
|
|
76
99
|
| **The agent stays sharp at turn 50.** | `file_read({entity})` returns 200 lines instead of 3,000. Shell output is compressed 93% on average. The context window stays uncluttered, so the model isn't fighting "lost in the middle." |
|
|
77
100
|
| **Tool sprawl dies.** | One graph, one set of tools, project-aware routing. Five MCP servers no longer compete for the agent's attention. |
|
|
78
101
|
|
|
@@ -163,9 +186,9 @@ Close and reopen your IDE (or start a new chat session). Your agent picks up une
|
|
|
163
186
|
|
|
164
187
|
## Who it's for
|
|
165
188
|
|
|
166
|
-
- **
|
|
167
|
-
- **
|
|
168
|
-
- **
|
|
189
|
+
- **Engineers on large, existing codebases.** The dependency graph, the load-bearing patterns, and the prior incidents a senior engineer carries in their head — handed to the agent before every edit, so it stops breaking callers it never read.
|
|
190
|
+
- **Teams with conventions worth enforcing.** The standard you agreed on once, applied every time the agent touches that scope — no `.cursorrules` file to hand-maintain, re-paste, or merge-conflict over.
|
|
191
|
+
- **Solo builders shipping into a codebase that's already grown.** The continuous thread across tools — switch from Claude Code in the terminal to Cursor in the IDE and the graph, rules, and history come with you, instead of relearning the repo every session.
|
|
169
192
|
|
|
170
193
|
---
|
|
171
194
|
|
package/dist/cli.js
CHANGED
|
@@ -5639,13 +5639,13 @@ var init_temporal_facts = __esm({
|
|
|
5639
5639
|
session_analysis: 0.6,
|
|
5640
5640
|
user_fed: 0.95
|
|
5641
5641
|
};
|
|
5642
|
-
MAX_CONTENT_LENGTH =
|
|
5642
|
+
MAX_CONTENT_LENGTH = 1400;
|
|
5643
5643
|
TYPE_CONTENT_LIMITS = {
|
|
5644
|
-
convention:
|
|
5645
|
-
semantic:
|
|
5646
|
-
episodic:
|
|
5647
|
-
procedural:
|
|
5648
|
-
negative:
|
|
5644
|
+
convention: 1400,
|
|
5645
|
+
semantic: 1400,
|
|
5646
|
+
episodic: 1600,
|
|
5647
|
+
procedural: 1400,
|
|
5648
|
+
negative: 1400
|
|
5649
5649
|
};
|
|
5650
5650
|
TemporalFactStore = class _TemporalFactStore {
|
|
5651
5651
|
constructor(db, config) {
|
|
@@ -12996,12 +12996,12 @@ function formatSessionResumeBlock(payload) {
|
|
|
12996
12996
|
);
|
|
12997
12997
|
if (payload.last_intents && payload.last_intents.length > 0) {
|
|
12998
12998
|
const intent = payload.last_intents[0];
|
|
12999
|
-
if (intent) parts.push(`\u25B8 last intent: ${intent.text}`);
|
|
12999
|
+
if (intent) parts.push(`\u25B8 last intent: ${truncateForStrip(intent.text)}`);
|
|
13000
13000
|
}
|
|
13001
13001
|
if (payload.open_blockers && payload.open_blockers.length > 0) {
|
|
13002
13002
|
for (const b of payload.open_blockers.slice(0, 3)) {
|
|
13003
13003
|
const anchor = b.file_path ? ` [${b.file_path}]` : "";
|
|
13004
|
-
parts.push(`\u25B8 unresolved blocker: ${b.text}${anchor}`);
|
|
13004
|
+
parts.push(`\u25B8 unresolved blocker: ${truncateForStrip(b.text)}${anchor}`);
|
|
13005
13005
|
}
|
|
13006
13006
|
}
|
|
13007
13007
|
if (payload.broken_callers && payload.broken_callers.length > 0) {
|
|
@@ -13031,6 +13031,10 @@ function formatSessionResumeBlock(payload) {
|
|
|
13031
13031
|
const result = parts.join("\n");
|
|
13032
13032
|
return result.length > 500 ? `${result.slice(0, 497)}...` : result;
|
|
13033
13033
|
}
|
|
13034
|
+
function truncateForStrip(text2, max = 100) {
|
|
13035
|
+
const t = text2.trim();
|
|
13036
|
+
return t.length > max ? `${t.slice(0, max - 1)}\u2026` : t;
|
|
13037
|
+
}
|
|
13034
13038
|
function formatElapsed(ms) {
|
|
13035
13039
|
const minutes = Math.floor(ms / 6e4);
|
|
13036
13040
|
if (minutes < 60) return `${minutes}m`;
|
|
@@ -26756,27 +26760,27 @@ var init_tool_descriptions = __esm({
|
|
|
26756
26760
|
// ── Tier 3 — intent unlock ─────────────────────────────────────────────
|
|
26757
26761
|
mark_intent: {
|
|
26758
26762
|
tier: 3,
|
|
26759
|
-
active: "REQUIRED first on coding tasks (implement/fix/refactor/build).
|
|
26760
|
-
locked: "[locked, unlock: first non-trivial action] REQUIRED first on coding tasks.
|
|
26761
|
-
unlocked: "REQUIRED first on coding tasks.
|
|
26763
|
+
active: "REQUIRED first on coding tasks (implement/fix/refactor/build). 1 terse sentence. Skip only for read-only questions. Powers resume strip.",
|
|
26764
|
+
locked: "[locked, unlock: first non-trivial action] REQUIRED first on coding tasks. 1 terse sentence.",
|
|
26765
|
+
unlocked: "REQUIRED first on coding tasks. 1 terse sentence. One per task; powers turn titles + cross-session resume."
|
|
26762
26766
|
},
|
|
26763
26767
|
mark_decision: {
|
|
26764
26768
|
tier: 3,
|
|
26765
|
-
active: "Record a deliberate choice between alternatives (\
|
|
26769
|
+
active: "Record a deliberate choice between alternatives (1-2 sentences, \u22641400 chars). Optional list of considered alternatives.",
|
|
26766
26770
|
locked: "[locked, unlock: after mark_intent] Record a deliberate choice between alternatives.",
|
|
26767
|
-
unlocked: "Record a deliberate choice (\
|
|
26771
|
+
unlocked: "Record a deliberate choice (1-2 sentences, \u22641400 chars). Optional alternatives list (\u22645, each \u226480 chars). Surfaces in timeline."
|
|
26768
26772
|
},
|
|
26769
26773
|
mark_blocker: {
|
|
26770
26774
|
tier: 3,
|
|
26771
|
-
active: "Record an unresolved obstacle (\
|
|
26775
|
+
active: "Record an unresolved obstacle (1-2 sentences, \u22641400 chars). Returned marker_id is required by mark_resolution when fixed.",
|
|
26772
26776
|
locked: "[locked, unlock: after mark_intent] Record an unresolved obstacle.",
|
|
26773
|
-
unlocked: "Record an obstacle (\
|
|
26777
|
+
unlocked: "Record an obstacle (1-2 sentences, \u22641400 chars). Returned marker_id must be passed to mark_resolution when fixed. Surfaces in resume."
|
|
26774
26778
|
},
|
|
26775
26779
|
mark_resolution: {
|
|
26776
26780
|
tier: 3,
|
|
26777
26781
|
active: "Resolve a prior blocker. blocker_ref is the marker_id from mark_blocker; text describes the fix.",
|
|
26778
26782
|
locked: "[locked, unlock: after mark_blocker] Resolve a prior blocker.",
|
|
26779
|
-
unlocked: "Resolve a prior blocker. blocker_ref is the marker_id from mark_blocker. Text (\
|
|
26783
|
+
unlocked: "Resolve a prior blocker. blocker_ref is the marker_id from mark_blocker. Text (1-3 sentences, \u22641400 chars) describes the fix."
|
|
26780
26784
|
},
|
|
26781
26785
|
recall_facts: {
|
|
26782
26786
|
tier: 3,
|
|
@@ -27238,7 +27242,7 @@ var init_tool_definitions = __esm({
|
|
|
27238
27242
|
properties: {
|
|
27239
27243
|
text: {
|
|
27240
27244
|
type: "string",
|
|
27241
|
-
description: "
|
|
27245
|
+
description: "Task in 1 terse sentence. Hard cap 1400 chars; be concise."
|
|
27242
27246
|
}
|
|
27243
27247
|
},
|
|
27244
27248
|
required: ["text"]
|
|
@@ -27255,7 +27259,7 @@ var init_tool_definitions = __esm({
|
|
|
27255
27259
|
properties: {
|
|
27256
27260
|
text: {
|
|
27257
27261
|
type: "string",
|
|
27258
|
-
description: "
|
|
27262
|
+
description: "Decision in 1-2 sentences. Hard cap 1400 chars; be concise."
|
|
27259
27263
|
},
|
|
27260
27264
|
alternatives: {
|
|
27261
27265
|
type: "array",
|
|
@@ -27277,7 +27281,7 @@ var init_tool_definitions = __esm({
|
|
|
27277
27281
|
properties: {
|
|
27278
27282
|
text: {
|
|
27279
27283
|
type: "string",
|
|
27280
|
-
description: "
|
|
27284
|
+
description: "Blocker in 1-2 sentences. Hard cap 1400 chars; be concise."
|
|
27281
27285
|
},
|
|
27282
27286
|
file_path: {
|
|
27283
27287
|
type: "string",
|
|
@@ -27302,7 +27306,7 @@ var init_tool_definitions = __esm({
|
|
|
27302
27306
|
},
|
|
27303
27307
|
text: {
|
|
27304
27308
|
type: "string",
|
|
27305
|
-
description: "
|
|
27309
|
+
description: "What fixed the blocker, in 1-3 sentences. Hard cap 1400 chars."
|
|
27306
27310
|
}
|
|
27307
27311
|
},
|
|
27308
27312
|
required: ["blocker_ref", "text"]
|
|
@@ -27425,7 +27429,7 @@ var init_tool_definitions = __esm({
|
|
|
27425
27429
|
// ── Legacy free-form (TemporalFactStore) payload ──
|
|
27426
27430
|
content: {
|
|
27427
27431
|
type: "string",
|
|
27428
|
-
description: "Normalised statement of the user's fact
|
|
27432
|
+
description: "Normalised statement of the user's fact, 1-3 sentences. Hard cap 1400 chars; keep terse."
|
|
27429
27433
|
},
|
|
27430
27434
|
source_quote: {
|
|
27431
27435
|
type: "string",
|
|
@@ -28023,9 +28027,9 @@ async function executeRecordFact(args, factStore, sessionId) {
|
|
|
28023
28027
|
if (!content || content.trim().length === 0) {
|
|
28024
28028
|
throw new Error("content is required and cannot be empty");
|
|
28025
28029
|
}
|
|
28026
|
-
if (content.length >
|
|
28030
|
+
if (content.length > 1400) {
|
|
28027
28031
|
throw new Error(
|
|
28028
|
-
`content
|
|
28032
|
+
`content is ${content.length} chars, exceeds 1400-char cap. Shorten to \u22641400 (1-3 sentences).`
|
|
28029
28033
|
);
|
|
28030
28034
|
}
|
|
28031
28035
|
if (!["procedural", "semantic", "negative", "convention"].includes(fact_type)) {
|
|
@@ -28048,11 +28052,8 @@ async function executeRecordFact(args, factStore, sessionId) {
|
|
|
28048
28052
|
base_confidence: 0.95
|
|
28049
28053
|
};
|
|
28050
28054
|
const { fact_id, deduplicated } = await factStore.createFact(input);
|
|
28051
|
-
const verb = deduplicated ? "Reinforced" : "Recorded";
|
|
28052
|
-
const message = `${verb}: "${content.trim().slice(0, 60)}${content.trim().length > 60 ? "..." : ""}" [${fact_type}] \u2192 ${scope}`;
|
|
28053
28055
|
return {
|
|
28054
28056
|
fact_id,
|
|
28055
|
-
message,
|
|
28056
28057
|
deduplicated
|
|
28057
28058
|
};
|
|
28058
28059
|
}
|
|
@@ -28193,9 +28194,9 @@ async function executeUnerrRemember(args, factStore, sessionId, turn, behaviorEv
|
|
|
28193
28194
|
if (!content || content.trim().length === 0) {
|
|
28194
28195
|
throw new Error("content is required and cannot be empty");
|
|
28195
28196
|
}
|
|
28196
|
-
if (content.length >
|
|
28197
|
+
if (content.length > 1400) {
|
|
28197
28198
|
throw new Error(
|
|
28198
|
-
`content
|
|
28199
|
+
`content is ${content.length} chars, exceeds 1400-char cap. Shorten to \u22641400 (1-3 sentences).`
|
|
28199
28200
|
);
|
|
28200
28201
|
}
|
|
28201
28202
|
if (!source_quote || source_quote.trim().length === 0) {
|
|
@@ -28248,11 +28249,6 @@ async function executeUnerrRemember(args, factStore, sessionId, turn, behaviorEv
|
|
|
28248
28249
|
});
|
|
28249
28250
|
const ambiguity_flag = confidence < REMEMBER_AMBIGUITY_THRESHOLD;
|
|
28250
28251
|
const trimmedContent = content.trim();
|
|
28251
|
-
const previewContent = `${trimmedContent.slice(0, 60)}${trimmedContent.length > 60 ? "..." : ""}`;
|
|
28252
|
-
const scopeText = scope.trim() === "project" ? "the whole project" : `\`${scope.trim()}\``;
|
|
28253
|
-
const verb = deduplicated ? "reinforced an existing note" : "added a new note";
|
|
28254
|
-
const tail = ambiguity_flag ? ` \u2014 I'm only ${Math.round(confidence * 100)}% sure I got that right, please confirm or correct` : "";
|
|
28255
|
-
const echo_summary = `unerr ${verb} for ${scopeText}: "${previewContent}"${tail}`;
|
|
28256
28252
|
if (ambiguity_flag && pendingConfirmations) {
|
|
28257
28253
|
pendingConfirmations.register({
|
|
28258
28254
|
fact_id,
|
|
@@ -28289,8 +28285,7 @@ async function executeUnerrRemember(args, factStore, sessionId, turn, behaviorEv
|
|
|
28289
28285
|
fact_id,
|
|
28290
28286
|
deduplicated,
|
|
28291
28287
|
ambiguity_flag,
|
|
28292
|
-
confidence
|
|
28293
|
-
echo_summary
|
|
28288
|
+
confidence
|
|
28294
28289
|
};
|
|
28295
28290
|
}
|
|
28296
28291
|
var REMEMBER_CONFIDENCE_FLOOR, REMEMBER_AMBIGUITY_THRESHOLD;
|
|
@@ -42158,6 +42153,7 @@ var init_loop_breaker = __esm({
|
|
|
42158
42153
|
// src/tools/intelligence/timeline-markers.ts
|
|
42159
42154
|
var timeline_markers_exports = {};
|
|
42160
42155
|
__export(timeline_markers_exports, {
|
|
42156
|
+
MARKER_TEXT_CAP: () => MARKER_TEXT_CAP,
|
|
42161
42157
|
MARKER_TOOLS: () => MARKER_TOOLS,
|
|
42162
42158
|
handleMarkerCall: () => handleMarkerCall,
|
|
42163
42159
|
isMarkerTool: () => isMarkerTool
|
|
@@ -42172,7 +42168,9 @@ async function handleMarkerCall(toolName, args, deps) {
|
|
|
42172
42168
|
return errorResult2(`${toolName}: text is required`);
|
|
42173
42169
|
}
|
|
42174
42170
|
if (text2.length > cap2) {
|
|
42175
|
-
return errorResult2(
|
|
42171
|
+
return errorResult2(
|
|
42172
|
+
`${toolName}: text is ${text2.length} chars, exceeds ${cap2}-char cap \u2014 shorten to \u2264${cap2}.`
|
|
42173
|
+
);
|
|
42176
42174
|
}
|
|
42177
42175
|
const argsToPersist = { text: text2 };
|
|
42178
42176
|
let blockerRef = "";
|
|
@@ -42251,7 +42249,7 @@ function errorResult2(msg) {
|
|
|
42251
42249
|
]
|
|
42252
42250
|
};
|
|
42253
42251
|
}
|
|
42254
|
-
var MARKER_TOOLS, MARKER_TOOL_SET, TEXT_CAP;
|
|
42252
|
+
var MARKER_TOOLS, MARKER_TOOL_SET, MARKER_TEXT_CAP, TEXT_CAP;
|
|
42255
42253
|
var init_timeline_markers = __esm({
|
|
42256
42254
|
"src/tools/intelligence/timeline-markers.ts"() {
|
|
42257
42255
|
"use strict";
|
|
@@ -42263,11 +42261,12 @@ var init_timeline_markers = __esm({
|
|
|
42263
42261
|
"mark_resolution"
|
|
42264
42262
|
];
|
|
42265
42263
|
MARKER_TOOL_SET = new Set(MARKER_TOOLS);
|
|
42264
|
+
MARKER_TEXT_CAP = 1400;
|
|
42266
42265
|
TEXT_CAP = {
|
|
42267
|
-
mark_intent:
|
|
42268
|
-
mark_decision:
|
|
42269
|
-
mark_blocker:
|
|
42270
|
-
mark_resolution:
|
|
42266
|
+
mark_intent: MARKER_TEXT_CAP,
|
|
42267
|
+
mark_decision: MARKER_TEXT_CAP,
|
|
42268
|
+
mark_blocker: MARKER_TEXT_CAP,
|
|
42269
|
+
mark_resolution: MARKER_TEXT_CAP
|
|
42271
42270
|
};
|
|
42272
42271
|
}
|
|
42273
42272
|
});
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unerr-ai/unerr",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"mcpName": "io.github.unerr-ai/unerr",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Your AI agent has read your codebase but still can't safely change it. unerr is a local guardrail that hands the agent the call graph and your rules at the moment it edits.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/unerr-ai/unerr-cli.git"
|