Register the progress-report generator as a #123 task-registry entry #136
Labels
No labels
agent
blocked
foreground
needs-andrew
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
Tabled
needs-andrew
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
kreeader/kreeader-server#136
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to the kreeader-docs progress-report CI job (v1 runs in Forgejo CI per Andrew's spec: additive workflow, read-only everywhere, CI secrets, generated-label output, weekly windows, MEASURED/ATTRIBUTED/FORECAST tiers, deterministic generator — no LLM). v2: register the generator in the Server Health task registry so it gains Run-now and task_runs history alongside the other scheduled tasks. Requires the generator to be invocable server-side (or via a task-registry exec seam) without weakening the read-only guarantees — the task entry must run with the same read-only role, not server credentials.
The generator this issue refers to has landed in
kreeader-docsmaster (commits7b14663+3dc3bbf) — noting it here rather than filing a duplicate issue.What exists now:
.forgejo/workflows/progress-report.yml— new, isolated,workflow_dispatchonly (no cron until a sample is approved). Nothing inbuild-and-release.ymlorscripts/build.shwas touched.scripts/progress-report/— deterministic generator (psycopg+requests, pinned), the versioned rule set (rules.py,PR-001..PR-007), the digest seam (suggestions.py), a versioned prompt, and unit tests for window arithmetic / tier labelling / rule firing.scripts/render-progress-report.sh— reusesdocs/_shared/preamble.texwithout entanglingbuild.sh.docs/_generated/progress-report.md, with its data digest atdocs/_generated/digest.json.Access profile, for the registry entry: Forgejo REST GET only; Prometheus
query_range+/api/v1/metadataathttp://192.168.3.9:9099(LAN-open, a plain variable, not a secret); Postgres SELECT only as thekreeader-docsrole in aREAD ONLYsession. No writes, no deploys, no restarts. SecretsREPORT_FORGEJO_TOKENandREPORT_PG_DSNreach the job through the environment only.Every number is produced by deterministic code. The one place a language model is allowed is the labelled advisory subsection 4b, which is assembled from the report's own digest through an input-file seam and is non-blocking — absent or broken input degrades to a sentence and the report still succeeds.
Done on branch
fix/openapi-tags-and-report-task(commit4b9641e). Not merged, not closed. kreeader-docs is untouched — the docs-side wiring is specified below for the orchestrator to add there.Shape: a seam, not a runner. #123's registry is explicitly a view over schedulers that already run in the server. The progress-report generator does not, and this issue's constraint is that registering it must not move it or weaken its read-only guarantees. So the server gains no ability to execute it; what it gains is a memory of what was reported and the ability to notice when nothing was.
New registry entry kind (
api/healthtasks.go)External— runs outside this process. Run-now answers 501 naming where the work happens (newErrTaskExternal, distinct fromErrTaskNotRunnable: "runs elsewhere" and "runs on its own trigger" are different facts). A button that could only ever fail is worse than none.CadenceSeconds— the declared expectation. Without it, "stopped" and "between runs" are the same observation, and silence stays undetectable.GraceSeconds— how late is late. A weekly CI job slips by hours for ordinary reasons; raising at the first minute past due would train the operator to ignore the panel, which is the failure #123 exists to prevent.progress-report— kreeader-docs CI, cadence 7 days, grace 36 hours.The external-report contract
/api/admin/health/*.{name}must be a declared external task. An unknown name — or an in-process task — is 404, never an auto-created entry: a POST must not be able to invent a scheduled task nobody scheduled, and a typo in a workflow has to fail loudly instead of accumulating history under a name no one reads.started_at,result.finished_atdefaults to now and must not precedestarted_at.urlmust be absolute http(s).summarytruncated at 500 chars.db.RecordTaskRunwrites one already-finished row;StartTaskRun/FinishTaskRunremain for work this process watches). A run that took nine minutes elsewhere did not take zero seconds here.skippedsurvives as itself — a generator that found nothing new ran correctly but published nothing, and flattening that tookwould lie about it.400with its reason. A weekly job gets one chance per run to be right.202with the task view,400 invalid_payload,401/403,404 not_found.Raise-or-bump wiring
external_task_missed(warn, scope = task id) is raised by a derived emitter registered throughhealth.RegisterRefresher, exactly like the Metron latch and the correction stall — "has not reported" is a state, so nothing can raise it at a call site and opening the Issues tab reconciles it.last_run + cadence + grace.cadence + grace. There is no other honest clock without a run to count from. Stated trade-off: a server restarted more often than the cadence will not raise the never-reported case, so an unwired workflow is caught by the first report that never comes rather than by the first restart. This is in the code comment and the doc, not hidden.external_task_failed(warn) covers a reported failure: it happened, so it is not "missed", but nobody should have to read the run history to notice. A later non-error run resolves it.Also:
TaskRungains aURLcolumn (additive, AutoMigrate) so a run that published something links to it; the task view gainsexternal+expected_every_secondsso the UI renders "runs in kreeader-docs CI" rather than a dead button.openapi.yamlmirrors the endpoint (taggedHealth & Opsper #137) plus theExternalTaskReportschema and the newHealthTask/HealthTaskRunfields.The exact call the kreeader-docs workflow must add
Full write-up in
docs/external-tasks.mdon the branch. First step of the progress-report job:Final step,
if: always()so a failed generation still reports (a failure that reports is visible; a failure that stays quiet is indistinguishable from a run that never started):Notes for whoever wires it:
KREEADER_ADMIN_TOKENis a server admin credential and belongs in CI secrets. It is not one of the generator's read-only inputs and must not be used for anything the generator reads — appending one row to its own run history is the whole of its authority here.result: skippedwhere the workflow deliberately publishes nothing (no changes in the window), notok.urlonly when a release was actually published; omit it rather than sending an empty or relative value (a relativeurlis a 400).Tests —
api/healthtasksexternal_test.gopins the four properties that would otherwise put the generator back where this issue found it: the runner's timestamps survive into the history; malformed reports and unknown names are refused without writing anything; Run-now is 501 and opens no run row; silence raises exactly one issue that bumps rather than duplicates and is resolved by the next report.Gates:
GOWORK=off CGO_LDFLAGS=-lprotobuf go build ./...clean,go vet ./...clean,go test ./api/ -count=1ok (18.7s).Merged to master (the tag test immediately caught five operations from branches merged after this one forked — tagged at merge). #137 closes when kreeader-docs retires its workaround on the next reference render; #136 closes once the docs workflow posts its first report (needs an admin credential in kreeader-docs CI secrets — queued for Andrew).