Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
986b40f
care loop: adding care loop and related workflows
Jacobjeevan Jul 11, 2026
6ef9f09
care loop: adding all logic
Jacobjeevan Jul 12, 2026
66f5d98
feat: updated care loop doctor and care diff review
Jacobjeevan Jul 13, 2026
5a8734c
moving to loopd architecture
Jacobjeevan Jul 14, 2026
eba07c4
converting planning/triaging to skills, additional opencode related c…
Jacobjeevan Jul 15, 2026
3b71673
fine tuned (sdk) changes for planner, triager and ci handler
Jacobjeevan Jul 17, 2026
a812a51
ci fix: passing along logs and added tests
Jacobjeevan Jul 17, 2026
7fdd555
logging (round step), tier enforcement and additional improvements
Jacobjeevan Jul 20, 2026
8506fe7
test grade and ux review skill updates
Jacobjeevan Jul 20, 2026
b858096
added plan docs
Jacobjeevan Jul 20, 2026
87cc487
auto loop doctor v1
Jacobjeevan Jul 20, 2026
38cf563
auto loop doctor v2
Jacobjeevan Jul 20, 2026
e4c70f0
add care evals
Jacobjeevan Jul 21, 2026
75bb2bf
doctor improvements
Jacobjeevan Jul 21, 2026
fcbb3a4
preserve verdicts/feedback per round
Jacobjeevan Jul 21, 2026
d4b44e9
IMP 18: auto formatting
Jacobjeevan Jul 21, 2026
f21e607
commit doctor loop diagnoses
Jacobjeevan Jul 21, 2026
1d34f85
adjust bot arrived check/check by commit hash alone
Jacobjeevan Jul 21, 2026
4a66bba
adding careloopd as launcher
Jacobjeevan Jul 21, 2026
4a880af
before PR resume, adjust perms for reviewer, timeout adjustment
Jacobjeevan Jul 21, 2026
832c45e
rm local ci flow
Jacobjeevan Jul 28, 2026
7121020
add report for doctor loop
Jacobjeevan Jul 31, 2026
4297c9d
care-loop: fetch Jira ticket text + image attachments into the planner
Jacobjeevan Aug 11, 2026
8e9048a
care-loop: COLLATION-2026-07-28 doctor batch (triager churn, diff bli…
Jacobjeevan Aug 11, 2026
bd9015f
care-intent: extract intent reconstruction as a standalone skill
Jacobjeevan Aug 19, 2026
c250322
care-loop: salvage mode — `care-loopd --pr <n>` enters the loop at an…
Jacobjeevan Aug 19, 2026
68d472a
repo: commit the dashboard launch config, ignore local editor/permiss…
Jacobjeevan Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "dashboard",
"runtimeExecutable": "npx",
"runtimeArgs": ["--yes", "tsx", "care-loop/orchestrator/src/cli.ts", "dashboard"],
"port": 3141
}
]
}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
care-loop/runs/
__pycache__/
.env
care-evals/results/
.claude/settings.local.json
.vscode/
666 changes: 666 additions & 0 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

837 changes: 837 additions & 0 deletions SKILL-REVIEW.md

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions care-ci-fix/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# care-ci-fix — CI failure fixer for the care-loop

Step 6b CI-fix track: when all bot review feedback has been addressed (6a verdicts clean) but remote
CI is still red, this skill reads the failing check's annotations and decides whether the **test** or
the **code** needs updating, then makes the bounded edit.

<!-- care-loop:methodology name="default" -->

## 1. Classification — the one judgment that matters

You receive:
- The **failing CI checks** with their annotations (file, line, assertion message).
- The **diff** of the change (`<base>...HEAD`).
- The **acceptance criteria** and **decisions** from the approved plan.

For each failing check / annotation, classify it into exactly one category:

### A. Test is stale (most common)
The test asserts the OLD behaviour that the change intentionally replaced. The plan's acceptance
criteria confirm the new behaviour is correct.

**Action:** update the **spec file** to assert the new expected value. Change ONLY the assertion(s)
that fail — do not rewrite surrounding test structure, add new tests, or refactor the spec.

