EXPERIMENT: the capability tier becomes shipped policy plus a query

Capability differs from prohibits_outside in one way that matters: a utility
program cannot be trusted to declare its own restrictions, because it would
declare none. So the policy comes from OUTSIDE the program -- it ships with the
language as data, editable without a compiler release.

  tools/check/capabilities.rel   18 names that were string literals in codegen
  tools/check/capabilities.sh    the query that decides

PREDICTIONS AND RESULTS
  P1 codegen emits kind + call graph, drops the 4 name tests   TRUE  zero #errors
  P2 the 18 literals become a data file                        TRUE
  P3 the checker catches capability violations                 TRUE  exit=1
  P4 codegen drops ~76 lines                                   TRUE  4963 -> 4881
  P5 below the 4661 baseline                                   FALSE ~+230

TWO DEFECTS THE HARNESS FOUND THAT READING WOULD NOT HAVE

1. Calls inside main became invisible. cg_fn returns early for main -- C
   provides its own -- so hooking the recording there left every call in main
   unrecorded: a blind spot exactly where a program does its work. The old
   cap_check_call ran from cg_expr and did see main. Moved the recording to
   cg_expr.

2. Caller attribution was stale. __cg_current_fn kept whatever cg_fn set last,
   so a violation in main was reported against the previously emitted function.
   The test still PASSED, because the violation was detected -- only the name
   was wrong, and a diagnostic naming the wrong fn is worse than none. Fixed at
   all three main-emission sites; the first patch missed two because the live
   path is codegen_streaming.

98/98 native, 7/7 + 4/4 + 5/5 integration, fixpoint ok.
This commit is contained in:
bigmerge
2026-08-17 09:16:36 -05:00
parent 60c07ad784
commit c2d9596e76
4 changed files with 100 additions and 88 deletions
+18
View File
@@ -0,0 +1,18 @@
# capabilities.rel — the capability policy, as shipped data.
#
# A program's tier bounds what it may call. This is policy that comes from
# OUTSIDE the program: a utility cannot be trusted to declare its own
# restrictions, because it would declare none. So unlike prohibits_outside,
# which a program declares about itself, this ships with the language and is
# editable without a compiler release.
#
# Previously: four functions and eighteen string literals inside codegen.el.
#
# <kind> prohibits_within <comma-separated names>
service prohibits_within llm_call_agentic,llm_register_tool,dharma_emit,dharma_field
utility prohibits_within dharma_connect,dharma_send,dharma_activate,dharma_emit,dharma_field,dharma_strengthen,dharma_relationship,dharma_peers
utility prohibits_within llm_call,llm_call_system,llm_call_agentic,llm_vision,llm_register_tool,llm_models
# cgi is unrestricted: self-formation is what a cgi program is for.
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# capabilities.sh — enforce the capability tier as a QUERY over emitted
# relations plus a shipped policy file. The compiler records the program's kind
# and its call graph; deciding what that tier may call is not an emitter's job.
set -uo pipefail
REL="${1:?usage: capabilities.sh <relations-file> [policy]}"
POLICY="${2:-$(dirname "${BASH_SOURCE[0]}")/capabilities.rel}"
[ -f "$REL" ] || exit 0
KIND=$(grep -m1 '^program calls is_kind:' "$REL" | sed 's/.*is_kind://')
[ -n "$KIND" ] || KIND=utility
V=0
while read -r kind rel names; do
[ "$kind" = "$KIND" ] && [ "$rel" = "prohibits_within" ] || continue
IFS=',' read -ra NAMES <<< "$names"
for n in "${NAMES[@]}"; do
while read -r caller _ callee; do
[ "$callee" = "$n" ] || continue
printf "capability violation: '%s' programs may not call '%s' (called from %s)\n" "$KIND" "$n" "$caller"
V=$((V+1))
done < <(sort -u "$REL")
done
done < <(grep -v '^#' "$POLICY" | grep -v '^[[:space:]]*$')
[ "$V" -eq 0 ] && echo "capabilities: clean ($KIND)"
exit "$V"