Skip to content

guard: dynamically-ish typed userspace proof of concept#5668

Open
Fang- wants to merge 20 commits into
developfrom
m/guardian
Open

guard: dynamically-ish typed userspace proof of concept#5668
Fang- wants to merge 20 commits into
developfrom
m/guardian

Conversation

@Fang-
Copy link
Copy Markdown
Member

@Fang- Fang- commented Apr 1, 2026

/lib/guard attempts to detect mark-mismatching data at compile-time. We do this by loading in our marks and replacing the $cages in %poke and %fact cards with a $rail type, which is a %$ over all the imported marks.

This approach has some advantages:

  • Compile-time mark/type-validation of cages! Can easily do this for pokes, facts, also +on-peek results.
  • It's just functions. Take them on/off as relevant. No agent wrapper needed.
  • Keeps marks warm. (But does that keep conversions warm?)
    • Moot anyway once "build all /mar files" gets enabled...
  • You get an untyped/unsafe "out" but you must explicitly write %unsafe.

Draft because this is incomplete (only chat agent uses it rn) and wants some additional questions answered.

  • Ergonomics around helper libraries (logging, /lib/dm) is a bit awkward. Maybe we can make nicer utilities.
  • Is there some way to combine this with discipline-style API specification?
  • Do we just want to chuck every /mar file from our desk into /lib/guardian? You can also imagine per-agent lib files for this, and you may need to do that if you also specify API details, but rn we could get away with a single (huge) file.
    • Doing so would worsen our "changing one file recompiles everything" problem though. But maybe that's a price we can live with for what we gain.

