docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix - #1685
Draft
claude[bot] wants to merge 2 commits into
Draft
docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix#1685claude[bot] wants to merge 2 commits into
claude[bot] wants to merge 2 commits into
Conversation
`.github/instructions/logic.md` taught `broker.find('opportunity', { filters })`
— a data surface this repo does not have, in three separate ways at once:
* `broker` has zero occurrences under `src/`, and `@objectstack/runtime`
exports no `Broker` to import. Data access is ObjectQL through `ctx.api`.
* `filters` (plural) is not a predicate key and not an alias: the engine
rejects any option it does not recognise, so it throws on the first call.
The canonical key is `where`.
* `'opportunity'` names an object that does not exist — there is no runtime
prefix injection, so every business object name is written out as `crm_*`.
It is the same example #855 already retired from AGENTS.md; it survived in the
per-role briefs because they sat outside every gate until #1233 put them inside
one. Rewritten against the pinned 17.3.0 packages and `src/objects/_hook-api.ts`
rather than from memory: the method/option table (`count` narrower than `find`,
`top` not `limit`, `update` with the id inside the doc), the measured
`FILTER_OPERATORS` table with the retired `$regex`/`$options` called out, the
eight camelCase hook events, the real `Hook` / `HookContext` handler shape, the
sandbox's no-module-scope constraint, and the named-export `Action` shape.
`metadata.md` gets the `crm_` prefix half only: `name: 'crm_contract'`,
`reference_to: 'crm_account'`, and a Constraint Checklist entry so it does not
drift back. No object names were invented in the four briefs that name none.
Co-authored-by: Claude
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
This was referenced Sep 6, 2026
Two reasons, neither of which changes this PR's own scope. 1. The head commit carries a permanently-failed `Check Changeset` run. That run started 7s after the PR was opened; the `skip-changeset` label landed 1s later, but the job had already read a payload without it, so the workflow's `if: !contains(labels, 'skip-changeset')` guard let the job run and it failed 8s after starting. The `labeled` re-run skipped correctly, but the failed run stays attached to that head for ever and no event re-evaluates it. A new head is the only way to clear it without a rebase or a force-push. 2. The base had moved 18 commits since the PR was opened, so the last green `Build and Test` measured a base that no longer exists. One of those 18 touches the surface this brief documents: #1689 re-scoped the pin-claim comment in `src/objects/_hook-api.ts` from "measured on 17.2.0" to "first taken on 17.2.0, re-taken on the current pin 17.3.0". The brief already states 17.3.0, so the merge agrees with it rather than contradicting it. #1675, which gave `count` its own `HookCountQuery`, was already in this branch's history when it was cut and the brief was written against it. The diff against main is unchanged: `.github/instructions/logic.md` plus `.github/instructions/metadata.md`. Co-authored-by: Claude
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1678
.github/instructions/logic.md— the brief a backend agent reads before writing its first hook —taught
broker.find('opportunity', { filters }). That one line is wrong in three independent ways,and it is the same example #855 already retired from
AGENTS.md; it survived here because these sixbriefs sat outside every gate in the repo until #1233 put them inside one.
What was wrong, re-measured on
origin/main@a9a9a301The card's three greps were taken at
8c07f119; all three still hold on a freshmain:brokeris not a thing heregrep -rn '\bbroker\b' src/ | wc -l0(also 0 case-insensitively)grep -rc 'crm_' .github/instructions/*.md0sgrep -n 'filters' .github/instructions/logic.mdTwo further readings taken for this PR, both against the pinned 17.3.0 packages:
@objectstack/runtimeexports noBrokerat all — the brief'simport { Broker } from '@objectstack/runtime'never resolved to anything.FILTER_OPERATORSis 16 operators, and$regex/$optionsare retired (refused withINVALID_FILTER/ 400, prescribed replacement$icontains) — so the brief's four-row operatortable was both incomplete and shaped like a different stack's AST (
[['amount', '>', 50000]]).What this PR changes
logic.md— rewritten against the real surface (Q1, ruled by the maintainer's #1518 Option A:these briefs describe this workspace). Written from
src/objects/_hook-api.tsas it stands afterPR #1675 settled
HookQuery/HookCountQuery, plus the spec schemas — not from memory:ctx.api, cast once per hook asHookApiand guarded;ctx.api.object(...)directly in an action body. Object names always written out with
crm_.find/findOne(where?,fields?,top?),count(where?andnothing else — the engine's legal keys are
context, where),insert,update(the id travelsinside the doc; there is no
(id, doc)overload),delete. The three asymmetries a readercannot guess are stated as such, including that
top— notlimit— is how this repo caps a read.whereand onlywhere;filteris a live alias but a compile error here andcaught repo-wide by
test/hook-query-predicate.test.ts;filters(plural) throws;findOne({})throws rather than returning an arbitrary row.
where-document shape(
{ field: { $op: value } }), the$and/$or/$notgrouping, and the retired pair called out.beforeInsert…afterFind) replace thebefore_create/after_createvocabulary, which this stack's enum rejects; the handler takes onectx: HookContext(event,input,previous,user,api,id) rather than a broker, and theexample is a real
Hookliteral with a default export.pnpm verify: ahandler is lowered and runs body-only in QuickJS with no module scope, so its constants must be
declared inside it —
test/action-sandbox.test.tsruns that lowering pass over every hook.const … : Actionre-exported fromsrc/actions/index.ts, oneaction per export,
typefrom the measured six, implementation inbodyunder declaredcapabilities — not a bare exported arrow function.
metadata.md— thecrm_prefix only (Q2, ruled: fix it in the files that already name anobject, which today is these two).
name: 'crm_contract',reference_to: 'crm_account', and oneConstraint Checklist entry so it does not drift back — including the point that the file stays
unprefixed while the name does not. No object names were invented in the four briefs that name
none: that would be adding requirements.
Q3 is not implemented, by ruling. #1233's guard is not extended to read identifiers — this repo
does not grow a gate farm (AGENTS.md:431, same disposition as #1262). The recurrence protection is
already live: that guard put these briefs inside the gate, which is why this was found at all.
Verification
pnpm verifyfully green on12e211d0— all eight steps, run asvalidate,lint,lint:i18n-gate,hygiene,hygiene:tokens(exit 0 each), thentypecheck && buildandtestunder the shared heavy-verify lock (
VERDICT command-exit 0both times):Ablation — the #1233 guard really reads this file. Committed first, then mutated one
src/objects/_hook-api.tsmention tosrc/agents/(deleted by #512), proved the mutation landed ondisk (
grep -c 'src/agents/': 0 → 1, and no such directory exists), and ran the guard:Restored with
git checkout HEAD -- PATHand proved it by bytes —git hash-objectmatches theHEAD blob (
d46fc53a…) andgit diff HEADis empty — then re-ran:1 passed, 28 tests.Both guard rules still hold by construction:
logic.mdnamessrc/objects/andsrc/actions/inline (rule 1 does not go vacuous, and both exist), and neither file names any retired-layout path
(rule 2).
.github/instructions/**is in the control-byte hygiene scan; scanned clean.Landing
⛔ Draft, human floor.
.github/instructions/**isAGENTS.md-class (2026-08-25 grading on#1233): no auto-merge, not for the merge queue, no approval from an agent — the maintainer merges
this by hand. Same disposition as PR #1603 / #1677.
skip-changesetapplied: nothing ships from this PR (the precedent for this directory is #1518).⛔
.github/instructions/architect.mdis untouched — PR #1677 owns it;src/objects/_hook-api.tswasread but not touched, since #1676 is editing its comments.
Out of scope, filed separately
metadata.md's object-definition example teaches a shape the pinned spec rejects —reference_tois an unrecognized key (
FieldSchemaprescribesreference),@objectstack/specdoes not exportObjectSchemaat all (it is in@objectstack/spec/data, and the repo callsObjectSchema.create()with a named export, not
export default {…} as ObjectSchema). Same defect class, differentquestion from the prefix this card rules on, and the
reference_tohalf also appears inAGENTS.md,so it needs its own card rather than a rider here.
CI triage, 2026-09-06 — what was red, why, and what fixed it
Red:
Check Changeset, and nothing else. Read from the check-runs API for head12e211d0(the combined-status endpoint on this repo only ever returns Vercel, which is why this needed the other endpoint):Build and Test (22.x),Playwright,link-check,CodeQL,Analyze Code (javascript)andLabel Pull Requestwere allsuccess;Check Changesetappears twice — run34027799455failure, run34027805740skipped.The failing job's log, verbatim:
Cause — a label race at PR-open, not a stale base.
changeset-check.ymlgates the job onif: !contains(github.event.pull_request.labels.*.name, 'skip-changeset'), and that is evaluated against the payload of the event that started the run:Check Changesetstarts from theopenedpayload — no labels on it yetskip-changesetapplied — one second too late for the run already in flightlabeledre-run fires and skips, correctlySo this PR has carried that red since 15 seconds after it was opened — nothing turned red later. A workflow run is never re-evaluated, so the failed run stays bound to
12e211d0for ever, and re-running it would only replay the same label-less payload.The stale-base hypothesis was tested and killed as the cause.
mainhad really moved 18 commits past this PR's base8dccbbba, so the last greenBuild and Testmeasured a base that no longer exists — but the branch verified green both as it stood and after the merge, so the staleness was not the red. One of those 18 does touch the surface this brief documents: #1689 re-scoped the pin-claim comment insrc/objects/_hook-api.tsfrom "measured on 17.2.0" to "first taken on 17.2.0, re-taken on the current pin 17.3.0". This brief already states 17.3.0, so the merge agrees with it. #1675 (countgetting its ownHookCountQuery) was already in this branch's history when it was cut, and the brief was written against it. Nothing was relaxed, skipped or deleted to reach green.Fix: merge
maininto the branch (commit8faec05c). That refreshes the base and gives the PR a head whoseCheck Changesetrun is evaluated withskip-changesetalready applied. No rebase, no amend, no force-push; the PR's own diff is unchanged — still.github/instructions/logic.mdplus.github/instructions/metadata.md, and.github/instructions/architect.mdremains untouched (PR #1677 owns it).Gate re-run on
8faec05c, exit code captured before any pipe:pnpm test:coveragealso exit 0 —All files 95.93 | 84.77 | 95.87 | 99.36. The E2E (Playwright) andlink-checkworkflows are not part ofpnpm verify; they re-run in CI on this head.Posture unchanged: still a draft, no auto-merge, no merge queue, no approval. The maintainer merges it by hand.
Generated by Claude Code