<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pantograph.git/src/subcommand.zig, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>https://code.tjp.lol/pantograph.git/atom?h=main</id>
<link rel='self' href='https://code.tjp.lol/pantograph.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/'/>
<updated>2026-07-05T22:23:49Z</updated>
<entry>
<title>big cli/tui gaps project</title>
<updated>2026-07-05T22:23:49Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-07-04T15:50:12Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=f759f149377942c4e04802c45162cda1c9bfb2b3'/>
<id>urn:sha1:f759f149377942c4e04802c45162cda1c9bfb2b3</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Load extensions via unified policy, entry/activate, rocks and paths</title>
<updated>2026-07-01T21:37:04Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-07-01T21:36:20Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=800b2c4b6115845f6bf15d90484b3e80e81a606f'/>
<id>urn:sha1:800b2c4b6115845f6bf15d90484b3e80e81a606f</id>
<content type='text'>
Replace the split [tools]/[extensions] config sections and the two-stage
load gate with a single model:

- [extensions] is now one policy resolved across all layers. Rules from
  every layer are kept (not clobbered) and resolved by last-match-wins
  after sorting by (layer, glob specificity, deny-last), so a base layer
  can carve one name out of an otherwise-denied group and a higher layer's
  broad rule still wins. Default is allow; whitelist via deny=["**"].
- Registration is deferred: a source returns an entry {name, activate}
  (or a list, or the sugar tool table), is always eval'd side-effect-free,
  and only permitted names get activate()d. Identity is the declared name,
  not the filename. Collapses the old pre/post-load two-stage gate.
- The loader runs two passes (eval -&gt; shadow -&gt; filter -&gt; activate) with
  precedence project&gt;user&gt;base and, within a layer, rocks&lt;paths&lt;dir.
- extensions.paths adds extra scan dirs; extensions.rocks loads luarocks
  packages as extension sources (require-as-entries). Startup installs
  only missing rocks (no per-launch network hit); panto update force-
  (re)installs every configured rock.

deny is a feature toggle, not a security boundary: rocks is where registry
code enters, so the pin list is the trust boundary. Rock integrity
(first-party GPG signing + --verify) is designed but not yet wired; until
then rocks pins which version, not which bytes.

Breaking: [tools] is removed; extensions must return entries. Built-in
tools and the wc example keep working via the sugar tool form.
</content>
</entry>
<entry>
<title>ponytail simplifications to panto cli and lua extensiosn</title>
<updated>2026-06-23T16:53:26Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-23T15:38:23Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=69a1ee138bb78ad4663fe2d9e58678f7b0d07b74'/>
<id>urn:sha1:69a1ee138bb78ad4663fe2d9e58678f7b0d07b74</id>
<content type='text'>
</content>
</entry>
<entry>
<title>models.dev list validation against actual provider's /models</title>
<updated>2026-06-16T02:52:24Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-16T02:51:54Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=8206642d3a1736aaf928a5b9a732e747f5294228'/>
<id>urn:sha1:8206642d3a1736aaf928a5b9a732e747f5294228</id>
<content type='text'>
</content>
</entry>
<entry>
<title>model registry sync via models.dev</title>
<updated>2026-06-15T22:15:10Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-15T22:14:55Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=d9d4131cb321a9ce29b000cd7aed8ced9a18efc1'/>
<id>urn:sha1:d9d4131cb321a9ce29b000cd7aed8ced9a18efc1</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auth: flatten [auth.&lt;name&gt;] config + ${...} substitution</title>
<updated>2026-06-15T21:08:32Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-13T20:24:31Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=20e6e08a42240aef0b36ecf627cbcde921912071'/>
<id>urn:sha1:20e6e08a42240aef0b36ecf627cbcde921912071</id>
<content type='text'>
Collapse the auth schema: infer `type` from keys, replace key/key_env_var with
a single `key` (resolved via substitution), flatten the exchange to flat
`exchange_*` keys, and drop the auth-level headers tables in favor of reusing
the provider's `extra_headers` on the auth HTTP calls. Add `${sibling}` and
`${env:VAR}` substitution over auth values (GitHub Enterprise = set `domain`).
Restore api_key-empty → provider-drop. Update default config, docs, and tests.
</content>
</entry>
<entry>
<title>auth: CLI auth manager + `panto auth` subcommands</title>
<updated>2026-06-15T21:08:32Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-13T18:09:00Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=73324a15aa524cf75deebc4172f5a1f0d0051bc6'/>
<id>urn:sha1:73324a15aa524cf75deebc4172f5a1f0d0051bc6</id>
<content type='text'>
Add src/auth_manager.zig (turn-time resolution: load→login→refresh→exchange→
build credential, patch live config) and `panto auth status|login|logout`
subcommands with a line-based device-code presenter. Add config_file.loadFromString.
</content>
</entry>
<entry>
<title>libpanto API fixes</title>
<updated>2026-06-11T15:23:28Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-11T15:08:42Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=e2477f7d2d2a4eab870a2bd61534cfd146907915'/>
<id>urn:sha1:e2477f7d2d2a4eab870a2bd61534cfd146907915</id>
<content type='text'>
- FSJSONLStore: don't require `cwd`, instead panto CLI provides it in
  the session metadata