Notably this already found a bad type in +refs:migrate. (;

@Fang- Fang- requested review from arthyn and mikolajpp April 1, 2026 21:42
@blacksmith-sh

This comment has been minimized.

Copy link
Copy Markdown
Member

@arthyn arthyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm this is the beginning of ruby on rails for gall

Fang- added 2 commits April 17, 2026 15:05
Adds a +groups!rail generator, which generates a file, intended to live
at /lib/rail.hoon, which imports all the desk's marks and incorporates
them into the $rail type and its helpers.
Many marks didn't compile into proper mark cores. Here, we make a bunch
of changes to correct this.
@Fang- Fang- mentioned this pull request Apr 22, 2026
3 tasks
Fang- added 5 commits April 29, 2026 09:29
The discipline mark set lets us convert vases into well-typed rails.
(But does not take away crash risk due to poorly typed vases.) We make
chat use it right away to deduplicate its mark list.
The generator contains a list of marks marked as non-strict for the
purpose of mark-type-changed checking.

We also add a conversion from cage to rail, paving the way for further
guardian work.
This makes the argument contain rails instead of cages, for better
compile-time type safety. Using this you cannot unpack a vase from a
cage into a type different from that of its mark.

Applies both to /app/chat, athough +on-agent doesn't do much there: chat
doesn't do subscriptions, so we don't handle fact cages anyway.
Stubs out some of the hooks stuff, whose types have been drifting.
Copy link
Copy Markdown
Member Author

@Fang- Fang- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready enough for review.

Some stuff highlighted for extra-care review. There was more here, but #5764 resolved most of it!


Note about the discipline stuff: I'm not a fan. Needing to explicate every mark that should be non-strict-ed (in the rail generator) is probably not the modality we want.

With some rejiggering we could probably move back to agents specifying the marks which they do want strict-checked, whilst making /lib/discipline pull in the mark types from the /lib/rail instead of depending on agents to pass them.

afaic I'll consider that an outstanding TODO, but I'm open to hearing feedback/ideas.


Note about other libraries: lib-negotiate and lib-subscriber are quite low impact wrt this. lib-logs is a bit rougher, but I'm also hesitant to make that always produce type-safe cards. afaic the current situation is fine, especially if we clean the local patches up just a tad. But open to feedback.

Comment thread desk/mar/foreigns-2.hoon
@@ -0,0 +1,14 @@
/- gv=groups-ver
/+ j=groups-json
|_ =foreigns:v10:gv
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: this was missing even though groups was using it for its latest foreigns scry endpoint. Correct to add this, yes?

Copy link
Copy Markdown
Collaborator

@mikolajpp mikolajpp May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should have been included! We should also remember to update the discipline while we are at it; looks like discipline for the singular foreign-2 mark is also missing.

%groups
=/ =cage group-action-4+!>(`a-groups:v7:gv`a-groups.effect)
(emit [%pass /hooks/effect %agent [our.bowl %groups] %poke cage])
=/ =rail !! ::group-action-4+`a-groups:v7:gv`a-groups.effect ::REVIEW
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the other nearby cases suggest hook implementation has drifted wrt the types. @arthyn confirmed. We'll probably want to clean these up somehow. Could be trivial, I haven't given it a serious try yet.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two main problems with hooks is that (1) they are not in real use and (2) we have never sat down to describe what should happen when we update hook type dependencies. I think they should probably use current types always and attempt to recompile when types change. The proper solution here is out of scope, but we should somehow make the types consistent so it is still possible to use hooks going forward.

Comment thread desk/app/channels.hoon
@Fang- Fang- marked this pull request as ready for review May 8, 2026 21:54
claude[bot]

This comment was marked as low quality.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b46ff7916c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

%groups
=/ =cage group-action-4+!>(`a-groups:v7:gv`a-groups.effect)
(emit [%pass /hooks/effect %agent [our.bowl %groups] %poke cage])
=/ =rail !! ::group-action-4+`a-groups:v7:gv`a-groups.effect ::REVIEW
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove crash stubs from non-channel hook effects

In run-hook-effects, the %groups, %dm, %club, and %contacts branches bind rail to !!, which always crashes before emitting the poke. Any hook effect of those kinds will therefore terminate this path and fail to dispatch the downstream action, breaking hook-driven automations for those targets.

Useful? React with 👍 / 👎.

@Fang- Fang- requested a review from arthyn May 9, 2026 08:46
Copy link
Copy Markdown
Collaborator

@mikolajpp mikolajpp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all library files. Answered the questions.
The only substantial question I have thus far is regarding not having a dedicated mark exclusion list in the code generator.

We should also accompany, or follow this PR with a short documentation about this pattern (a few terse paragraphs, with a few code samples) , given that it substantially alters the usual gall agent api. This is not a blocker for the release obviously, but would be good to have to aid models in comprehending our codebase.

Comment thread desk/lib/rail.hoon
Comment on lines +10 to +11
:: specifies a $rail type, a "typed $cage" containing all the desk's marks
:: and a +de-rail helper for turning that back into a $cage.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what sense the $rail type is a "typed $cage"? It would rather seem be a typed $page. The %unsafe variant carries a vase, but all others just carry simple values, not vases.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it's more nuanced to say "statically typed $cage"?

The thinking is that the $rail gets put in all the places we would otherwise put $cages (pokes, facts), and that they're now typed in such a way (dynamically) that the compiler can see the types. Vases always have a single (static) type. They contain the information about the type of the data, but not in a way that's legible to the compiler.

Comment thread desk/lib/guard.hoon
Comment thread desk/lib/guardian.hoon Outdated
Comment thread desk/gen/rail.hoon Outdated
Comment on lines +3 to +4
::TODO investigate adding a "meta-build" for rune that evaluates the file
:: to obtain a hoon ast, which it then compiles into the result
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
::TODO investigate adding a "meta-build" for rune that evaluates the file
:: to obtain a hoon ast, which it then compiles into the result
::TODO investigate adding a "meta-build" ford rune that evaluates the file
:: to obtain a hoon ast, which it then compiles into the result

Comment thread desk/gen/rail.hoon Outdated
Comment thread desk/gen/rail.hoon
Comment thread desk/gen/rail.hoon
%activity-summary-1
%activity-update
%activity-update-1
%aqua-effect
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not ideal that we have to care about the marks that are not going to be used in any of our agents, but I understand this is because we scan all the marks in the desk, and thus need to specify all exceptions to allow for future changes.

This makes me think whether we should come up with a similar wrapper for threads, but this would be out of scope and rather low-priority, since historically we have not such problems with threads.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One other alternative with perhaps better semantics would be to have a mark exclusion list for marks that are not of interest, which there are some.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have to care about the marks that are not going to be used in any of our agents

We could consider removing them from our desk. %aqua-effect for example is only included here (and in the generated output) because we have a /mar/aqua/effect.hoon in the groups desk distribution.

Having a mark exclusion list would let us clean those out of the library before even cleaning up desks. (We certainly don't want to do desk cleanup while the library still depends on those marks!)

Comment thread desk/gen/rail.hoon
Comment thread desk/app/chat.hoon Outdated
Copy link
Copy Markdown
Collaborator

@mikolajpp mikolajpp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reviewed agent integrations. Looked more closely at channels-server.hoon, and skimmed over the other agents. Any mistakes or omissions would cause certain compile errors, so while changes are extensive they only amount to replacing cages with rails and consequences.

It seems like these changes should not cause any failures in any of the tests, but based on the logs the desk fails to upgrade. We should investigate it locally before merging.

=? old ?=(%0 -.old) (state-0-to-1 old)
=? old ?=(%1 -.old) (state-1-to-2 old)
=? cor ?=(%2 -.old) (emit %pass /trim %agent [our.bowl %chat] %poke %chat-trim !>(~))
=? cor ?=(%2 -.old) (emit %pass /trim %agent [our.bowl %chat] %poke %unsafe %chat-trim !>(~))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use unsafe here because we don't have a corresponding mark?
Probably fine, given that this is historical. If gall will start to enforce marks on local pokes we will be able to easily find these cases with guardian.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

Fang- added 2 commits May 12, 2026 16:40
@Fang- Fang- changed the title guardian: dynamically-ish typed userspace proof of concept guard: dynamically-ish typed userspace proof of concept May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants