Commit Graph
18 Commits
Author SHA1 Message Date
kyleandClaude Opus 5.5 aafc1d1c28 P5a review: outlines from named destinations; pool race; fast over-limit; revalidation under the limiter; Accept pdf
- pdftext/outline: resolve named destinations through the catalog /Dests and the /Names /Dests
  tree, resolve indirect /Dest, /A and /Title, and treat reader.Null (what Dict.Get returns for
  a missing key) as absent. Before this every LaTeX and Acrobat PDF had an empty outline.
  pdftest gains NamedDests; TestOutlineNamedDestinations.
- api: pool() always goes through its Once (data race on concurrent first use);
  TestDefaultPoolConcurrentFirstUse. Revalidation of a stale cache entry counts against the
  caller/host limit.
- pdftext/runner: output over MaxText kills the child at once instead of waiting for the
  deadline; TestRunnerTooMuchTextFailsFast.
- fetch: Accept includes application/pdf;q=0.8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 04:48:17 -07:00
kyleandornith-1.5-35b-a3b 09f738bcac api: PDF cache with revalidation; pages and grep; refuse questions on very long documents
Answer extracted PDFs from the document cache: fresh for PDFTTL, then a
conditional GET (304 reuses the stored text, a 200 is extracted and stored
without a second GET). Store after extraction with the response hash, ETag,
fetch time and extracted pages. Route pages/grep through pdfdoc.Options with
400s for bad ranges and non-PDFs, and refuse a question when the document
exceeds PDFMaxQuestionChunks with a pointer to grep and pages.

Co-Authored-By: ornith-1.5-35b-a3b <ornith-1.5-35b-a3b@llama.cpp.invalid>
2026-09-26 04:23:21 -07:00
kyleandornith-1.5-35b-a3b 93ec310113 api: serve PDFs — extraction in the child under the pool, full text or map, errors
Route "pdf" through clean.Kind in doFetch/cleanFetched: extract under the pool
(keyed by caller class + document hash, one per caller), map the five pdftext
errors plus a pool panic to 422, ErrBusy to 503+Retry-After 10, ErrCallerBusy to
429, and answer with the whole text or the map. Adds RetryAfter to fetch.Error
and the matching header. No cache, pages or grep — those are task 07.

Co-Authored-By: ornith-1.5-35b-a3b <ornith-1.5-35b-a3b@llama.cpp.invalid>
2026-09-26 04:04:11 -07:00
kyleandClaude Opus 5.5 cfde35397a P5a plan: PDF documents — seven Ornith tasks with acceptance tests first
docs/plans/p5a: 01 kind+fetch limits, 02 pdftext child + runner, 03 dcache PDF tables,
04 pdfpool, 05 pdfdoc render (map/pages/grep), 06 api, 07 digest citations, metrics, CLI,
skill, unit, README. Given tests compile against a panic-only skeleton and fail there for the
intended reasons; PDFs for tests are built by internal/pdftest (given), plus two qpdf-encrypted
fixtures.

Owner changes for the run: vendor go-pdfkit/extract v0.3.0 + reader v0.6.0 (pinned via
tools.go until task 02); AGENTS.md, tools/run-plan.sh (enforces a Co-Authored-By trailer for
the model), docs/implementer-log.md, `make gate`; gofmt (whitespace) on clean.go and guard;
TestUnsupportedType uses a zip now that PDFs are supported; requestDeadline 90→210 s and
writeTimeout 120→240 s for the PDF path's worst case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 20:47:38 -07:00
kyle 4372673184 p2.7: prometheus /metrics
Default GET /metrics is Prometheus text; JSON stays at /metrics.json
and ?format=json. :8443 needs the metrics caller bearer; loopback
stays open. Restricted callers have no per-caller series and no
tavily:restricted gauge.
2026-09-23 21:49:38 -07:00
kyle 429f6b207e p3: tavily parse errors degrade; retry DNS on search
A 200 with a bad Tavily body is tavily: error, not an empty success
that would cache for the hour. Upstream clients stay in the source
list if DNS is down at boot and retry the pin on Search; /healthz
lists them as unresolved until a pin lands.
2026-09-23 12:22:31 -07:00
kyle d7873403ff p3: search API, pinned sources, cache, CLI
POST /v1/search and /v2/search fan in SearXNG, Brave LLM Context, and
Tavily from config-fixed endpoints. Public sources refuse private A
records; SearXNG is a loopback-only client, not the fetch guard.

Cache keys include caller class. Restricted callers search like the
fleet; logs omit query, hosts, URLs, and upstream errors. Degraded
results are not stored. Tavily sends search_depth=basic and drops
answer. Missing keys surface in /healthz.