- Lua: expose the `SessionStore` interface and the `FSJSONLStore` and
  `NullStore` implementations
- C: use idiomatic `const char *` for incoming strings
- C: expose the `FSJSONLStore` and `NullStore` implementations
</content>
</entry>
<entry>
<title>Migrate panto CLI onto the public.zig surface</title>
<updated>2026-06-07T17:42:41Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-07T17:42:41Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=11818552dad254649af012df3b4277633943d2b6'/>
<id>urn:sha1:11818552dad254649af012df3b4277633943d2b6</id>
<content type='text'>
Move the CLI off the internal libpanto module namespaces onto the curated
public API: data-type aliases (Config family, Message/MessageRole/
effectiveSystemBlocks, Event, Pricing/PricingRegistry, the session seam,
FileSystemJSONLStore, ContentBlockType), process lifecycle (panto.init/
deinit), and ResultParts.fromText/fromTextOwned/deinit in place of the
freestanding textResult/ownedTextResult/freeResultParts.

The CLI remains on two flagged internal namespaces, panto.agent and
panto.conversation: it is a deep embedder that drives the loop below the
curated Agent/Conversation facades (system-prompt seeding through the
agent, compaction_system_prompt, the open_stream_fn test seam, standalone
Conversation values, compactAndPersist). These stay re-exported from
public.zig as a documented deep-embedder escape hatch; trimming the
transitional block removed every other internal re-export.
</content>
</entry>
<entry>
<title>R2: redesign session store with wire-format identity</title>
<updated>2026-06-07T17:35:49Z</updated>
<author>
<name>t</name>
<email>t@tjp.lol</email>
</author>
<published>2026-06-07T17:35:49Z</published>
<link rel='alternate' type='text/html' href='https://code.tjp.lol/pantograph.git/commit/?id=b14859b9726185ab873356390068e887b7f486d3'/>
<id>urn:sha1:b14859b9726185ab873356390068e887b7f486d3</id>
<content type='text'>
Replace the single-session SessionManager seam with a directory-backed
catalog. session_manager.zig -&gt; file_system_jsonl_store.zig; the old
machinery becomes internal SessionFile, and a new FileSystemJSONLStore
implements the redesigned SessionStore vtable (create/list/resolve/latest/
load/appendMessages) minting Session/SessionInfo handles.

Session logs now record wire-format provider identity
({api_style, base_url, model, reasoning}) instead of a single provider
string or CLI aliases; no api_key material is ever stored. Disk* content
types renamed Stored*; the rich audit-oriented write record is
PersistentMessage (in-memory Message + WireIdentity + provenance).

Agent.init now takes a Session; persist_provider/persist_model display
strings deleted (banner stays alias-based, resume picks default model).
Message.metadata round-trips. Dangling-prompt recovery dropped. CLI
migrated to the catalog store for run/resume/list. Clean break, no version
bump (old logs wiped).
</content>
</entry>
</feed>
