agent-bios 0.17.0 → 0.17.1
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 +8 -0
- package/compose/corpus_ui.py +54 -5
- package/package.json +1 -1
- package/provenance.json +1 -1
package/README.md
CHANGED
|
@@ -283,6 +283,14 @@ arbitrary package authoring/import, automatic semantic conflict resolution, or v
|
|
|
283
283
|
native skill-menu registration; those design stages must not be inferred from the
|
|
284
284
|
library UI.
|
|
285
285
|
|
|
286
|
+
Studio marks rules containing explicit `guides/*.md` references with **→ GUIDE**
|
|
287
|
+
and the guide names in the library. Their **Guide pointer** section links to exact
|
|
288
|
+
guide members in the same package and shows each target's current consumption surface
|
|
289
|
+
and state. Missing or ambiguous targets are disclosed rather than guessed. These
|
|
290
|
+
are display-only references, not new dependencies or proof of loading: rule bodies,
|
|
291
|
+
IDs, ordering, selection, and delivery remain unchanged. Personal body edits are
|
|
292
|
+
reflected when the library refreshes; ordinary rules are not classified by meaning.
|
|
293
|
+
|
|
286
294
|
New personal identities are allocated once in the creation plan and remain stable
|
|
287
295
|
on retry; reset and history rollback do not make retired identities reusable.
|
|
288
296
|
Member files are the content authority: `primary_member` identifies the main file,
|
package/compose/corpus_ui.py
CHANGED
|
@@ -11,7 +11,9 @@ import json
|
|
|
11
11
|
import re
|
|
12
12
|
from pathlib import PurePosixPath
|
|
13
13
|
from typing import Any
|
|
14
|
-
from urllib.parse import unquote
|
|
14
|
+
from urllib.parse import quote, unquote
|
|
15
|
+
|
|
16
|
+
from rich.text import Text
|
|
15
17
|
|
|
16
18
|
from textual.app import App, ComposeResult
|
|
17
19
|
from textual.binding import Binding
|
|
@@ -41,6 +43,34 @@ SURFACES = ("always", "relevant", "requested", "event", "delegated")
|
|
|
41
43
|
VIEWS = ("effective", "installed", "change", "diff", "history")
|
|
42
44
|
|
|
43
45
|
|
|
46
|
+
def guide_pointers(item: dict[str, Any], inventory: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
47
|
+
"""Display literal guide references, not inferred dependencies or new routing."""
|
|
48
|
+
if item.get("kind") != "rule":
|
|
49
|
+
return []
|
|
50
|
+
paths = dict.fromkeys(re.findall(r"\bguides/[A-Za-z0-9][A-Za-z0-9_./-]*\.md\b", item.get("body", "")))
|
|
51
|
+
result = []
|
|
52
|
+
for path in paths:
|
|
53
|
+
if ".." in PurePosixPath(path).parts:
|
|
54
|
+
continue
|
|
55
|
+
matches = [candidate for candidate in inventory
|
|
56
|
+
if candidate.get("package_id") == item.get("package_id")
|
|
57
|
+
and candidate.get("kind") == "guide" and path in candidate.get("members", {})]
|
|
58
|
+
result.append({"path": path, "target": matches[0] if len(matches) == 1 else None,
|
|
59
|
+
"problem": "Ambiguous guide reference" if matches else "Not found in this package"})
|
|
60
|
+
return result
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def library_label(item: dict[str, Any], inventory: list[dict[str, Any]]) -> Text:
|
|
64
|
+
pointers = guide_pointers(item, inventory)
|
|
65
|
+
label = Text()
|
|
66
|
+
if pointers:
|
|
67
|
+
label.append("→ GUIDE ", style="bold cyan")
|
|
68
|
+
label.append(", ".join(PurePosixPath(pointer["path"]).stem for pointer in pointers))
|
|
69
|
+
label.append(" · ")
|
|
70
|
+
label.append(f"{item.get('title', item.get('ref'))} · {item.get('surface', '?')}")
|
|
71
|
+
return label
|
|
72
|
+
|
|
73
|
+
|
|
44
74
|
def render_member_body(body: str, member: str | None, kind: str | None = None) -> str:
|
|
45
75
|
"""Render prose as Markdown and preserve source files as literal code."""
|
|
46
76
|
suffix = PurePosixPath(member).suffix.lower() if member else ""
|
|
@@ -83,6 +113,9 @@ class CorpusMarkdownViewer(MarkdownViewer):
|
|
|
83
113
|
"""Keep all links inside Studio; never hand a URL to the operating system."""
|
|
84
114
|
|
|
85
115
|
async def _on_markdown_link_clicked(self, message: Markdown.LinkClicked) -> None:
|
|
116
|
+
# stop() prevents bubbling, not the inherited MarkdownViewer handler.
|
|
117
|
+
# Its default go() would try to load corpus:// as a filesystem path.
|
|
118
|
+
message.prevent_default()
|
|
86
119
|
message.stop()
|
|
87
120
|
if message.href.startswith("corpus://"):
|
|
88
121
|
ref = unquote(message.href.removeprefix("corpus://"))
|
|
@@ -252,7 +285,7 @@ class CorpusStudio(App[None]):
|
|
|
252
285
|
groups[key] = state_nodes[state].add(package)
|
|
253
286
|
groups[key].expand()
|
|
254
287
|
groups[key].add_leaf(
|
|
255
|
-
|
|
288
|
+
library_label(item, self.items),
|
|
256
289
|
data=item.get("ref"),
|
|
257
290
|
)
|
|
258
291
|
tree.root.expand()
|
|
@@ -327,8 +360,7 @@ class CorpusStudio(App[None]):
|
|
|
327
360
|
members[self.current_member] = self.query_one("#editor-body", TextArea).text
|
|
328
361
|
return members
|
|
329
362
|
|
|
330
|
-
|
|
331
|
-
def _render_item(row: dict[str, Any], result: dict[str, Any], view: str) -> str:
|
|
363
|
+
def _render_item(self, row: dict[str, Any], result: dict[str, Any], view: str) -> str:
|
|
332
364
|
if view == "effective" and isinstance(result.get("item"), dict):
|
|
333
365
|
item = result["item"]
|
|
334
366
|
links = "\n".join(
|
|
@@ -344,11 +376,28 @@ class CorpusStudio(App[None]):
|
|
|
344
376
|
+ (f" Available members: {members}." if members else "") + "\n"
|
|
345
377
|
)
|
|
346
378
|
body = render_member_body(item.get("body", ""), item.get("primary_member"), item.get("kind"))
|
|
379
|
+
pointers = guide_pointers(item, self.items)
|
|
380
|
+
guide_links = ""
|
|
381
|
+
if pointers:
|
|
382
|
+
lines = []
|
|
383
|
+
for pointer in pointers:
|
|
384
|
+
target = pointer["target"]
|
|
385
|
+
if target is None:
|
|
386
|
+
lines.append(f"- `{pointer['path']}` — {pointer['problem']}")
|
|
387
|
+
else:
|
|
388
|
+
destination = quote(target["ref"], safe="@/:")
|
|
389
|
+
lines.append(f"- [{pointer['path']}](corpus://{destination}) — "
|
|
390
|
+
f"**{target['surface']}** · {target.get('state', 'active')}")
|
|
391
|
+
guide_links = (
|
|
392
|
+
"## Guide pointer\n\nThis rule explicitly references the following guide(s). "
|
|
393
|
+
"The rule keeps its own consumption surface; these links do not change "
|
|
394
|
+
"delivery or prove that a guide was loaded.\n\n" + "\n".join(lines) + "\n\n## Rule\n\n"
|
|
395
|
+
)
|
|
347
396
|
return (
|
|
348
397
|
f"# {item.get('title', item.get('ref'))}\n\n"
|
|
349
398
|
f"`{item.get('ref')}` · **{row.get('state', 'active')}** · "
|
|
350
399
|
f"{item.get('surface')} · {item.get('kind')}\n\n"
|
|
351
|
-
f"{reconciliation}\n{body}\n\n## Dependencies\n\n{links}\n"
|
|
400
|
+
f"{guide_links}{reconciliation}\n{body}\n\n## Dependencies\n\n{links}\n"
|
|
352
401
|
+ ("\n## Native consumption\n\nRequires explicit `agent-launch --corpus-native`.\n"
|
|
353
402
|
if item.get("kind") == "hook" else "")
|
|
354
403
|
)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-bios",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"releaseDate": "2026-09-11",
|
|
5
5
|
"description": "A thin, low-level instruction layer for LLM CLI agents: one set of principles and behavior whichever model you run. Stores a private, editable corpus for explicitly activated sessions.",
|
|
6
6
|
"bin": {
|
package/provenance.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"ef9c746993ca2908f76ea41e2bfb7e097a18047f","committedAt":"2026-09-11T16:37:10+09:00","dirty":false}
|