**Locator / label drift (multi-file).** When the value your change altered is used not just in an
assertion but as a **locator or accessible name** — `getByRole(..., { name: /…/ })`, `getByText`, a
label/aria regex, a `waitForURL` fragment — a single output change can break that locator in *several*
specs at once (often as a navigation `.click()` that then times out, not an obvious assertion). When
CI reports multiple failing specs that all key off the same changed value, update that **one value in
every spec that references it** — a mechanical find-replace of the old token for the new. This is the
one case where you may touch more than two files (see §3): the edit is still a single-value swap, never
a change to test logic or structure. Use the CI-reported failing-spec list to find every consumer.

### B. Code is wrong
The test is correct — the change actually broke intended behaviour. The assertion failure reveals a
real bug in the source code.

**Action:** fix the **source file** to satisfy the test's assertion. Minimal edit — do not refactor
or add unrelated improvements.

### C. Infra / flake
The failure is unrelated to the change: network timeout, backend down, CI runner OOM, a flaky test
that fails intermittently regardless of the diff.

**Action:** do NOT edit anything. Return outcome `noop` so the loop hands off to a human rather than
making a spurious edit.

## 2. Decision procedure

1. Read each annotation's `path:line` + `message` (the assertion error).
2. Check whether the annotated file/line is in the diff or is a test that asserts a value the diff
changed. If yes → likely A or B. If the file is unrelated to the diff → likely C.
3. Cross-reference the plan's **acceptance criteria**: does the new behaviour (what the diff does)
match the criteria? If the test asserts the old value and the criteria say the new value is
correct → **A (test stale)**. If the criteria agree with the test → **B (code wrong)**.
4. If no plan context is available, reason from the diff: does the change intentionally alter the
value the test checks? If yes → A. If the change is unrelated to the assertion → C.

## 3. Guardrails — hard constraints on every edit

- **NEVER edit CI config or workflows** (`.github/**`, `.circleci/**`, `Jenkinsfile`, etc.).
- **NEVER weaken a test to pass**: no `.skip`, `test.fixme`, `test.todo`, `xtest`, `xit`, deleting
assertions, or wrapping assertions in try/catch. You may ONLY update an assertion's expected value
to the new intended value, or fix source code.
- **Scope = the failing check's files only.** Edit only the files cited in the annotations or the
source files directly responsible for the assertion failure. No repo-wide refactors.
- **Plan authority**: if updating the test would contradict the acceptance criteria or decisions
(the plan says the value SHOULD be X but the test expects X and the code produces Y), do NOT
change the test — the code is wrong (category B). If you cannot reconcile, return `handoff`.
- **One or two files max — with ONE exception.** If the fix requires touching more than two files,
return `handoff` — the failure is too complex for a bounded automated fix. The **only** exception is
locator/label drift (§1.A): a single changed value referenced across N specs may be updated in all N,
because each edit is the same mechanical token swap, not independent logic. Divergent fixes across
multiple files are still a `handoff`.

## 4. Output contract

Your edit should be the minimal change that makes the failing check pass:
- For category A: update the assertion expected value(s) in the spec file.
- For category B: fix the source code to satisfy the test's assertion.
- For category C: make NO edits.

After editing, stop. The orchestrator handles commit, gate, push, and the next CI round.

<!-- /care-loop:methodology -->
113 changes: 88 additions & 25 deletions care-diff-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@ name: care-diff-review
description: Reconstruct, from the code alone, what a CARE frontend (care_fe) diff does and what requirement it fulfills, and flag where the code fails to make that legible. The intent/legibility lens of /care-review (can run standalone). Use for "what does this change do", "is this readable / self-explanatory", "reconstruct the intent", or to verify a refactor is behavior-preserving. Defaults to diffing against develop; suggests rather than edits. For a full review (intent + approach), use /care-review instead.
user-invocable: true
argument-hint: "[develop | commit | working | <file>]"
model: opus # declared judgment tier — honored by the invoker (see care-review "Models"), not auto-enforced
---

# CARE Diff Review

**Premise: good code is self-readable.** A reviewer should be able to tell *what* a change does
and *why* (the requirement it fulfills) from the code alone — no commit message needed. This
**Premise: good code is self-readable.** A reviewer should be able to tell _what_ a change does
and _why_ (the requirement it fulfills) from the code alone — no commit message needed. This
skill reconstructs that intent from the diff, surfaces every place the code failed to convey it,
and confirms the reconstruction with the user. Wherever the reading was hard, that's the finding.

<!-- care-loop:methodology name="agreement" -->

## Working agreement (applies throughout)

