Skip to content

qa(checklist): clauses for the four defects 18.0 round 3 found outside the ledger, plus two RUNNER rules — a pin scores only the layer it drives, and every run keeps an off-clause probe budget #24802

Closed

Description

@objectstack-fleet

Filing gate: ③ a task the maintainer directed — the maintainer's words are quoted verbatim below.
Reader: a checklist-author dispatch from the 18.0 QA wave's dispatch session (session_01CfRDy7SuTfUqaTu2AEH2Hi): one ledger PR under docs/qa/platform-checklist/ (area files and RUNNER.md).
Dedupe (open AND closed), objectstack: "checklist RUNNER rule a pin scores only the layer it drives unit pin cannot score full stack clause" → 21 hits, none on this (nearest: #23950 and #21735, clause re-point families; #24173, a RUNNER wording fix); "QA runner off-clause exploratory probe budget findings beside the clauses checklist" → 92 hits, none on this (nearest: the anchor #24579, which collects re-points, not new clauses or rules).

Directed-by

In Claude Code session session_01CfRDy7SuTfUqaTu2AEH2Hi on 2026-10-20, the maintainer asked why round 3 (580fd4ed) found four defects that rounds 1 and 2 did not. The session's answer ended with this proposal, verbatim:

  • 补清单条款: 把这 4 个点补进测试清单:批量接口的空字符串 id、warning 规则的日志措辞、@ 提及的收件人要按读权限过滤、group 模式下没有当前组织的成员写入。按立卡门的规定,清单缺项是去补清单本身,不是立卡,可以用 checklist-author 技能来做。
  • RUNNER 加一条: 用自动测试判 walled 这类条款时,要核对测试走到了哪一层,单元级测试只能判单元级的条款。
  • 每轮留探测时间: 以后每轮都给 runner 留一段清单之外的探测时间。这一轮 4 张卡里有 2 张就是这样找到的。

The maintainer answered, verbatim: 「同意建议的改进」

Why these were missed

All four defective code paths were already present at round 1's subject 5b14b7f3. The rounds missed them for two reasons.

Scope

  1. Clauses, one per defect. Each gets a QA-source: citation, a revision bump and a history row. Each stays red until its card's fix lands, and its knownGaps names that card.
  2. RUNNER rule — a pin scores only the layer it drives. Before a pin scores a clause whose oracle is a public door's answer, the runner names the layer the pin reaches: a plugin unit, the engine, or HTTP. A pin that stops above the layer the clause's oracle sits at scores that clause partial, naming the missing layer. group posture: a member whose session has no active organization gets 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED on a tenant-scoped create, where isolated answers 403 naming the missing organization #24784 is the worked instance. Place it beside rule 6 (pin evidence), not inside the walled-boot entry.
  3. RUNNER rule — an off-clause probe budget. Each run keeps time after its clauses for probing the selector's doors past the clauses. Examples: boundary values (empty strings, missing or unknown ids), the opposite severity or posture of an asserted path, recipients outside the asserted scope. A finding that passes the filing gate is filed with QA-source: … · observed beside the clauses. The run record says how long the probes took and what they covered. In round 3 this budget found rest: POST /api/v1/batch answers 500 for an update or delete op whose id is the empty string, where a missing id answers 400 VALIDATION_FAILED #24781 and objectql(validation): an unevaluable severity:'warning' rule logs "write rejected: … fails closed" twice while the write is accepted 201 and persists #24782.

Not in scope: the round-3 re-points and accuracy findings in #24579 comment 6284472874. Those belong to the anchor lane.

Gates: node scripts/check-platform-checklist.mjs, plus whatever node scripts/pm/dispatch-gates.mjs --commands derives for the touched paths.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: maintainer-directed dispatch (18.0 QA wave, round-3 follow-up)
    Session: session_01CfRDy7SuTfUqaTu2AEH2Hi
    Account: os-warren (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24802-ledger-probe-rules
    Worktree: none — the author runs in its own cloud session checked out at origin/main a43405d596 or later
    Domain: domain:devx (self-applied on the filing side, SKILL exception two: the card's body carries the three gate answers; triage may re-route)
    Seat: domain:devx#1 (nominal, the absent-line default — this is the 18.0 QA wave's dispatch session acting on the maintainer's direct instruction quoted on the card, not a lane seat)
    File surface: docs/qa/platform-checklist/areas/api-backend.json, areas/records-forms.json, areas/access-security.json, docs/qa/platform-checklist/RUNNER.md, and coverage.json only if the checker requires it (stop on breach; explain in the report)
    Container & model: M, mode:cloud, model: opus (TIER_DEFAULT — dispatch-gates.mjs --tier on this surface reads "no path-derived mandate · floor sonnet · default opus · ceiling fable")
    Clause-②: no — the internal QA ledger and its runner protocol; nothing published
    Responsibility: n/a — not a defect card
    Thread-read: none
    Serial constraints cleared: the anchor #24579 (domain:devx, in flight) edits the same area files and RUNNER.md in rounds; round 10 (#24788) merged and no round PR is open now, so whichever lands second merges main. The record-discussion-mentions clause waits on #24785's fix PR merging (RUNNER rule 2).
    Directed-by: the maintainer, verbatim 「同意建议的改进」, in Claude Code session session_01CfRDy7SuTfUqaTu2AEH2Hi, 2026-10-20, answering the proposal quoted on the card.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24802,
      "status": "done",
      "branch": "claude/issue-24802-ledger-probe-rules",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24811",
      "session": "session_01MRkuLGosywLTY6EMcP6fGK",
      "premise_still_valid": true,
      "summary": "Three clauses landed, each red until its card's fix merges, each with QA-source, a revision bump, a history row and a knownGaps line naming the card. (a) api-backend.batch-transactional-discovery rev 6, acceptance[5]: an empty-string id on update/delete in POST /api/v1/batch answers 400 VALIDATION_FAILED like a missing id, never 5xx (#24781). (b) records-forms.validation-rule-type-matrix rev 5, acceptance[5]: an unevaluable warning rule lets the write land, and no log entry says it was rejected (#24782); fixtures.requires[2] carries the scratch-object recipe and closes round 2's fixture gap (QA run #24616 negative[0]). (c) access-security.no-active-org-session-semantics rev 6, acceptance[7]: the walled group leg asserts no 5xx and no NULL organization_id (#24784), and automated.ref now says the pin's group CONTROL stops at the plugin-security layer (stub terminal for the engine). RUNNER: rule 6 gains 'a pin scores only the layer it drives' (partial, naming the missing layer; #24784 as the instance), and a new rule 8 adds the off-clause probe budget; the run-record body contract gains the probe line. Clause (d) for #24785 is NOT written: fix PR #24794 is still an open draft (re-checked before the PR), so it waits for that merge, as stated in the PR body.",
      "tests": "Live on a stock showcase at a43405d596 (= branch base = origin/main), after pnpm build --concurrency=2 (76/76, os-verify-lock VERDICT command-exit 0). (a) red as expected: update with id '' -> 500 DATABASE_ERROR, delete with id '' -> 500 INTERNAL_ERROR, no-id controls -> 400 VALIDATION_FAILED 'Operation ... requires an id'; log '[REST] Unhandled error: Error: Update requires an ID or options.multi=true'. (b) red as expected: qa_vr_probe write 201, re-read 1 row, two log entries naming qa_unevaluable_warn both say 'write rejected' (the first, a multi-line entry with a CEL caret, also says 'fails closed'). The verify text now says to read each entry to its end. Error twin qa_vr_probe_err 400 VALIDATION_FAILED, fields[0] {_record, rule_violation}, 0 rows: negative[0] green. (c) not live-tested: it needs a walled boot, so per the dispatch it is written from knownGaps (evidence: #24783, #24784). Server stopped by process group, port freed. No ablation: the diff changes no tested behaviour.",
      "gates": "On head 1143504b: node scripts/check-platform-checklist.mjs exit 0 (OK — 16 areas, 328 items; 0 line citations survive; 943/953 symbol anchors, unchanged from base). dispatch-gates --commands derived 13, all exit 0: check-ci-filter-parity, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, lint check:doc-formula-expressions, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:platform-checklist, check:refd-timer-probe, check:watch-hint-literal. dispatch-gates --ran exit 0: 13 derived, 13 run, 0 NOT-MEASURED (the ran list carried no exit codes, so that zero is declared; the exit codes are in the PR body). coverage.json untouched. CI check-runs on #24811: in_progress at report time.",
      "mcp_calls": "10 — issue_read x6 (24802 get + comments, 24781, 24782, 24784, 24779), pull_request_read x2 (24794 twice), search_issues x2; no write tool",
      "api_writes": "2 — repository_dispatch to the fleet-write relay (pr_create #24811 with assignees [os-warren] and labels [skip-changeset], read back identical, run 39386966089 success); post-stamped.mjs issue comment on #24802 (this report)",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: named producer .claude/hooks/guard-main-checkout-bash.sh · evidence: a read-only curl command run from the worktree was blocked as a write into the primary checkout. The hook read a greater-than sign inside a double-quoted JSON -d argument ('\"condition\":\"int(record.title) > 1\"') as a redirect, target '1\"'. Its header promises precision-first and fail-open on unresolved shapes. Worked around by moving the request into a scratchpad .mjs file · dedupe words: guard-main-checkout-bash quoted redirect false positive, greater-than inside string literal",
        "carrier: none · noted, not filed — RUNNER environment fact: 'setsid nohup pnpm exec objectstack dev ... &' puts the serve grandchild in the group led by the setsid child, not $!, so kill -TERM -- -$! leaves the server listening. Stop the group of the listener's PGID, read with ps -o pgid. The round-3 record #24779 already proposes the setsid fact for RUNNER's table (anchor #24579 lane)"
      ]
    }

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions