Skip to main content

goal-drift

Read-only goal-drift auditor. Holds each project's immutable goal as a typed record derived only from real human prompts, inspects what the project actually produced (tickets first, then artifacts, commits, and absences), and labels every action SERVES_GOAL, SUPPORTS_INDIRECTLY, DECLARED_DRIFT, UNTICKETED_WORK, SCOPE_DRIFT or MISSING_EXPECTED with a reason. Runs nightly on cron and reports; it never edits, commits, fixes, or reprioritises. Use when asked whether work is on track, whether an agent drifted, to register or read a project's immutable goal, or to run the goal-drift check.

Zur Installation springen

Quellinformationen

Repository
grahama1970/agent-skills
Letzte Quellaktivität
8. August 2026 um 16:32
Erkannte Sprache von SKILL.md
Englisch
Sterne
5
Forks
2

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
13 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
goal-drift
description
Read-only goal-drift auditor. Holds each project's immutable goal as a typed record derived only from real human prompts, inspects what the project actually produced (tickets first, then artifacts, commits, and absences), and labels every action SERVES_GOAL, SUPPORTS_INDIRECTLY, DECLARED_DRIFT, UNTICKETED_WORK, SCOPE_DRIFT or MISSING_EXPECTED with a reason. Runs nightly on cron and reports; it never edits, commits, fixes, or reprioritises. Use when asked whether work is on track, whether an agent drifted, to register or read a project's immutable goal, or to run the goal-drift check.
allowed-tools
["Bash","Read"]
triggers
["goal drift","did we drift","am I on track","scope drift","check goal drift","drift verdict","is this work serving the goal","register immutable goal","what is the immutable goal","why did we drift"]
metadata
{"short-description":"Read-only goal-vs-actions drift audit on a nightly cron","author":"Graham","version":"0.1.0","inspired-by":"nicobailon/pi-subagents watchdog scope-drift (README verified 2026-08-02)"}
runtime_self_improvement
basic
provides
["goal-registry","goal-drift-detection","scope-drift-report"]
composes
["ticket","tau","memory","goal-helper","scheduler","task-monitor","agentic-evals"]
complies
["best-practices-skills","best-practices-python","best-practices-arangodb"]
taxonomy
["operations","validation","precision","resilience","human-in-the-loop"]
disciplines
["evaluation-quality","observability-operations"]
# goal-drift **Read-only.** Observes and reports. It cannot edit files, commit, or reprioritise. A drift detector that can also act becomes one more lane to drift into. ## Related skills, easily confused | Skill | Axis | |---|---| | `/goal-helper` | **authors** a goal: proof command, completion criteria, retry limits | | `/project-drift` | **knowledge** drift: does transcript evidence stale-date `PROJECT_KNOWLEDGE.md`? | | **`goal-drift`** | **goal** drift: does the work still serve the registered immutable goal? | `/project-drift` asks *"is the documentation still true?"* This asks *"are we still doing the right thing?"* Both are real; they fail independently. Documentation can be perfectly accurate while the work wanders. ## Why it exists An immutable goal written into a document does not prevent drift. Observed 2026-08-02: a goal was recorded verbatim in a skill header, and the work still went to a compiler fix in another repo, four unrelated documentation edits, and single-employer archaeology reported as chat prose. Every step was defensible alone. None was the artifact the goal named. The `PROJECT_KNOWLEDGE` claims stayed accurate throughout, so a knowledge-drift auditor would have reported clean. Nobody noticed until the human asked. The mechanism is ported from `nicobailon/pi-subagents`, whose watchdog keeps a current-scope artifact from real user prompts and flags work that no longer serves it as `scope-drift`. That project is a Pi extension (TypeScript), so the pattern is reimplemented here rather than installed. ## The rule that makes it work **Scope comes only from real human prompts.** The agent's own intermediate goals, self-generated plans, and auto-follow steps are never admitted as scope. Without this rule an agent invents a sub-goal, pursues it, and grades itself compliant. pi-subagents makes the same exclusion: its watchdog auto-follow prompts are explicitly not recorded as scope. `register` stores `source: human_prompt` with the verbatim text. Anything marked `agent_inferred` is **refused at registration**, not warned about. ## Commands ```bash ./run.sh register --project <name> --goal-file goal.txt # human text only ./run.sh goal --project <name> # read the goal back ./run.sh check --project <name> --since 24h [--json] # the audit ./run.sh schedule # nightly cron ./sanity.sh # behavioral gates ``` Nightly: ```bash /scheduler add goal-drift --cron "0 6 * * *" --budget 5 ``` 06:00 deliberately — **after** nightly producers finish, so it grades a completed night rather than one in progress. ## Evidence hierarchy — tickets first | Rank | Evidence | Source | Why | |---|---|---|---| | 1 | **Tickets** | `/ticket` + `gh issue list` | declares intent **before** work starts | | 2 | Artifacts | criterion `artifact_globs` | did the thing actually get produced? | | 3 | Commits | `git log --since` | secondary; a commit citing **no** ticket is itself a signal | | — | **Absence** | expected artifact never produced | the case a what-happened-only checker cannot see | Tickets rank first because a ticket declares intent at filing time, so drift is catchable the day it is declared rather than weeks later in commit forensics. A lease shows what is being worked on *now*; attached proof is real acceptance evidence rather than a filename guess. Verified: a ticket titled "Fix DAG reachability in tau compiler" against a report-and-resume goal yields `DECLARED_DRIFT` with zero commits present. **Absence remains the finding that matters most.** A night with twelve commits and zero instances of the artifact the goal names *is* the drift case. ## Strict seam contracts Every boundary-crossing artifact is validated at the producer with a typed `@dataclass` + `validate()` (copy-safe, no pydantic). Exactly three outcomes: **pass, self-heal-with-record, or raise** — never warn-and-continue. Validated artifacts carry a `seam_validation` stamp so a reader can tell "validated" from "never checked". Cross-field truth checks, because field presence alone does not catch a lying summary: - `ON_GOAL` while findings contain drift markers → **refused** - `NOT_ESTABLISHED` without a `GOAL_UNREGISTERED` finding → refused - `indirect_share > indirect_cap` while claiming `ON_GOAL` → refused - `read_only: false` → refused The skill therefore cannot emit a verdict its own evidence contradicts. ## tau integration The audit is handed to `/tau` as a skill node using **`tau.generic_dag_spec.v1`** — *not* `tau.dag_contract.v1`, which tau skill nodes reject — with `tau.skill_work_order.v1` and `tau.skill_dag_node.v1`. The node declares `read_only: true` and the work order's task text carries "Never edit, commit, or reprioritise", so the constraint travels with the handoff. **Goal identity is `goal_hash`**, canonical over the goal object the way tau hashes goals: - hash covers goal **content**; `registered_at` is excluded, so re-registering identical text and criteria reproduces it - change one word of the goal and the hash changes - a revision carries the prior hash as **`goal.parent_goal_hash`** — traceable lineage, not a silent overwrite "Immutable" stops being a promise in prose and becomes something a receipt can prove. ## Verdicts | Verdict | Meaning | |---|---| | `SERVES_GOAL` | maps to an acceptance criterion | | `SUPPORTS_INDIRECTLY` | plausible enabler — **capped**, see below | | `SCOPE_DRIFT` | real work, no mapping to any criterion | | `DECLARED_DRIFT` | a **ticket** declares work matching no criterion — caught at filing time | | `UNTICKETED_WORK` | a commit cites no ticket and matches no criterion | | `MISSING_EXPECTED` | a criterion produced nothing | | `GOAL_UNREGISTERED` | no goal → report is `NOT_ESTABLISHED`, never "clean" | Run verdict: `ON_GOAL`, `DRIFTED`, `NOT_ESTABLISHED`, or **`DEGRADED`** (an evidence source failed; partial evidence can never read as on-goal). `SERVES_GOAL` from a ticket requires **closed AND attached proof**. An on-criterion ticket still open, or closed without proof, is `SUPPORTS_INDIRECTLY` and does **not** satisfy absence — "in progress" is not done. **`SUPPORTS_INDIRECTLY` is capped at 30% of actions.** Past the cap the run is `DRIFTED`, because *"it was all necessary groundwork"* is precisely the story drift tells about itself. Infrastructure that enables the goal is legitimate; infrastructure that replaces producing the goal's artifact is not. ## Report contract Leads with the verdict and the absences, never with the volume of work: ``` project: monitor-opportunities window: 24h verdict: DRIFTED MISSING_EXPECTED daily interactive report (0 produced, >=1 required) MISSING_EXPECTED tailored resume variant (0 produced) SCOPE_DRIFT tau compiler fix (no criterion references tau) SERVES_GOAL ATS tenant discovery -> criterion: discover opportunities indirect 42% exceeds cap 30% -> DRIFTED ``` An honest `DRIFTED` verdict is a **success** for this skill. It must never soften a verdict because the work looked productive. ## Non-negotiables - **No mutation.** `sanity.sh` asserts the runtime cannot write to a project tree and that no subcommand edits, commits, or reprioritises. - **No self-certification.** `agent_inferred` goals are refused. - **Absence is a finding.** Zero expected artifacts is `DRIFTED`, not silence. - **No goal means `NOT_ESTABLISHED`** — never "on track by default". - **Writes go through `/memory`**, never direct ArangoDB. ## References - `references/verdict-contract.md` — verdict definitions and the indirect cap - `fixtures/agentic_eval.json` — positive, negative, adversarial cases
Auf GitHub ansehen