1. **Suggest first, don't edit.** Propose changes; apply only after explicit approval.
2. **Smallest possible diff.** Fix the issue and nothing adjacent. Anything out of scope goes in
a one-line *Out of scope* note, not into the working tree.
a one-line _Out of scope_ note, not into the working tree.
3. **Don't change the contract or invent logic** to paper over something. Diagnose the cause; if
you don't understand why existing code is the way it is, ask — don't rewrite it.
4. **Match the codebase** — new code reads like the file around it (`CLAUDE.md`).
<!-- /care-loop:methodology -->

## Step 1 — Get the diff (default: against develop)

Expand All @@ -35,11 +39,11 @@ git diff $(git merge-base develop HEAD) > /tmp/care_review.diff && wc -l /tmp/ca

Override only when explicitly asked:

| User says | Command |
|---|---|
| "against the last/previous commit" | `git show HEAD` |
| "unstaged / working changes only" | `git diff` + `git diff --staged` |
| a specific file ("only this file") | scope the diff to that path |
| User says | Command |
| ---------------------------------- | -------------------------------- |
| "against the last/previous commit" | `git show HEAD` |
| "unstaged / working changes only" | `git diff` + `git diff --staged` |
| a specific file ("only this file") | scope the diff to that path |

**List the changed files first**, then review only those (read an unchanged file only if a
finding needs its context). **Do not read the commit message, PR body, or branch name yet** —
Expand All @@ -48,14 +52,12 @@ at the end.

## Step 2 — Reconstruct the intent from the code

For the diff as a whole, and for each distinct logical change, state plainly:

- **What it does** — the behavior change, in one or two sentences.
- **Why** — the requirement or problem it most plausibly fulfills, inferred from the code.
- **Confidence** — *high* if the code makes it self-evident; *low* if you had to guess.
Reconstruct, per change, _what it does_ / _why_ / a _confidence_ rating. This methodology is the
**`care-intent`** skill, extracted verbatim so it can run as a standalone maker-tier role and be
graded by care-evals — read `care-intent/SKILL.md` for it. Form the reading from the code first; the
commit message, PR body, and branch name are the answer key (see Step 1).

Reason from *this* code in *this* file. Read the actual control flow and data flow — don't
pattern-match to a catalog of known bugs.
<!-- care-loop:methodology name="findings" -->

## Step 3 — Legibility gaps (the core output)

Expand All @@ -65,41 +67,101 @@ the **minimal** change that would make the intent legible:
- **Misleading / vague names** → intention-revealing rename (a function should say what it does:
`releaseLocation` → `markLocationAsReserved`).
- **Purpose not evident from surrounding code** → smallest restructure (extract / split / move)
that makes it self-explanatory. Add a comment *only* where naming can't carry the meaning —
that makes it self-explanatory. Add a comment _only_ where naming can't carry the meaning —
a non-obvious "why", a BE quirk, a guarded edge case.
- **Fat handlers / mixed flows** → split so each path reads top-to-bottom and can be debugged in
isolation.

Keep every suggestion legibility-sized, not a rewrite. The bar is: *would another dev understand
this change, and the requirement behind it, by reading it cold?*
Keep every suggestion legibility-sized, not a rewrite. The bar is: _would another dev understand
this change, and the requirement behind it, by reading it cold?_

### Tier your findings for routing

Organize legibility findings by severity so care-loop can route them appropriately:

**`Broken` (blocks understanding — loop routes to Step 3 re-implement)**
- Code is actively misleading (a function name says "release" but does "reserve"; a comment describes old behavior)
- Intent is illegible despite reasonable effort to reconstruct (control flow is convoluted, no clear entry/exit points)
- A rename or small restructure is the minimal fix

**`Convention` (repo style — loop notes in round summary)**
- Violates a documented pattern in `CLAUDE.md` or the repo's conventions
- Example: event handlers should cite the event + expected side effect, per CLAUDE.md section 3.2
- Fix is straightforward once the rule is known

**`Polish` (optional — advisory only)**
- Minor readability improvements that are good-but-optional
- Extracting a loop to a named function when names already carry it
- Inline comments that could be refactored but the code is already legible

### Secondary — correctness

While reading, if the code plainly can't fulfill the intent it implies, flag it: a logic/edge-case
error, or a regression in the **other usages** of a shared component/hook/util/route the diff
touched (always check those). Only concrete, evidenced issues — no speculation.

