Skip to main content

threadlight-ground

GROUND leg: assesses ACL/citation/refusal probe evidence into a threadlight.ground/v1 manifest (GRD-001..004: ACL, citation, refusal, freshness/coverage/baseline). Each SPEC knowledge_source's enabled control must be evidenced under its own source_id, never inferred across sources. expected_entitled is required (no name heuristic); missing/ambiguous evidence -> not-verified, never guessed; a proven leak (an unentitled principal handed a document outside its allowed_document_ids) -> must-fix. Malformed evidence raises GroundEvidenceError before any output. Persists only source metadata, principal/document IDs and allowlisted detail - never content, prompts, completions, tokens/credentials, or payloads. Manual handoff - threadlight-auto never runs probes. USE FOR: grounding evidence, ACL leak detection, citation validation, refusal checks, ground-manifest, knowledge_sources gate. DO NOT USE FOR: Foundry IQ retrieval, quality scoring, live probes, cross-leg readiness gating.

Quellinformationen

Repository
aiappsgbb/threadlight-skills
Letzte Quellaktivität
19. August 2026 um 09:25
Erkannte Sprache von SKILL.md
Englisch
Sterne
1
Forks
5

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
threadlight-ground
description
GROUND leg: assesses ACL/citation/refusal probe evidence into a threadlight.ground/v1 manifest (GRD-001..004: ACL, citation, refusal, freshness/coverage/baseline). Each SPEC knowledge_source's enabled control must be evidenced under its own source_id, never inferred across sources. expected_entitled is required (no name heuristic); missing/ambiguous evidence -> not-verified, never guessed; a proven leak (an unentitled principal handed a document outside its allowed_document_ids) -> must-fix. Malformed evidence raises GroundEvidenceError before any output. Persists only source metadata, principal/document IDs and allowlisted detail - never content, prompts, completions, tokens/credentials, or payloads. Manual handoff - threadlight-auto never runs probes. USE FOR: grounding evidence, ACL leak detection, citation validation, refusal checks, ground-manifest, knowledge_sources gate. DO NOT USE FOR: Foundry IQ retrieval, quality scoring, live probes, cross-leg readiness gating.
metadata
{"version":"0.1.0"}
# Threadlight Ground — prove the retrieval is safe, not just plausible The **GROUND** leg: the step that turns "the agent cited something" into "the citation is provably grounded, access-controlled, and honest about what it doesn't know." `threadlight-ground` is a **coordinator**, not a retrieval or evaluation engine — it never calls Foundry IQ, never issues a retrieval query, and never runs an evaluator. It only ingests probe *results* an operator already captured (an ACL probe run, a citation validation run, a refusal probe run) and turns them into four findings. > **Why "coordinator."** Provisioning and query planning stay with > `foundry-iq` (Azure AI Search Knowledge Agent); quality/relevance scoring > stays with `threadlight-evals`. This leg's job is narrower and stricter: > given evidence someone already gathered, does it *prove* the knowledge > source is safe to ground answers on? This is a **manual, live handoff** — > `threadlight-auto` does not run live ACL/citation/refusal probes against a > real agent for you. Running those probes against production or pilot data > is an operator decision; this script only assesses evidence the operator > already captured and supplies. ## What this skill does and does not do - **Does:** sanitize a SPEC `knowledge_sources` declaration (whitelist-only — see `references/ground-manifest.schema.json`), assess ACL enforcement, citation grounding, and refusal behavior from caller-supplied probe runs, compute source freshness/coverage, and emit a schema-validated, atomically-written `specs/ground-manifest.json`. - **Does NOT** call Foundry IQ, run a retrieval query, or invoke an evaluator. Every finding here is computed from evidence the caller already captured — a live probe is the operator's responsibility, not this script's. - **Does NOT** score answer quality/relevance (`threadlight-evals`) or aggregate findings across every leg into a single go/no-go (`threadlight-production-ready` consumes GRD-001..004 for that). ## The four findings | ID | Checks | `not-verified` when | `must-fix` when | |---|---|---|---| | `GRD-001` | ACL enforcement | no `permission_model: acl` source declared → trivial `pass`; an ACL source has **no runs carrying its `source_id`** (uncovered); fewer than two distinct principals; no explicit `expected_entitled` on a run (ambiguous); no entitled *and* unentitled probe for a source; a source's declared `acl_probe_principals` are not all probed | an **explicit** unentitled principal received **any** document outside its explicit `allowed_document_ids` — a subset is enough, and no allowlist means nothing is allowed. **A proven leak takes precedence over a coexisting coverage gap:** the finding is `must-fix` even when another run is ambiguous or a declared principal is unprobed, and a sibling source's `not-verified` never erases it | | `GRD-002` | Citation grounding | a `citation_required` source has no non-vacuous citation evidence carrying its `source_id` — it needs at least one citation and at least one retrieved ID | any citation falls outside its run's retrieved set (`missing_from_retrieval`, sorted, de-duplicated) | | `GRD-003` | Refusal behavior | a `refuse_when_unsupported` source has no refusal runs carrying its `source_id` (uncovered) | an executed probe for an unsupported query was **answered** instead of refused | | `GRD-004` | Source freshness / coverage / baseline | no sources declared → trivial `pass`; a declared source has no covering run; a covered source's runs carry no valid RFC3339 `captured_at` (freshness unverifiable); no `retrieval_quality_baseline` was supplied | never `must-fix` — caps at `should-fix` (a covered source's oldest evidence is stale relative to its own `refresh_cadence`) | `GRD-001..003` can reach `pass`, `must-fix`, or `not-verified`. `GRD-004` can reach `pass`, `should-fix`, or `not-verified` — freshness/coverage gaps are never escalated past `should-fix`, reserving `must-fix` for a *proven* control failure. The manifest `status` is `partial` exactly when required evidence is genuinely missing: a `not-verified` finding, an uncovered / freshness-unverifiable source hidden behind an aggregated must-fix, or a `must-fix` proven against **incomplete** ACL coverage (see below). An **executed** `must-fix`/`should-fix` with **complete coverage** is still complete evidence and never downgrades `status` on its own. > **Negative evidence is never erased by a coverage gap.** `GRD-001` computes > a proven leak from the **explicit** unentitled runs first, so an ambiguous > run (no `expected_entitled`), too few principals, or an unprobed declared > principal cannot suppress a leak proven elsewhere in the same source — and > across sources the worst per-source status wins, so one source's > `not-verified` never downgrades another source's `must-fix`. The coexisting > gap is not discarded: it is preserved in a schema-safe `coverage_complete: > false` detail flag (alongside `missing_principals` where available) so the > envelope `status` is still `partial`. A `must-fix` with **complete** > coverage omits the flag and remains `complete`. > **Malformed shapes raise, they are never `not-verified`.** A missing/empty > `source_id`, a `source_id` not in the declared inventory, a missing > `document_ids`/`citations`/`retrieved_ids`/`query_id`, a non-string element, > a non-boolean `expected_entitled`/`refused`, or a negative/non-finite > telemetry value all raise `GroundEvidenceError` **before** any manifest is > built, returned, or written. `not-verified` is reserved for genuinely > *absent* evidence (an uncovered source, an ambiguous entitlement), never a > *malformed* run. ## Source inventory is authoritative — coverage is never inferred The `sources` argument **is** the SPEC-derived `knowledge_sources[]` input contract (see `threadlight-design/references/speckit-template.md`), not anything the CLI's `--project-root` supplies. Every declared source's *enabled* control must be covered by evidence that carries **that source's `source_id`**: ACL evidence when `permission_model == "acl"`, citation evidence when `citation_required`, refusal evidence when `refuse_when_unsupported`. Coverage for one source is never inferred from another source's runs. A source that declares `acl_probe_principals` must have every one of those principals probed. Every declared source id must be **unique**: a duplicate id (e.g. a public twin that would otherwise mask an ACL-protected source under the same id) raises `GroundEvidenceError` before any grouping, assessment, or output. ## Explicit `expected_entitled` is required — no name heuristic `assess_acl` classifies each ACL run only by an **explicit** `expected_entitled` (or `entitled`) boolean on the run. There is no name heuristic: a run without an explicit signal is *ambiguous* and yields `not-verified`, never a guessed pass or fail. A source's ACL runs must include at least one entitled (`true`) and one unentitled (`false`) probe. An unentitled principal's `allowed_document_ids` is its allowlist of legitimately-visible (e.g. public) documents; receiving anything outside it — including a subset — is a `must-fix` leak, and **no allowlist means nothing is allowed**. Only **explicit** unentitled runs contribute a leak, so an ambiguous run never fabricates one — but neither can it hide a leak proven by another run in the same source. ## Evidence shapes ```jsonc // acl_runs[] — one per principal probed against a source. source_id and an // explicit expected_entitled are REQUIRED; allowed_document_ids is the // unentitled principal's allowlist (public docs it may legitimately receive). {"principal": "entitled-analyst", "document_ids": ["doc-1", "doc-2"], "source_id": "policy-library", "expected_entitled": true, "captured_at": "2026-08-17T09:00:00+00:00"} {"principal": "unentitled-guest", "document_ids": ["public-1"], "source_id": "policy-library", "expected_entitled": false, "allowed_document_ids": ["public-1"], "captured_at": "2026-08-17T09:00:00+00:00"} // citation_runs[] — one per answer's citations vs. what was actually retrieved {"citations": ["doc-1"], "retrieved_ids": ["doc-1", "doc-2"], "source_id": "policy-library", "captured_at": "2026-08-17T09:00:00+00:00"} // refusal_runs[] — one per unsupported-query probe {"query_id": "q-out-of-scope-1", "refused": true, "source_id": "policy-library", "captured_at": "2026-08-17T09:00:00+00:00"} ``` `assess_grounding(*, sources, acl_runs, citation_runs, refusal_runs, generated_at, retrieval_quality_baseline)` sanitizes `sources` (the SPEC `knowledge_sources` declaration — see below), computes all four findings, schema-validates the built manifest (so `--json` can never emit invalid or oversharing data), and returns the full `threadlight.ground/v1` manifest. `retrieval_quality_baseline` is a **reference** to the baseline artifact (`threadlight-evals`) — a nonempty repo-relative path or id, never its content, and never an absolute path, `..` traversal, or URL. A `None` baseline is allowed but makes `GRD-004` `not-verified`. `validate_citations(citations, retrieved_ids)`, `oldest_timestamp(runs)`, and `aggregate_telemetry(runs)` are also exposed standalone for direct use. ## Persistence contract — never the raw evidence The manifest persists **only**: sanitized source metadata (the six `knowledge_sources` fields plus optional `acl_probe_principals`), principal identifiers, document IDs, the four findings (whose `detail` is an **allowlisted schema** of IDs, counts, status maps, an optional `coverage_complete` boolean, and a controlled `reason` enum — never a free-form note), aggregate telemetry (`retrieval_count`, summed `subqueries`, summed `tokens`), and the retrieval-quality baseline *reference*. It **never** persists retrieved document content, raw query/prompt text, model completions, access tokens, credentials, or customer payloads — `_summarize_*_runs` rebuilds curated evidence dicts from scratch rather than passing raw runs through, and every write is scanned recursively for credential/content/prompt-shaped **keys** (matched as whole snake-case words, so a legitimate `tokens` **count** is never confused with a credential-shaped `access_token`) **and** secret-shaped **values** (a smuggled key/token in any ID field) before anything touches disk. Value scanning is **structural, never entropy-based**: opaque hashes, UUIDs, and base64/base64url document keys are legitimate IDs and are never rejected for looking random, while a value that parses as an Azure Shared Access Signature — an `http(s)` URL, bare `?`-query, or unprefixed query carrying `sig`, `sv`, and at least one additional SAS marker (`se`/`sp`/`sr`/`st`/`spr`) — is rejected even though an ordinary URL or opaque id is not. `aggregate_telemetry` sums only genuinely numeric, non-negative, finite `subqueries`/`tokens` — a boolean, string, negative, or non-finite value raises rather than being coerced. ## CLI ```bash python3 skills/threadlight-ground/scripts/ground.py \ --project-root . --evidence-file specs/ground-evidence.json --emit --gate ``` The `--evidence-file` is the SPEC-derived evidence bundle (`sources`, `acl_runs`, `citation_runs`, `refusal_runs`, `retrieval_quality_baseline`, optional `generated_at`) — the **`sources` inventory comes from that object, not from `--project-root`**. `--project-root` is only the output/project boundary: a `--manifest-path` that escapes it (an absolute path outside it, a `..` traversal (including through missing parents), or a parent symlink resolving outside it) is rejected before any temporary or destination file is written. `GroundEvidenceError`, `ManifestValidationError`, and read/write `OSError`/JSON errors are all caught cleanly (exit 1) so a failed run never corrupts a prior valid manifest. ## Files ``` scripts/ground.py # stdlib implementation + CLI references/ground-manifest.schema.json # ground-manifest.json shape (shared envelope) tests/test_ground.py # pytest suite ``` ## Tests ```bash python3 -m pytest skills/threadlight-ground/tests/ -v ``` ## See also - **`foundry-iq`** — owns Foundry IQ (Azure AI Search Knowledge Agent) provisioning and the actual retrieval/query planning this leg's evidence comes from. - **`threadlight-evals`** — owns answer-quality/relevance scoring; a separate concern from the ACL/citation/refusal proofs here. - **`threadlight-production-ready`** — consumes `GRD-001..004` from `specs/ground-manifest.json` alongside every other leg's findings for a single pilot go/no-go.
Auf GitHub ansehen