Repository navigation
Add the skill lifecycle hooks to the Trace mappings - #63
rocklambros merged 12 commits into
Conversation
Signed-off-by: Saba Siddique <sabasiddiqdev@gmail.com>
Signed-off-by: Saba Siddique <sabasiddiqdev@gmail.com>
|
Retargeted to Two decisions needed from the Spec leads (@bar-capsule @afogel):
|
Operationalizes the contribution governance the core team agreed on September 8, filtered through the Strategic Adoption Plan v3 committed outcome. Design: `design/2026-09-09-contribution-governance-design.md` (v1.1) Plan: `design/plans/2026-09-09-contribution-governance.md` ## What this installs **Current Priority Scope.** `CONTRIBUTING.md` gains one section that states what the project is driving at for the next ninety days, what is deferred to v0.2.0, and what is out of scope by design. It is stated once. Every other surface links to it rather than restating it, and the landing page now renders it straight out of `CONTRIBUTING.md` so the two cannot drift. **Branching.** `main` publishes the site and all 44 schema `$id` URIs on merge, so specification and code land on `integration` and publish on a deliberate promotion. A guard (`tools/base_branch_guard.py`, 16 tests) enforces a positive path allowlist and fails closed on anything nobody anticipated. The promotion exemption checks the head *repository*, not just the ref, so a fork branch named `integration` cannot walk a schema change onto the publishing branch. **Intake.** Blank issues are off. Six forms route by type, and no form can stamp a `scope:`, `priority:`, `workstream:`, or `status:accepted` label. That prohibition is the whole structural guarantee behind maintainer-only triage. The sixth form asks for nothing but a description, because the strongest outside contribution this project has received would have fit none of the other five. **The gate.** A change to behavior, normative text, or code references an issue carrying `status:accepted`. An editorial correction does not, wherever it lands. A pull request whose issue is not accepted yet is neither closed nor reviewed. It waits, and a bot says why. **Automation.** Four workflows: the base-branch guard, an integration sync, a weekly promotion pull request, and the intake comment. Plus a reminder that opens an issue when the priority scope passes its review date. **Phase 2 executor.** `tools/apply_governance.py` performs the live migration steps idempotently, `--dry-run` by default. It is structurally incapable of merging, closing, or retargeting a pull request, and a test asserts no code path can emit those commands. ## Authorship policy change The rule that a maintainer strips a `Co-Authored-By` trailer naming a model is removed. The project now mandates neither direction. The human `Signed-off-by` stays required, because only a person can make the DCO certification. A standard about agent provenance should not erase the provenance of its own commits. ## Reviewer notes - Nothing on the published site changes except the landing page's Contribute section. I built the full pipeline from `main` and from this branch and diffed: the only files that differ are `index.html` and `acs.css`. All 44 schemas are byte identical. - 253 tests pass. `mkdocs build --strict` passes. - This targets `integration` rather than `main` because it touches `.github/`, `tools/`, and `tests/`, which is exactly what the guard it installs requires. ## Still to do after this merges Retarget #63, #24, #60, and #22 to `integration`. Merge #21, #20, and #22 when the team is ready. Then run the executor for rulesets, default branch, required check, and the seeded issues. The order that matters is in the plan. --------- Signed-off-by: rocklambros <rock@rockcyber.com>
|
Thanks for this. It is queued rather than ignored. This pull request does not reference an issue carrying If this is an editorial correction, tick that box in the description and this comment stops applying. |
…oks-trace-mappings Signed-off-by: Saba Siddique <sabasiddiqdev@gmail.com>
…que1/agent-control-standard into fix/skill-hooks-trace-mappings
|
@sabasiddique1 sorry for the long wait. Decisions, plus two things for the same update:
The new taxonomy tests are a good guard: I checked that they catch the missing skill rows. Happy to approve once these are in. |
|
@bar-capsule thanks, that's clear. Pushing all four tomorrow. |
…oks-trace-mappings Signed-off-by: Saba Siddique <sabasiddiqdev@gmail.com> # Conflicts: # docs/acs.md
…y Info, split the skill digest Signed-off-by: Saba Siddique <sabasiddiqdev@gmail.com>
|
@bar-capsule pushed: 1005 for load/unload with activity_id 1 and 2, "Device Inventory Info" on 5001, integration's acs.md line kept, and the digest split into acs.skill.digest.algorithm and acs.skill.digest.value. pytest and mkdocs --strict pass. |
README.md still said sixteen native lifecycle hooks after the skill hooks brought the schemas to nineteen. The taxonomy guard missed it because it scanned only docs/ and only digit counts. Signed-off-by: rocklambros <rock@rockcyber.com>
Every failure message now names the fix and, where one exists, the escape hatch. A page that lists a deliberate subset or names a proposed hook goes in SUBSET_SURFACES or PROPOSED_HOOKS with a reason, and a new test rejects entries that lose their reason or outlive their need. The reference pattern skips globs, paths and anchors, which matched as unknown hooks. The count check skips subset counts below the restating threshold, reads spelled-out counts, and scans README.md, which is how the stale sixteen above went unnoticed. A renamed section heading now fails with the heading's name instead of a bare StopIteration. Signed-off-by: rocklambros <rock@rockcyber.com>
|
@sabasiddique1 I reviewed this tonight, and it's ready from my side. Thank you for turning Bar's four asks around in a day. What I checked
What I pushed to your branch, and why I pushed two small commits, so please pull before you push again.
I tested the guard by putting "sixteen" back in the README. It failed with this message: I also updated the PR description, because it becomes the squash commit message. It still said One thing I'm leaving as it is The Next step I pushed the last commit, so the branch rules say someone else has to approve. @bar-capsule, you said you'd approve once your four asks were in. They are, and the only new changes are the two commits above. When Bar approves, I'll squash it with |
185ef4e
into
GenAI-Security-Project:integration
|
For the record, since this merged with the admin bypass on October 12 and I owe a note on why. I pushed the last two commits here (the hook-taxonomy guard fixes), so my approval couldn't count, and I merged before Bar's approval came in because the trace work queued behind it (PR #261, PR #244 and issue #228) needed these mappings. Here's what was in place at merge: Saba had addressed all four of Bar's asks on October 9, my two commits only touched the guard, and CI was green on the merged head, @bar-capsule, if you get a chance to look at it after the fact, anything you find goes into a follow-up PR. |
The embedded schemas follow integration after GenAI-Security-Project#63, GenAI-Security-Project#258 and GenAI-Security-Project#261. The parity recording stores the git object IDs of the deciding TypeScript paths instead of a commit, so a squash merge no longer makes TestRecordingIsCurrent fail. The paths include agt.lock and the agt-bridge package.json, which pin the AGT commit and SDK. The recorder and the test read them from one list; the test fails when the recording names other paths or was made from another corpus, and the recorder refuses uncommitted changes to them. A test checks that the Go workflow runs on every deciding path. agt/README.md tells a TypeScript contributor when to re-record. A test requires agt-native.lock and agt.lock to pin the same AGT repo and commit. The native build fails when AGT at that commit changes ffi.rs, which agteval/acs.h is written from, or fetches another opa than agt-native.lock pins. Under the agt evaluator, policy.opa_timeout must be shorter than protocol.decision_timeout; guardian.yaml ships 4s. Otherwise a slow opa lets the agent stop waiting before AGT's deny arrives (GenAI-Security-Project#269). make load measures either evaluator under concurrent clients, selected by EVALUATOR like the other targets. Under agt each decision runs one opa process; on a 20-core host decisions stop rising near 16 concurrent ones, and at 256 they reach the 5s timeout. guardian.yaml now ships limits.max_engine_calls 32, and docs/load.md records the results. The load run found that an engine call gave its slot back only after its answer was sent, so a client's next step could be refused engine_saturated with no call running; callEngine now releases the slot first, also after a panic. When the host adapter's audit log cannot be written, the record goes to stderr as one JSON line with the final disposition, and the refusal's reasoning says whether the record went to stderr or nowhere. The audit file's close error now counts. The Codex and OpenCode hooks pass their own stderr. The §6.3 row says that ALLOW at a hook that permits no DENY is an interpretation (GenAI-Security-Project#270), and the docs say only the adapter library reaches those hooks. Dependabot proposes Go updates, one pull request per dependency across both modules. The Go workflow runs weekly, so govulncheck sees advisories for the toolchain that Dependabot does not move, triggers on the agt-bridge package.json, and no longer fetches full history. A test checks that the method table permits DENY exactly where hooks.md does, and fails on a Decision line it cannot classify. The coverage floor counts every package except commands, examples and test helpers. The Guardian meets the expectations GenAI-Security-Project#256 sets for reference implementations, mapped to tests in docs/conformance.md. audit.max_file_bytes and audit.max_files rotate each audit file; guardian.yaml keeps at most 1 GiB per log; max_file_bytes needs max_files of at least 1, so a rotation never deletes the live log. make load can set the rotation and fails if the log drops, splits or reorders a record or exceeds its bound; docs/load.md records a run and the cost of long sessions. storage.provider names the session store. The HMAC secret file holds base64 of at least 32 bytes. key_id is a configured label with no default, an unknown key_id is refused (GenAI-Security-Project#118, GenAI-Security-Project#272), and the hooks and the conformance harness take it as a flag. A toolCallResult whose request_id_ref matches no request is recorded (GenAI-Security-Project#272). Decisions from other pull requests that the Go code contradicted: - A shell command's URL ends only at ASCII whitespace; U+FEFF or U+00A0 in the userinfo no longer hides the host curl reaches (GenAI-Security-Project#268). - Versions are compatible when they share X.Y under 0.x; the handshake negotiates only such a version, and a step must match it (GenAI-Security-Project#196, GenAI-Security-Project#255). - A policy target that is not a string is denied evaluation_failed; the TypeScript fix is in GenAI-Security-Project#229, so two recorded cases are listed as ahead of the recording until it is re-recorded. - The host adapter records every decision failure under either posture, with its class, handshake failures included (GenAI-Security-Project#37). - The host adapter denies under any posture a signed error other than -32603, an unverified answer and a malformed answer; the docs mark this as an interpretation of §6.4 ahead of GenAI-Security-Project#32, which is open. The version rule is marked the same way against §3. - The audit directory is 0700; a symlinked audit path or an audit file open to group or others is refused (GenAI-Security-Project#71). Claude-Session: https://claude.ai/code/session_01DFdYnoBitHhPcUSq7wMWs1 Signed-off-by: Konstantin Trunin <konstantin@trunin.com>
What changed
skillRegister,skillLoad, andskillUnloadhad no entry inotel-mapping.jsonorocsf-mapping.json, so a deployment claiming ACS-Trace had no normative span name orclass_uidfor a skill event. This adds both mappings, renders them on the Trace Events and Extending OCSF pages, links them from the Skill concept page, and widenstests/test_hook_taxonomy.pyto guard every surface that restates the hook set.docs/acs.mdkeeps integration's version, which #21 already updated.Which issue does this implement
Closes #57, closes #58.
Base branch
integration, because this touches the specification, schemas, a reference implementation, an adapter, tests, or CImain, because every changed path is on the documentation lane allowlist in CONTRIBUTING.mdType of change
Specification changes
Breaking for implementers? No. Nothing on the wire changes. Three new keys appear in each mapping's
default; existing keys, span names, and class assignments are untouched.OTel:
acs.skill.register,acs.skill.load,acs.skill.unload. Required attributes come only from fields each hook schema requires. The digest maps to two attributes,acs.skill.digest.algorithmandacs.skill.digest.value, so every exporter emits the same values.acs.skill.load_pathstays required because cascade containment is the reason the hook carries it.OCSF, as the Spec leads decided:
skillLoadandskillUnloadmap to Module Activity (1005) withactivity_id1 (Load) and 2 (Unload). Its required module object is the skill itself, and keeping loads off Process Activity (1007) lets a reader tell a skill loading from the tool calls its actions raise.skillRegistermaps to 5001, labeled Device Inventory Info, its name in every OCSF release. Theagbom/*rows still say Inventory Info until #121 renames them. A deniedskillRegisterstill surfaces as Detection Finding 2004 throughdecision_class.Guard
The first commit widens the test and fails on exactly the surfaces #58 lists, plus one it did not: the class table in
extend_ocsf.mdnever listedsteps/agentTrigger. That row is fixed here too.Two maintainer commits harden the guard. Every failure message now says how to fix it. A page that lists a deliberate subset or names a proposed hook goes in
SUBSET_SURFACESorPROPOSED_HOOKSwith a reason. The reference pattern skips globs, paths, and anchors. The count check skips subset counts, reads spelled-out numbers, and scansREADME.md, which still said sixteen native hooks and now says nineteen.Not changed
The AgBOM trigger list in
docs/spec/inspect/README.mdomitsskill; filed as #120. The "Sixteen" inspecification/proposals/skill-lifecycle/README.mddescribes the pre-skill state and is correct in context.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