Default-on sources stay off until the bake-off. Query harvest is not
in this commit.
2026-09-23 12:17:51 -07:00
kyle 3687636ed7 p2.6: partition dcache by caller class; pin restricted workspace
Digest, chunk-embed, and question-embed keys include fleet|restricted so
a fleet caller cannot observe a restricted cache hit. Digest.Run takes
the class from permit_restricted.

A permit_restricted caller whose keys.toml workspace is not
guardian-star is refused at Search (no Honcho request) and flagged at
serve start and keys reload.

docs: P3 restricted callers search like the fleet; cache/logs isolate.
2026-09-23 11:51:39 -07:00
kyle 7be4ed1d43 p2.5: redact reason/err for permit_restricted logs
Guard messages embed the hostname (resolve <host>, no addresses for
<host>). Restricted callers now log a coarse reason class and err=-.
Test dumps slog records and forbids the hostname anywhere in them.

docs: P3 review — fail-closed search, cache class, public dialer
2026-09-23 11:47:37 -07:00
kyle 85113f9c0b p2.5: log host=- for permit_restricted callers
Scrape, fetch, refused, fetch-failed, and internal lines redact the
host for callers in context.permit_restricted. final_url stays in the
response. Test captures slog records, not the journal.
2026-09-23 11:40:45 -07:00
kyle e36da19f57 p2.4: restricted workspace for permitted callers
guardian-star context is allowed only when the authenticated caller is in
permit_restricted and mapped to that workspace. Fleet callers remapped to it
still refuse. CLI client.toml: SIFT_CLIENT, then $HERMES_HOME/sift, then ~/.config.
2026-09-23 08:33:58 -07:00
kyle 16a7d678d3 p2.1: honcho-embed, wayback http/204, memento, keys owner
Embed requests send dixie.embed_model (default honcho-embed).
Wayback accepts http://web.archive.org, rewrites to https, skips
non-200 closest.status. Memento-Datetime is parsed as an HTTP date
and future/garbage values become empty snapshot_at. keys add writes
via temp+fchown/chmod/rename so root does not clobber keys.toml.
Digest fallback is capped at the 6k-token budget.
2026-09-23 02:41:46 -07:00
kyle 2db001e0d7 p2: 120s write timeout and flags after the URL
WriteTimeout 30s was cutting digest mid-flight (queue+fetch+digest)
and tailscale then 502'd. 120s write, 90s handler deadline.
sift fetch URL --question now parses; extra positionals error.
2026-09-23 00:28:59 -07:00
kyle ff87a04f94 p2: fence document tags, atomic fleetctx, harden workspace
Neutralise </document and <document in page text. Counters are
atomic.Uint64. Workspace names are [A-Za-z0-9_-] and PathEscaped;
foreign workspace_id rows are dropped. Wayback closest.url must be
https://web.archive.org. archive.today snapshot_at is Memento-Datetime
or null.
2026-09-23 00:01:04 -07:00
kyle 2f9d3d97e6 p2: digest with in-sift FIFO, SQLite caches, Honcho context, recover
Dixie is capped (max_inflight 2, queue_depth 8, queue_wait 20s) and
never queued on llama-server. Streaming chat, thinking off, 45s
fallback to clean. Digest and chunk-embedding caches are
content-addressed SQLite (Honcho context is not cached). Recover
uses the guarded Fetcher. guardian-star is refused in code.
2026-09-22 23:54:49 -07:00
kyle 447842f860 p1.1: dynamic self-IP deny (DDNS/trace, keep previous, atomic swap)
Discover WAN via ddns:<host> then trace:<url> before listen. Persist to
self_ip.json. Previous addresses stay denied for keep_previous. Failure
keeps the last known set. /healthz reports age and source.
2026-09-22 22:59:08 -07:00
kyle 8e3a6cd339 p1: cap jq output, log refusals, fail contract without SDK
jq results are bounded (10k items / output cap) and return 400 when
exceeded. 401/403 log caller, host, and reason. make contract exits 1
unless firecrawl-py is present (SIFT_CONTRACT_SKIP_SDK=1 to skip).
2026-09-22 22:02:38 -07:00
kyle 9444a35322 p1: /v2/scrape, /v1/fetch, auth, CLI, contract tests
Single Fetcher.Fetch on the Guard that holds DenyPrefixes. skipTlsVerification
is ignored. No 502. keys add writes the secret only to --out. Release binary
has no -test-allow-prefix.
2026-09-22 21:54:01 -07:00