<<~YAML
version: textus/3
zones:
- { name: identity, write_policy: [human], read_policy: [all] }
- { name: working, write_policy: [human, agent, runner], read_policy: [all] }
- { name: intake, write_policy: [runner], read_policy: [all] }
- { name: review, write_policy: [agent, human], read_policy: [all] }
- { name: output, write_policy: [builder], read_policy: [all] }
entries:
- { key: identity.self, path: identity/self.md, zone: identity, schema: null, owner: human:self }
- { key: working.notes, path: working/notes, zone: working, schema: null, owner: human:self, nested: true }
YAML
<<~MD
# Hooks
Drop one Ruby file per hook. All hooks register through one DSL.
Files anywhere under `.textus/hooks/` (including subdirectories) are loaded at
startup in alphabetical order by full path. Subdirectory names are organizational
only — the registered event and name come from the DSL call, not the file path.
## DSL
```ruby
Textus.on(:resolve_intake, :my_source) do |config:, args:, **|
{ _meta: { "last_refreshed_at" => Time.now.utc.iso8601 }, body: "…" }
end
Textus.on(:transform_rows, :my_source) { |rows:, **| rows.map { |r| r.merge(processed: true) } }
Textus.on(:validate, :my_check) { |store:, **| [] }
Textus.on(:entry_put, :my_listener, keys: ["working.*"]) { |key:, envelope:, **| }
# Run a side-effect every time textus writes a file to your repo:
Textus.on(:file_published, :notify) do |key:, target:, **|
warn "wrote \#{target} (from \#{key})"
end
```
The intake handler above is paired with a manifest entry plus a
top-level `rules:` block for freshness (ttl/on_stale live in
rules, not in the entry):
```yaml
entries:
- key: intake.foo
path: intake/foo.md
zone: intake
intake:
handler: my_source
rules:
- match: intake.foo
refresh:
ttl: 10m
on_stale: timed_sync # warn | sync | timed_sync (default: warn)
```
Events: :resolve_intake, :transform_rows, :validate (rpc — return value used)
:entry_put, :entry_deleted, :entry_refreshed, :entry_renamed,
:build_completed, :proposal_accepted, :proposal_rejected,
:file_published, :store_loaded,
:refresh_started, :refresh_failed, :refresh_backgrounded (pub-sub — return discarded)
See SPEC.md §5.10 for the full table.
MD