textus 0.8.0 → 0.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +4 -4
- data/SPEC.md +1 -1
- data/lib/textus/doctor.rb +1 -1
- data/lib/textus/init.rb +1 -1
- data/lib/textus/intro.rb +3 -3
- data/lib/textus/store.rb +3 -3
- data/lib/textus/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4b96d4cff83e901df4b2871b57f9c86d071b11126fd42e8fc5563abf45ce810
|
|
4
|
+
data.tar.gz: 6afa20a10f7ddee98b5b4adbf6eb87218725b5eb1c3f7b181b8bcb462d4fff74
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 83825a241b91ac10c2024ebdf04ec0f1bb753b8deeded27894fbbbff84f3f654ad6cc4c0faa2bbfcf940b989bc0393d832ae90af837039814fe51e5f7e4c4515
|
|
7
|
+
data.tar.gz: 57079b174111a5e89637140d53ca83f5c9b0c5f777c270be9833174c3dd11c7f4d8b8039ef30c69c6f85e1dfb9d78c89dab3eb99cd517b32e1cf7af2ce7ded7a
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,27 @@ The **gem version** (`0.x.y`) is distinct from the **protocol version**
|
|
|
8
8
|
(currently `textus/2`, embedded in every envelope as `protocol`). The protocol
|
|
9
9
|
is additive within a major; a new major would change the wire string.
|
|
10
10
|
|
|
11
|
+
## 0.8.1 — Terminology cleanup (2026-05-21)
|
|
12
|
+
|
|
13
|
+
### Breaking — intro output
|
|
14
|
+
- `textus intro` JSON: the `"extensions"` key is renamed to `"hooks"`. Consumers
|
|
15
|
+
reading `env["extensions"]` must switch to `env["hooks"]`. Wire protocol
|
|
16
|
+
remains `textus/2`; envelope shape on read/write is unchanged.
|
|
17
|
+
|
|
18
|
+
### Internal Ruby renames
|
|
19
|
+
- `Textus::Store#load_extensions` → `Textus::Store#load_hooks`.
|
|
20
|
+
- `Textus::Intro.extensions_for` → `Textus::Intro.hooks_for`.
|
|
21
|
+
- Error string `"failed loading extension <file>"` → `"failed loading hook <file>"`.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- `textus doctor` `:check`-hook failure hint pointed to `.textus/extensions/`,
|
|
25
|
+
which has never existed in 0.6+. Now correctly points to `.textus/hooks/`.
|
|
26
|
+
|
|
27
|
+
### Docs
|
|
28
|
+
- SPEC.md §5.10: "single extension verb" → "single hook verb".
|
|
29
|
+
- Scaffolded `.textus/hooks/README.md` no longer mixes "hook" and "extension"
|
|
30
|
+
terminology.
|
|
31
|
+
|
|
11
32
|
## 0.8.0 — Folder restructure & Zeitwerk autoload (2026-05-21)
|
|
12
33
|
|
|
13
34
|
### Breaking — internal Ruby renames
|
data/README.md
CHANGED
|
@@ -45,7 +45,7 @@ You get `.textus/` with all five zone directories, baseline schemas, an empty au
|
|
|
45
45
|
audit.log # append-only NDJSON, every write
|
|
46
46
|
schemas/ # YAML field shapes per entry family
|
|
47
47
|
templates/ # mustache templates for derived entries
|
|
48
|
-
|
|
48
|
+
hooks/ # one .rb per hook
|
|
49
49
|
sentinels/ # publish bookkeeping
|
|
50
50
|
zones/
|
|
51
51
|
canon/ # human-only — identity, voice, decisions
|
|
@@ -77,8 +77,8 @@ For the full shape — Claude plugin with agents, skills, commands, pending walk
|
|
|
77
77
|
- **Per-leaf publishing.** Nested entries declare `publish_each: "skills/{basename}/SKILL.md"`. Every leaf byte-copies to its consumer location on `textus build`. No more hand-mirrored `agents/` / `skills/` / `commands/` directories.
|
|
78
78
|
- **Stable identity (`uid:`).** 16-char hex, auto-minted on first `put`, preserved across writes and moves. `textus key mv old.key new.key` renames in place — uid survives, audit row records `from_key`, `to_key`, `uid`. Reorganising a tree no longer breaks references.
|
|
79
79
|
- **Strict key grammar.** `/^[a-z0-9][a-z0-9-]*$/`, max 8 segments × 64 chars. `textus key migrate --dry-run|--write` rewrites existing stores with illegal segments deterministically.
|
|
80
|
-
- **`textus intro`.** One-shot store orientation: zones with writers + purposes, entry families with schemas and publish targets, loaded
|
|
81
|
-
- **`textus doctor`.** Health check across 9 categories: missing schemas/templates, broken
|
|
80
|
+
- **`textus intro`.** One-shot store orientation: zones with writers + purposes, entry families with schemas and publish targets, loaded hooks, write flows per role, the full CLI verb table. The boot signal for any agent — one tool call and it knows your store.
|
|
81
|
+
- **`textus doctor`.** Health check across 9 categories: missing schemas/templates, broken hooks, illegal nested keys, sentinel drift, audit log readability, unowned schema fields, schema violations, and missing manifest files. Returns `ok: true` only when nothing is wrong; warnings and info don't flip the bit.
|
|
82
82
|
- **Actionable hints on every error.** `UnknownKey` carries ranked "did you mean" suggestions. `WriteForbidden` names the role that *would* be allowed. `BadFrontmatter` tells you exactly what to rename. Printed to stderr alongside the JSON envelope on stdout.
|
|
83
83
|
|
|
84
84
|
Symlink-mode publish was removed; publish is `FileUtils.cp` + sentinel. Sentinels for published files live under `.textus/sentinels/<target_rel>.textus-managed.json` so consumer directories stay clean. Legacy sibling sentinels auto-migrate on next publish.
|
|
@@ -91,7 +91,7 @@ All verbs accept `--format=json` and return the envelope defined in SPEC §8. Wr
|
|
|
91
91
|
|
|
92
92
|
| Verb | Purpose |
|
|
93
93
|
|---|---|
|
|
94
|
-
| `intro` | Store orientation: zones, entries,
|
|
94
|
+
| `intro` | Store orientation: zones, entries, hooks, write flows, CLI map |
|
|
95
95
|
| `list [--prefix=K] [--zone=Z]` | Enumerate keys |
|
|
96
96
|
| `where K` | Resolve a key to its filesystem path |
|
|
97
97
|
| `get K` | Full envelope (frontmatter, body, uid, etag, format) |
|
data/SPEC.md
CHANGED
|
@@ -365,7 +365,7 @@ Reducers are RPC hooks on the `:reduce` event. See §5.10.
|
|
|
365
365
|
|
|
366
366
|
### 5.10 Hooks
|
|
367
367
|
|
|
368
|
-
textus has a single
|
|
368
|
+
textus has a single hook verb: `Textus.hook(event, name, **opts) { ... }`. The EVENTS table below defines every extension point. Files in `.textus/hooks/*.rb` are `load`ed at `Store#initialize` in lexical order.
|
|
369
369
|
|
|
370
370
|
| Event | Mode | Args | Return | Failure |
|
|
371
371
|
|----------|---------|-----------------------------------|---------------|---------|
|
data/lib/textus/doctor.rb
CHANGED
|
@@ -67,7 +67,7 @@ module Textus
|
|
|
67
67
|
rescue StandardError => e
|
|
68
68
|
out << fail_issue(name, code: "doctor_check.failed",
|
|
69
69
|
message: "#{e.class}: #{e.message}",
|
|
70
|
-
fix: "fix the
|
|
70
|
+
fix: "fix the :check hook in .textus/hooks/")
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
out
|
data/lib/textus/init.rb
CHANGED
|
@@ -31,7 +31,7 @@ module Textus
|
|
|
31
31
|
File.write(File.join(target_root, "hooks", "README.md"), <<~MD)
|
|
32
32
|
# Hooks
|
|
33
33
|
|
|
34
|
-
Drop one Ruby file per hook. All
|
|
34
|
+
Drop one Ruby file per hook. All hooks register through one DSL.
|
|
35
35
|
Every handler receives `store:` as its first kwarg, then event-specific args.
|
|
36
36
|
|
|
37
37
|
```ruby
|
data/lib/textus/intro.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Textus
|
|
|
2
2
|
# Read-only "what's in this store and how do I use it" envelope.
|
|
3
3
|
# A single call gives an agent the working model of a textus-managed
|
|
4
4
|
# project: zones and their write authority, entries and their flags,
|
|
5
|
-
# registered
|
|
5
|
+
# registered hooks, write flows, and the CLI verb catalog.
|
|
6
6
|
#
|
|
7
7
|
# Intro is side-effect-free.
|
|
8
8
|
module Intro
|
|
@@ -53,7 +53,7 @@ module Textus
|
|
|
53
53
|
"store_root" => store.root,
|
|
54
54
|
"zones" => zones_for(store),
|
|
55
55
|
"entries" => entries_for(store),
|
|
56
|
-
"
|
|
56
|
+
"hooks" => hooks_for(store),
|
|
57
57
|
"write_flows" => WRITE_FLOWS.dup,
|
|
58
58
|
"cli_verbs" => CLI_VERBS.map(&:dup),
|
|
59
59
|
"docs" => { "spec" => "SPEC.md", "example" => "examples/claude-plugin/" },
|
|
@@ -87,7 +87,7 @@ module Textus
|
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
def self.
|
|
90
|
+
def self.hooks_for(store)
|
|
91
91
|
reg = store.registry
|
|
92
92
|
sections = {}
|
|
93
93
|
Hooks::Registry::EVENTS.each do |event, spec|
|
data/lib/textus/store.rb
CHANGED
|
@@ -42,12 +42,12 @@ module Textus
|
|
|
42
42
|
@bus = Hooks::Dispatcher.new(audit_log: audit_log)
|
|
43
43
|
@registry = Hooks::Registry.new(dispatcher: @bus)
|
|
44
44
|
@schemas = {}
|
|
45
|
-
|
|
45
|
+
load_hooks
|
|
46
46
|
@reader = Reader.new(self)
|
|
47
47
|
@writer = Writer.new(self)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def
|
|
50
|
+
def load_hooks
|
|
51
51
|
Textus.with_registry(@registry) do
|
|
52
52
|
Hooks::Builtin.register_all
|
|
53
53
|
dir = File.join(@root, "hooks")
|
|
@@ -57,7 +57,7 @@ module Textus
|
|
|
57
57
|
begin
|
|
58
58
|
load(f)
|
|
59
59
|
rescue StandardError, ScriptError => e
|
|
60
|
-
raise UsageError.new("failed loading
|
|
60
|
+
raise UsageError.new("failed loading hook #{File.basename(f)}: #{e.class}: #{e.message}")
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
data/lib/textus/version.rb
CHANGED