**Spec-boundary check (don't hedge a boundary you can derive).** When a change implements tiers,
ranges, or thresholds and the criteria state exact boundary outputs, take each boundary value and
trace it through the guard — confirm the branch that fires there produces the required output. A
boundary that contradicts a stated criterion is a `Broken` correctness finding; you have the spec, so
derive the answer rather than downgrading to "low risk, confirm the boundary." (Watch for a gate
computed in one unit but displayed in another — the two can disagree only at the edge.)

### Refactor-safety mode

If the diff is described as "just readability / renaming / nothing should change", the headline is
a yes/no on behavior preservation. Classify every hunk as rename / move / reformat / extract
(safe) vs. anything that alters control flow, conditions, data sent to BE, effect timing, or
render output (flag loudly, however small).

<!-- /care-loop:methodology -->

## Step 4 — Confirm with the user

> **Dispatched as an agent by `/care-review`:** reconstruct intent **independently** from
> `/tmp/care_review.diff`, then **return** your reconstructed intent + legibility/correctness
> findings to the orchestrator. Do **not** confirm with the user — the orchestrator reconciles
> your intent reading against the other agent's and owns the single confirm.

Lead with the reconstructed intent: *"Here's what I read the change as doing, and the requirement
I think it fulfills — is that right?"* A mismatch means either the code isn't legible (fix the
>
> **Loop-invoked** (the `/care-review` call came from `care-loop`, signalled by a run dir
> `<care-loop skill dir>/runs/<repo>-<branch>/`):
> additionally write your **full** intent reconstruction — the complete per-change _what + why_,
> not the 1–2 sentence condensed version — to `<run-dir>/intent.md`, so Step 4b
> (`care-test-grade`) can grade the specs against it without a second reconstruction. Standalone
> invocations are unchanged — write nothing extra.

Lead with the reconstructed intent: _"Here's what I read the change as doing, and the requirement
I think it fulfills — is that right?"_ A mismatch means either the code isn't legible (fix the
code) or there's a latent bug (fix the logic) — resolve which. Then list legibility gaps and any
correctness finding, each `file:line` + minimal fix, ending with a one-line *Out of scope* note.
correctness finding, each `file:line` + minimal fix, ending with a one-line _Out of scope_ note.

Producing a full requirements doc is usually overkill — default to the one-or-two-sentence intent
per change. Only emit a longer per-change requirements summary if the user asks or the diff is
large. **Don't edit until approved.**

### Care-loop integration (Step 4a orchestrator)

When invoked by care-loop (Step 4a), tier your findings so the orchestrator can route them:

```
## Legibility findings

**Broken (blocks understanding)**
- <finding> → <minimal fix> (file:line)

**Convention** (repo style)
- <finding> → cite: <CLAUDE.md section> (file:line)

**Polish** (optional)
- <finding> (minor improvement)
```

- **Broken** findings loop back to Step 3 (implementer re-codes for legibility)
- **Convention** findings are noted in the round summary (fix if time permits)
- **Polish** findings are advisory (not loop-back candidates)

<!-- care-loop:methodology name="findings" -->

## Reference — what "legible CARE code" looks like

Use these to judge whether a change reads idiomatically (so intent is obvious), not as a
Expand All @@ -115,6 +177,7 @@ mandatory checklist. `CLAUDE.md` / `.cursorrules` win on conflict.
`src/components/ui` (shadcn — don't modify) + `CAREUI` before inventing a component; one
component per file.
- **Conventions** — user-facing strings via i18next → `public/locale/en.json`; API through
`query()`/`mutate()` wrappers + `{domain}Api.ts` route objects (`silent: true` to suppress
toasts); mobile = Drawer, desktop = Popover; truncation needs `min-w-0` on the constrained
parent + `truncate`; plugin-support changes shouldn't duplicate the core flow.
`query()`/`mutate()` wrappers + `{domain}Api.ts` route objects (`silent: true` to suppress
toasts); mobile = Drawer, desktop = Popover; truncation needs `min-w-0` on the constrained
parent + `truncate`; plugin-support changes shouldn't duplicate the core flow.
<!-- /care-loop:methodology -->
5 changes: 5 additions & 0 deletions care-evals/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
__pycache__/
*.pyc
care-evals/results/
care-evals/**/__pycache__/
**/.DS_Store
Loading