Skip to main content

ops-triage-loop

The weekly sweep that turns captured proto-learnings into reviewed work. Reads the open `ops/proto-learning` issues on the learnings repo, clusters them by lesson, applies a promotion threshold, and routes each cluster to its home — an issue on the repo that owns it, a drafted PR against shared skills, a `ops/loop-improvement` issue against the engine, or closed with a reason. Files issues rather than editing product repos, and nothing auto-merges. Scheduled, not event-triggered: `ops/triaged` is a marker it writes, never a trigger. Trigger on "triage the learnings", "run the triage sweep".

معلومات المصدر

المستودع
umbraco/umbraco-ai-ops
آخر نشاط في المصدر
٢٣ سبتمبر ٢٠٢٦ في ١٥:٠٦
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
ops-triage-loop
description
The weekly sweep that turns captured proto-learnings into reviewed work. Reads the open `ops/proto-learning` issues on the learnings repo, clusters them by lesson, applies a promotion threshold, and routes each cluster to its home — an issue on the repo that owns it, a drafted PR against shared skills, a `ops/loop-improvement` issue against the engine, or closed with a reason. Files issues rather than editing product repos, and nothing auto-merges. Scheduled, not event-triggered: `ops/triaged` is a marker it writes, never a trigger. Trigger on "triage the learnings", "run the triage sweep".
# ops-triage-loop The **triage half** of the self-learning system. The capture half — read-only `SubagentStop` / `SessionEnd` hooks in this plugin — files **proto-learnings** as issues off the critical path. This loop turns that raw backlog into reviewed work by routing each lesson to whoever owns it. **It is scheduled, not routed.** There is no triage label and no route row: it wakes weekly and sweeps. `ops/triaged` is a marker **this loop writes**, so the next run skips what it has already handled — it is an output, never a trigger. Why weekly and not per-issue: **the threshold needs a population.** A lesson earns a shared-skills PR by *recurring*, and you cannot see recurrence one issue at a time. Capture is continuous; triage is periodic; a weekly cadence keeps the inbox from growing without flooding anyone. **It never hand-edits a product repo.** For anything specific to one repo it files an **issue** there and lets that repo's own process implement it. It drafts an actual **PR** only for shared tooling. Everything is gated; nothing auto-merges. ## What it calls | Capability · action | Why | Visibility | |---|---|---| | `ops-repo-meta · topology` | the `learnings` inbox, and the `code` repo a lesson belongs to | cross-cutting (read) | | `ops-repo-meta · identity` | `labels.proto_learning`, `labels.triaged`, `labels.loop_improvement`, by purpose | cross-cutting (read) | | `ops-notify · send` | one line per run, only when something was routed | cross-cutting (infra) | All GitHub work goes through **`github-ops`** by operation name. This loop commands **no services**: it reads, files and closes, which is forge work, not product work. ## Config | Thing | Value | |---|---| | Inbox | the **`learnings`** repo from `topology` (defaults to `code`) | | Inbox filter | open issues, labelled `labels.proto_learning`, **not** labelled `labels.triaged` | | Routed items per run | **≤ 10** total, of which **≤ 5** may be PRs | | Cadence | **weekly**, as a scheduled routine | > **The numbers are inherited defaults, not measurements.** The threshold of 2 and the caps of > 10/5 come from the prototype, which ran over a family of many small repos where the same lesson > recurred quickly. Over two large repos a cluster fills more slowly. Adopt them, watch real inbox > volume, and change them deliberately — do not re-derive them from nothing. ## The routing table `guessedHome` on the record is a **hint**; you decide. The deciding question is ***"would a different repo benefit from this?"*** | Home | Where it goes | Mechanism | When | |---|---|---|---| | **`code`** | the repo named by the cluster's `sourceRepo` | **Issue**, titled `[from-learnings] …` | The lesson is specific to that repo — a quirk of its own code, content or config. Only here when it affects *that* repo and no other. | | **`shared-skills`** | the shared consumer repo of a repo family | **PR**, drafted | Generalizable: it recurs across repos, or would help any repo. **Requires the threshold.** | | **`loop-self`** | this engine | **Issue** labelled `labels.loop_improvement` | About how a loop or the orchestration itself behaves. The loop must not rewrite its own definition unreviewed. | | *discard* | — | **Close** with a one-line reason | Not actionable, stale, or wrong. | **That fourth outcome is normal, not a failure.** "Not actionable, stale or wrong" is a legitimate result, and a triage run that never discards anything is not being honest with the inbox. **Domain-specific versus generalizable is the core judgement.** A lesson goes to one repo **only** when it affects that repo and no other. The moment it would help a second repo it belongs in `shared-skills`, not duplicated into one repo's skills. When genuinely unsure: prefer `shared-skills` if it is a tooling or pattern lesson, otherwise **hold it** (leave the proto-learning open, uncommented) rather than mis-filing. > **`shared-skills` may not be reachable in your topology.** It only means anything for a repo > **family** with a shared consumer repo. For a single-product consumer there are only two live > destinations, `code` and `loop-self` — and since a shared-skills PR is the *only* thing the > threshold gates, **the threshold gates nothing there.** Say so in the run summary rather than > pretending to apply it. ## Step 1 — gather the inbox **List** the open issues on the inbox repo carrying `labels.proto_learning` and **not** `labels.triaged`. For each, parse the fenced `json` record from the body (see [`references/proto-learning-schema.md`](references/proto-learning-schema.md)). - **Malformed record** → comment asking for a reformat and skip it. Never guess at fields; a guessed `category` clusters wrongly and is worse than a skip. - **Empty inbox** → report "nothing to triage" and stop. A normal outcome. ## Step 2 — cluster and dedupe Group issues expressing the **same lesson**: same `sourceRepo` + same `category` + a **semantically equivalent** `lesson`. Each cluster becomes **one** routed item and carries the full list of source issue numbers as **provenance**. **Dedupe across the whole open set, here, in reasoning — not per issue.** That is the entire point of a batch sweep, and it is the one part of this mechanism that is genuine judgement rather than arithmetic. Two records describing the same gap in different words are one cluster. ## Step 3 — apply the threshold Compounding means **a pattern**, not a one-off: - **Recurred** — a cluster with **≥ 2** distinct source issues, *or* the same lesson seen across **≥ 2** `sourceRepo`s → eligible for **`shared-skills`**. - **Single occurrence**, repo-specific → a **`code`** issue, or **hold** it (leave open, uncommented) if it is too thin to act on yet. **Never promote a single incident into a shared skill.** - **`loop-self` clusters are not threshold-gated** — route them whenever they are actionable. A loop that wastes a wake-up wastes it every week; waiting for a second sighting buys nothing. ## Step 4 — route each cluster **`code`** — an issue on the owning repo: 1. Confirm the lesson truly affects only that repo. If it would help another, re-route to `shared-skills`. 2. **Create an issue** there: a clear title prefixed `[from-learnings] `, what should change and why, and — from the record's notes — a hint whether it belongs in that repo's `CLAUDE.md` or in one of its skills. Let that repo's process decide the final placement. 3. **Do not apply the ready label.** A human decides whether to feed it to the issue loop. That is the compounding gate, and a loop that self-feeds has removed it. **`shared-skills`** — a drafted PR: 1. Create a branch and push the **smallest** edit to the shared skill that *should have* surfaced the lesson. 2. Open the PR. **Threshold and provenance are required, no exceptions.** **`loop-self`** — an issue on the engine: 1. **Create an issue** labelled `labels.loop_improvement`: what the loop does today, what should change, and why. 2. **Do not draft a PR editing a loop skill.** A human frames a change to the loop's own definition. **Every routed item carries provenance**: the source issue numbers linked, the `sourceRepo#issue` / PR each came from, and the occurrence count as threshold evidence. **Reviewers approve facts, not vibes** — a routed item without its evidence is unreviewable. ## Step 5 — mark processed **The rule differs by destination, and the difference matters:** - **`shared-skills` (a PR)** — comment the PR link on each source issue and add `labels.triaged` so the next run skips it, **but leave it open** until the PR merges. **Never close a proto-learning just because you opened a PR for it** — a rejected PR would silently lose the lesson. - **`code` and `loop-self` (issues)** — **close** each source proto-learning with a comment linking the new issue. Safe, because the lesson now lives in that issue. - **Discarded** — close with a one-line reason. ## Caps and guardrails - **≤ 10 routed items per run, of which ≤ 5 are PRs.** If more clusters are ready, route the highest-value ones, **`log` how many were deferred**, and leave the rest for next week — **never silently drop them.** - **Never hand-edit a product repo's content.** File an issue there instead. - **A shared-skills PR requires the threshold and provenance.** No exceptions. - **Never auto-merge, never force-push, never edit a protected branch directly.** - **One cluster → one routed item → one home.** Never bundle unrelated lessons. - **Never apply a ready label to anything you file.** The human gate is what makes this compound safely. - **Never use `fable`.** ## Running as a routine Schedule this **weekly** as a cloud routine. It wakes, runs Steps 1–5 against the current inbox, routes up to 10 clusters, and stops — the issues sit in their owning repos and any shared PR sits for review. `ops/triaged` keeps the next run from re-doing the same work. It needs this skill and the `ops-engine` plugin, for `github-ops`, `ops-repo-meta` and `ops-notify`. The three labels (`ops/proto-learning`, `ops/triaged`, `ops/loop-improvement`) must exist on the inbox repo before the first sweep — the filter is label-based, and `ops/triaged` is written by this loop.
عرض على GitHub