Repository navigation
Conversation
|
This pull request's description says it closes #149, which is on the project roadmap. When it merges, GitHub closes that issue and the roadmap counts it as delivered. Please confirm the change delivers the whole issue before merging. |
5e2b1ce to
931f598
Compare
rocklambros
left a comment
There was a problem hiding this comment.
Raghuvar, first wins is what docs/concepts/intent.md:9 already says. Your schema edits change only description text, so the wire shape stays the same (I compared both files). The merged tree on integration 19b1197 passes every suite.
@bar-capsule @afogel, this needs no ruling on first wins. It does add a MUST at specification.md:297, so it needs one of you. Today only session-start.json says a different Intent is rejected, and only when sessionStart carries one. The new line covers every session.
That line leaves three questions open. Two Guardians could answer each one differently, which is what issue #149 reports.
-
What does "rejected" mean on the wire? §17.1 has no error code for it. The next sentence in §8.4 says "ignored or rejected", so an
a2a_inboundtrigger gets both answers. Do you wantdenyon the step, and with which reason code? Or may a Guardian keep the first Intent and drop the new one? The reference store drops it (session-context-store.ts:272), though nothing calls that code yet. -
What counts as "different"? An
intenthas four fields, and §8.4 fixes onlyparsed. Is a newraworprovenance_iddifferent? Is a shorterparsedlist different? I'd compareparsedas a set, but that's your decision. -
Which Intent can establish, and what happens when none does? §8.4 requires
parser_provenance.originto beuser_input, so an honest Intent on ana2a_inboundorexternal_eventtrigger can't establish anything. A second trigger can't either, becausehooks.md:330callsagentTriggerthe first content-bearing hook. Does an Intent on a trigger the Guardian denied count? When no Intent is established, does the session run without one, and is a late Intent rejected?
This line also works only inside one session. If each scheduled run opens a new session, there's no earlier Intent to compare with, which is the last case in issue #149. I'm not asking for a change there.
Once you answer, Raghuvar can push and one of you can approve and merge. That closes issue #149 and lets PR #341 go next.
Raghuvar, please wait for those answers, so you only push once. I have four asks. I applied them to a scratch copy, and pytest and mkdocs build --strict pass. If Bar or Ariel answer differently, change ask 1 to match.
-
specification.md:297needs two small changes. First, "sessionStartwhen present" can mean the hook, and then asessionStartwith nointentnever reaches "otherwise". Change it to "sessionStartwhen it carriesintent".Second, the reject sentence has no exception for an approved extension, but your PR description says "unless widened". After an extension with
scope: session,Intent.parsedis larger (§9.1). A later trigger then differs from the first Intent or from the larger one, so this line rejects it. Change the sentence to:Any subsequent `agentTrigger` that proposes a different `intent` MUST be rejected, unless the difference is capabilities an approver already added through an `intent_extension` with `scope: session`. -
Please write the rule only in §8.4. The two schemas and
hooks.mddrop "before any content-bearing step", so those three let a late Intent establish and §8.4 doesn't.agent-trigger.json:19also adds a second new MUST ("MUST match it").SPEC_REVIEW_PRINCIPLES.mdsection 1 asks us to define a rule once. Use this text:agent-trigger.json:19, the whole description:Optional Intent for the session (IBAC adopters populate). Specification §8.4 defines what establishes the canonical session Intent and when a later Intent is rejected.session-start.json:24, the last sentence:When sessionStart carries no Intent, Specification §8.4 defines what establishes the canonical session Intent.hooks.md:104, fromoptionalto the end:optional `intent` (IBAC adopters populate, for activation-time policy checks). [Specification §8.4](./specification.md#84-intent) defines what establishes the canonical session Intent and when a later Intent is rejected.
-
Your test at
tests/test_hook_taxonomy.py:330checks two phrases and reads neither doc. I changedagent-trigger.jsonto say a first trigger "does not establish" the Intent, then changed MUST to MAY, then deleted the reject clause. The test passed all three times. Replace it with this one, which also tests asks 1 and 2. It failed on all 7 ways I broke the new text. End the file with one newline.def test_canonical_intent_rule_lives_in_section_8_4(): """Issue #149: section 8.4 states the rule, and the other places point to it.""" for name in ("session-start.json", "agent-trigger.json"): schema = json.loads((HOOK_SCHEMAS / name).read_text(encoding="utf-8")) assert "§8.4" in schema["properties"]["intent"]["description"] hooks = (ROOT / "docs/spec/instrument/hooks.md").read_text(encoding="utf-8") assert "#84-intent" in hooks.split("## agentTrigger")[1].split("\n---")[0] spec = (ROOT / "docs/spec/instrument/specification.md").read_text(encoding="utf-8") section = spec.split("### 8.4 Intent")[1].split("### 8.5")[0] for phrase in ("before any content-bearing step", "MUST be rejected, unless", "`scope: session`"): assert phrase in section
-
Please rebase after PR #338 lands. Both PRs add a test at the end of
tests/test_hook_taxonomy.py, so Git will show a conflict in that file. The conflict is only about position, so keep both tests. I tried this on a scratch copy: 926 tests collected, 925 passed, 1 skipped (the usual one). PR #341 has the same conflict, so keep every test there too.Test:
uv run pytest tests/test_hook_taxonomy.pypasses, and both test names are in the file.
Issue #149 has no assignee yet, because GitHub still won't let me assign you. It's the same step as on your other PRs, so please leave a comment on the issue. After you push, I'll run all of this again.
…intent Align hooks/session-start.json, hooks/agent-trigger.json, hooks.md, and Specification §8.4 on the first-Intent-wins rule: when sessionStart carries no intent, the first agentTrigger carrying intent before any content-bearing step establishes the canonical session Intent, and any subsequent agentTrigger proposing a different intent MUST be rejected unless the difference is capabilities added through an intent_extension with scope: session. Fixes GenAI-Security-Project#149 Signed-off-by: Raghuvar Karthik Durga <177662415+drk-ram@users.noreply.github.com>
|
@rocklambros Rebased onto |
931f598 to
a7227da
Compare
What changed
Aligns
specification/v0.1.0/hooks/session-start.json,specification/v0.1.0/hooks/agent-trigger.json,docs/spec/instrument/hooks.md, anddocs/spec/instrument/specification.md(§8.4) withdocs/concepts/intent.md: whensessionStartomitsintent(for example on unattendedscheduled,external_event,a2a_inbound, orsystemactivations), the firstagentTriggercarryingintentestablishes the canonical session Intent, and any subsequentagentTriggerproposing a differentintentMUST be rejected unless widened viaask-details.json'sintent_extension.Which issue does this implement
Fixes #149
meaning, so it needs no issue
Base branch
integration, because this touches the specification, schemas, a referenceimplementation, an adapter, tests, or CI
main, because every changed path is on the documentation lane allowlist inCONTRIBUTING.md
Type of change
Specification changes
Breaking for implementers? No wire shape changes. Clarifies the
descriptionfields insession-start.jsonandagent-trigger.jsonand alignshooks.mdandspecification.md§8.4 with the existing rule indocs/concepts/intent.md.I tested this
uv run pytest -vpasses on my machineuv run mkdocs build --strictpasses on my machineChecklist
git commit -s(required by the DCO)Security
Closes the unattended-activation gap on
scheduled,external_event,a2a_inbound, andsystemtriggers by ensuring the firstagentTriggercarryingintentlocksIntent.parsedas the canonical session Intent whensessionStartomitted it.