diff --git a/docs/WORK_CYCLE.md b/docs/WORK_CYCLE.md index ffd0866..aaf2ee9 100644 --- a/docs/WORK_CYCLE.md +++ b/docs/WORK_CYCLE.md @@ -226,6 +226,33 @@ BASE="https://privacyllc.dev/api/internal/v1" AUTH="Authorization: Bearer $TOKEN" ``` +**Two things about refreshing that are worth knowing before you need them.** + +*The webhook must carry the signing secret.* `POST /repos/null/Queue-North-Website/hooks` +with a URL and no `secret` produces a hook that looks perfectly healthy in +Forgejo — `active: true`, test deliveries accepted with a 204 — and whose every +delivery is rejected by privacyllc.dev with `401 bad_signature`. Forgejo exposes +no delivery history through its API, so nothing anywhere says so. This repository +ran in exactly that state for ten minutes on 2026-08-18. The secret is +`FORGEJO_WEBHOOK_SECRET` in `~/.openclaw/credentials/privacyllc.md`. To prove a +delivery actually lands, sign a payload yourself and look for `"applied":true`: + +```bash +WHSEC=$(grep '^FORGEJO_WEBHOOK_SECRET=' ~/.openclaw/credentials/privacyllc.md | cut -d= -f2-) +# HMAC-SHA256 of the body, in X-Forgejo-Signature (hex, no "sha256=" prefix). +# X-Hub-Signature-256 is NOT accepted. +``` + +*A reconcile does not force a re-read.* Both `reconcile_all` and `sync_projects` +skip a project that is inside its freshness window, reporting `refreshed=0 +still_due=0` — which reads exactly like "nothing to do" and means "not yet due". +There is no per-project force in the agent API: `{"kind":"refresh"}` and +`{"kind":"reconcile"}` are both refused, and only `reconcile_all` and +`sync_projects` can be triggered. So a tracker change made minutes after a sweep +is not visible on the card until the next one, however many times you reconcile. +That is a wait, not a failure — but say so rather than reporting the numbers as +updated. + **Reconcile** — re-read the tracker and the pushed documents. Do this after the push, not before: @@ -250,13 +277,23 @@ curl -sk -X PATCH -H "$AUTH" -H "Content-Type: application/json" \ **A check-in** — a timestamped "what changed", when there is something real to report. `summary` is required and must say something; the API refuses an empty -"no change" update, deliberately: +"no change" update, deliberately. + +**`projectId` here is the UUID, not the slug.** Every other route in this API +takes the slug, and this one answers a slug with `{"code":"unknown","message": +"Something went wrong."}` — a generic 500 that says nothing about which field is +wrong, and which is identical to the error for a genuinely broken request. It +cost twenty minutes on 2026-08-18 and it will cost the next person the same +unless they read this line. Read the UUID from the project first: ```bash +UUID=$(curl -sk -H "$AUTH" "$BASE/agent/projects/queue-north-website" \ + | python3 -c 'import sys,json;print(json.load(sys.stdin)["project"]["id"])') + curl -sk -X POST -H "$AUTH" -H "Content-Type: application/json" \ - -d '{"projectId":"queue-north-website","health":"on_track", - "summary":"","accomplishments":"", - "blockers":"","nextActions":""}' \ + -d "{\"projectId\":\"$UUID\",\"health\":\"on_track\", + \"summary\":\"\",\"accomplishments\":\"\", + \"blockers\":\"\",\"nextActions\":\"\"}" \ "$BASE/agent/updates" ```