Skip to content

.github/tasks/autonomous_feature_dev.md:20 still tells the agent to check reference_to — the fourth teaching site for a key FieldSchema rejects, and the one #1686 could not reach #1812

Description

@zhuangjianguo

Found by #1686's dev while correcting the other three sites, and correctly not fixed there: it sits outside that card's declared file surface, so touching it would have been an undeclared widening. Filed by the repo:hotcrm seat at ACCEPT of PR #1809, per the acceptance-notes rule.

The citation

.github/tasks/autonomous_feature_dev.md:20 instructs the agent:

Ensure all foreign keys (reference_to) point to valid objects defined in Phase 2.

Why it is the same defect as #1686

reference_to is not a key on FieldSchema. Measured against the pinned @objectstack/spec 17.3.0, the engine answers:

Unrecognized key(s) on this field: reference_to. Did you mean reference_to → reference? Until this shape was closed these were dropped silently — the field was still created, minus whatever the key was meant to constrain, protect or compute.

⚠️ That tail is why this matters more than a spelling: before the shape was closed, an author following this instruction got a field that was created but silently stripped of the constraint they wrote. The canonical authoring form is the factory — Field.lookup('crm_account', { label: 'Account' }) — which is what all 18 src/objects/*.object.ts files use (0 raw reference_to among them, re-measured on PR #1809).

#1686 fixed three sites and stopped exactly at its surface, which is why this one survives:

site status
AGENTS.md:62, :141, :348 ✅ corrected by PR #1809
.github/instructions/metadata.md ✅ corrected by PR #1809
.github/tasks/autonomous_feature_dev.md:20 ⛔ this card

⇒ after PR #1809 merges, this is the last place in the repo that still teaches the retired key to an agent. It also refines a Zone 2 answer on #1686: :141 is the only such checklist entry in AGENTS.md, but not in the repo.

What a fix decides

Narrow. The batch #74 ruling on #1686 already settled the direction for this exact class — the brief stops teaching a raw key at all and names the factory instead — and this file is a consumer of the same prescription. The likely edit is one sentence: check that lookup / master-detail targets name real objects, matching the wording PR #1809 landed at AGENTS.md:141.

⚠️ Re-read AGENTS.md and .github/instructions/metadata.md at your own commit first and mirror the wording that actually landed, rather than the wording quoted here. ⛔ Do not invent a third phrasing for the same rule — three files saying it three ways is how this class recurs.

Three carried items, all with this card as their named carrier

#1686's dev reported these as noted, not filed, each pointing here:

  1. Five test/*.ts files read reference_to as a tolerant alias (f.reference ?? f.reference_to ?? f.referenceTo). They pass today; the alias branch is dead tolerance, not a reproducible defect. ⛔⛔ test/** is epic Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first, os lint --strict first, then retire the local re-implementations by family #1579's fenced territory — do NOT touch these here. Recorded so the next reader knows they exist and that they are deliberate.
  2. test/opportunity-line-item-add-picker.test.ts:91 carries a comment calling reference_to "the authoring-side word AGENTS.md uses". PR docs: stop teaching the retired reference_to key and an object shape the repo never uses #1809 makes that sentence false. Same fence: ⛔ not this card's to fix.
  3. Field examples 1 and 2 in metadata.md remain raw object literals rather than Field.text(...) / Field.select(...). Both parse clean ⇒ style divergence, ⛔ not a defect. Deliberately left alone.

⇒ items 1 and 2 need a test/** authorisation that does not exist. ⛔ Do not seek one on this card; they are inert today.

⚠️ A governance question this card surfaces but does NOT decide

The governed set landed by PR #1798 (AGENTS.md:578) is, verbatim and deliberately un-widened: AGENTS.md, CLAUDE.md, .claude/**, .github/instructions/**.

.github/tasks/** is not in it — so by the letter of the rule, a PR touching only this file is not governed and lands via auto-merge, even though it is an agent-instruction surface of the same kind as .github/instructions/**. That may be intentional or may be a gap.

⛔ The seat does not widen the governed set — that is gate strength and sits on the manual floor. Recorded here and raised to the maintainer in the R58 round report. This card proceeds as non-governed unless the maintainer says otherwise.

Refs: #1686 (the ruled sibling, three sites) · PR #1809 · #1678 · #855 · batch #74 ruling (issuecomment-5566140153)

Activity

  1. added
    documentationImprovements or additions to documentation
    pm:queueReady for the PM dispatch loop
    on Sep 9, 2026
  2. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 9, 2026
  3. self-assigned this
    on Sep 9, 2026
  4. zhuangjianguo commented on Sep 9, 2026

    @zhuangjianguo
    CollaboratorAuthor

    Claim: PM loop round R58
    Session: session_017FzrA1G4U89KEMf7wfLmqq
    Branch: claude/issue-1812-tasks-brief-drops-reference-to
    Worktree: hotcrm-issue-1812
    Domain: repo:hotcrm (single-lane repo — ⛔ no domain:*)
    File surface: .github/tasks/autonomous_feature_dev.md, .changeset/ (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: default judgement tier
    Clause-②: no
    Thread-read: 5601567405-sibling — the grading comment on this card is the newest; ⛔ no other comment exists
    Serial constraints cleared: .github/tasks/autonomous_feature_dev.md — no in-flight card, no queued card touches it. ⭐ The upstream sibling is landed: PR #1809 (#1686) MERGED as bd6a5a5, so AGENTS.md and .github/instructions/metadata.md already carry the corrected wording you must mirror. In flight beside you: #1797 (CONTRIBUTING.md), #1808 (content/docs + one ledger line) — ⛔ disjoint.

    Dispatched to a dev, who inherits this claim — ⛔ the dev posts no second claim and does not touch the assignee.

    What this is

    The fourth and last site in the repo that teaches an agent the retired reference_to key. #1686's dev found it, correctly refused to touch it (outside its declared file surface), and reported it. Read this card's grading comment in full — it is the ruling.

    Zone 1 — the direction is already ruled

    Decision batch #74 on #1686 (5566140153, maintainer 「同意」) settled the class: stop teaching a raw key at all; name the factory instead. This file is a consumer of the same prescription.

    .github/tasks/autonomous_feature_dev.md:20 currently says:

    Ensure all foreign keys (reference_to) point to valid objects defined in Phase 2.

    ⭐ Mirror the wording that actually landed, do not invent a third phrasing. PR #1809 put this at AGENTS.md (now on main): "Do all lookup / master-detail targets name real objects?" ⛔ Three files saying the same rule three ways is exactly how this class recurs.

    Zone 2 — PM mechanism assumptions (⚠️ must be tested)

    1. Read AGENTS.md and .github/instructions/metadata.md at your own commit first, and take their landed wording as the source. My quote above is from the merged diff, but ⛔ re-read rather than trusting it.
    2. I assume :20 is the only reference_to mention in .github/tasks/. ⚠️ Measure the whole directory, not just that file — the last three cards each found one more site than expected. If there is another, it is inside your file surface only if it is in .github/tasks/; anywhere else, report it, ⛔ do not widen.
    3. ⭐ After your edit, the repo should contain zero reference_to teaching sites. Verify that with a repo-wide grep and pair the zero with a control word — the five test/*.ts tolerant-alias reads (below) will still match, so a naive zero is impossible and a naive non-zero proves nothing. State precisely what you counted.

    ⛔ Out of bounds

    ⚠️ Landing — leave the flip to the seat on this one

    .github/tasks/** is not in the governed set landed by PR #1798 (AGENTS.md, CLAUDE.md, .claude/**, .github/instructions/**), so by the letter of the rule this PR is non-governed and auto-mergeable. ⚠️ But it is an agent-instruction surface of the same kind, and the seat has raised that gap with the maintainer rather than deciding it.

    ⇒ Open the PR as a draft and leave it there. ⛔ Do not mark ready and ⛔ do not arm auto-merge. Report when your gates are green and the seat will make the call once the governance question is answered. That costs you nothing and removes the only way this card can go wrong.

    Include a ## 维护者速读(草稿) section in the PR body (Chinese, business framing, 席位意见 left blank) in case it turns out to be governed.

    Gates

    pnpm verify = validate && typecheck && lint && lint:i18n-gate && hygiene && hygiene:tokens && build && test; capture the exit code before any pipe. Changeset required — empty frontmatter is the sanctioned "releases nothing" shape and is the right one here (agent-facing docs, nothing ships to users).

    Report

    Terminal report to this issue first, then as the return message. Machine-checkable fields only — gates / line_budget / deviations / files_changed. ⚠️ A declared deviation is a question for the seat; an undeclared one is a decision taken on the seat's behalf.


    Generated by Claude Code

  5. claude commented on Sep 9, 2026

    @claude
    Contributor

    os-dev-report

    {
    "issue": 1812,
    "status": "done",
    "branch": "claude/issue-1812-tasks-brief-drops-reference-to",
    "pr": "#1817",
    "premise_still_valid": true,
    "summary": "The one reference_to teaching line at .github/tasks/autonomous_feature_dev.md:20 now reads 'Ensure all lookup / master-detail targets (Field.lookup(...) / Field.masterDetail(...)) name real objects defined in Phase 2.' — every fragment lifted from what PR #1809 landed (AGENTS.md:141 for the noun phrase and verb, :62/:348 for the factory parenthetical), with the brief's own 'defined in Phase 2' anchor kept. The whole .github/tasks/ directory was measured, not just that file: reference_to appears there exactly once, now zero. Plus one changeset with empty frontmatter. PR #1817 is a draft and stays one — ready-flip and auto-merge left to the seat, as ordered.",
    "gates": {
    "command": "pnpm verify",
    "exit_code": 0,
    "exit_captured": "pnpm verify > log 2>&1; EXIT=$? (before any pipe)",
    "wall_seconds": 187,
    "commit": "9b6ac5f",
    "links": {
    "validate": "PASS — 'Validation passed (1552ms)', Data: 18 Objects 331 Fields",
    "typecheck": "PASS — tsc --noEmit, no diagnostics",
    "lint": "PASS — '1 warning(s), 12 suggestion(s)'; the warning is the pre-existing sales_home_page page:card description, untouched (this diff has no src/ file)",
    "lint:i18n-gate": "PASS — 'i18n lint gate: 0 i18n/missing-* issues'",
    "hygiene": "PASS — 'source hygiene clean'",
    "hygiene:tokens": "PASS — 'source token ratchet clean'",
    "build": "PASS — 'Build complete (1940ms)', Data: 18 Objects 331 Fields",
    "test": "PASS — 'Test Files 165 passed (165)', 'Tests 3453 passed | 1 skipped (3454)'"
    },
    "ci_on_9b6ac5f": "8/8 completed success (Build and Test 22.x, Check Changeset, link-check, Playwright, CodeQL, Analyze Code, Label Pull Request, Vercel Preview Comments) — one status read, no polling and no wait loop",
    "labels": "ci/cd, applied by the repo's own 'Label Pull Request' workflow; none applied by hand"
    },
    "line_budget": {
    "diff_vs_branch_point_7ddc88b": "+46 / -1 across 2 files",
    "target_file_lines": "23 before, 23 after (one line replaced in place)",
    "source_token_ratchet": "authored total ~137,092 tokens, ceiling ~140,000 — unchanged, byte-identical to the parent commit because nothing under src/ moves",
    "note": "anchored on the recorded branch point 7ddc88b, NOT on origin/main, which advanced to 5c329c6 during the run"
    },
    "files_changed": [
    ".github/tasks/autonomous_feature_dev.md (1 line replaced)",
    ".changeset/tasks-brief-names-the-lookup-factory.md (new, empty frontmatter)"
    ],
    "deviations": [
    "WORDING: the replacement carries the factory parenthetical '(Field.lookup(...) / Field.masterDetail(...))' in addition to AGENTS.md:141's bare checklist text. Both fragments are verbatim from AGENTS.md (:141, and :62/:348), so this is a mirror rather than a third phrasing, but the combination appears in no single landed sentence. Reason: batch #74 ruled 'stop teaching a raw key, name the factory', and in THIS file there is nowhere else to learn the factory — the role file it loads (.github/instructions/architect.md) names no field factory at all, and it is the sibling new-feature.md, not this brief, that points at .github/instructions/metadata.md. Revert to the bare :141 wording on one word from the seat.",
    "CHANNEL: the REST /search/issues endpoint is blocked for this session ('sessions are bound to their configured repositories'), so dedup was done with 2 targeted MCP search_issues calls instead of REST list + local grep. Declared per the channel-switch rule.",
    "BASE: the worktree was cut from origin/main at 7ddc88b, not the dispatch tip bd6a5a5 (#1813 had landed in between). bd6a5a5 is in this branch's history, so PR #1809's wording was read at my own commit as ordered. origin/main advanced again to 5c329c6 mid-run; every diff and count in this report is anchored on 7ddc88b.",
    "COUNT: the card and the dispatch both say five test/.ts files read reference_to. Measured: FOUR files, FIVE lines — lead-duplicate-management.test.ts (2 lines), sharing-coverage.test.ts, view-references.test.ts, and opportunity-line-item-add-picker.test.ts:91 (the now-false comment, not an alias read). Nothing under test/** was touched either way.",
    "FINDINGS NOT FOLDED IN: #1818's first site is line 17 of THIS file — one line above the one I changed, inside the declared file surface. It was filed, not fixed, because it is a different defect class (a non-existent metadata type and file suffix, ruled by #852) from this card's (a retired key replaced by naming its factory, ruled by batch #74). Folding it in would have widened a card whose landing question is already open. Say the word and it is a two-character follow-up.",
    "GOVERNED PATH NAMED, NOT TOUCHED: #1818's second site is .github/instructions/automation.md, which IS in the governed set. Reported only."
    ],
    "tests": "pnpm verify exit 0 at 9b6ac5f, 187s, exit code captured before any pipe; all eight links ran and printed the verdict lines quoted in gates.links above (165 test files / 3453 tests passed, 1 skipped). CI on the same sha: 8/8 success. No ablation or reverse-verification run: the diff is one documentation sentence plus a changeset, adds and changes no guard, and touches no code path — there is nothing that could be made to fail. MEASUREMENT with controls, each zero paired with a hit that proves the command is live: reference_to lines under .github/ = 0 after (control: Field.lookup under .github/ = 2, so the pathspec matches); reference_to teaching sites repo-wide = 0; reference_to lines repo-wide = 10, all non-teaching (3 in PR #1809's changeset, 2 in docs/archive/2026-02/, 5 across 4 fenced test/
    .ts files). For #1818: WorkflowRuleSchema in node_modules/@objectstack/ = 0 files (control: FlowSchema present in @objectstack/spec/dist), src//*.workflow.ts = 0 files, src//*.flow.ts = 22. For #1819: packages/, pnpm-workspace.yaml and base.tsconfig.json all absent (control: root tsconfig.json present, 18 metadata dirs under src/).",
    "mcp_calls": "4 — issue_read get, issue_read get_comments, and 2 targeted search_issues for dedup. Everything else (branch push, PR create and 2 body patches, 2 issue creates, all status reads) went over repo-scoped REST.",
    "open_questions": [
    {
    "question": "Is .github/tasks/** governed? PR #1817 touches only that path plus .changeset/, so by the letter of AGENTS.md 'How a green PR lands' it is non-governed and a seat may land it — but it is an agent-instruction surface of the same kind as .github/instructions/.",
    "options": [
    "A — treat as non-governed (the letter): a seat flips it ready and arms auto-merge",
    "B — treat as governed (the kind): it stays a draft and the maintainer merges it",
    "C — widen the governed set to include .github/tasks/
    , which decides this PR and every future one"
    ],
    "recommendation": "No recommendation offered, deliberately: gate strength sits on the manual floor and the seat has already put C to the maintainer. The PR is left as a draft with auto-merge unarmed, which is correct under A and B alike, so nothing has to be decided for it to be safe. A '## 维护者速读(草稿)' section is in the PR body in case C lands."
    }
    ],
    "out_of_scope_findings": [
    "filed as #1818: .github/instructions/automation.md §1 and .github/tasks/autonomous_feature_dev.md:17 still teach a *.workflow.ts metadata type — WorkflowRuleSchema has 0 occurrences in node_modules/@objectstack/, src/ has 0 .workflow.ts and 22 .flow.ts; same class as #852, and one site is in a governed path",
    "filed as #1819: .github/tasks/new-package.md prescribes the retired packages/[NAME]/ scaffold in full — no packages/, no pnpm-workspace.yaml, and no base.tsconfig.json (the file its step 4 says to update) exists; same class as #1518, and the fix is a real route choice (delete / repurpose / keep), not a one-line mirror",
    "noted, not filed: PR #1809's changeset says the tasks brief 'still instructs the agent to check ...'. It is an accurate record of that PR's own scope decision, so it was left alone rather than rewritten; this PR's changeset closes the loop instead, and both ship in the same release. Carrier: the release-notes reader, who sees both entries together.",
    "noted, not filed: 'FEATUE' typo at .github/tasks/autonomous_feature_dev.md:7. Style, in the copy-paste placeholder; no runtime meaning. Carrier: #1818 or #1819, whichever next edits this directory.",
    "noted, not filed: the five test/
    items named in the card (four tolerant-alias reads plus the now-false comment at opportunity-line-item-add-picker.test.ts:91). Known, inert, epic #1579's fence — not touched, and no authorisation sought."
    ]
    }


    Generated by Claude Code

  6. zhuangjianguo commented on Sep 9, 2026

    @zhuangjianguo
    CollaboratorAuthor

    ✅ ACCEPT — PR #1817. Landing it under the declared veto-window default, ⛔ not by deciding the governance question.

    repo:hotcrm seat · session session_017FzrA1G4U89KEMf7wfLmqq · R58 review, 2026-09-09T12:4xZ. Verified against the diff and the workflow runs — ⛔ not against the report.

    Checklist

    item reading
    changed files 2: .github/tasks/autonomous_feature_dev.md (+1/−1) and the new changeset — inside the declared surface ✅
    the edit the bullet is the only line that moves; the file is 23 lines before and after ✅
    wording mirrors what PR #1809 landed — "lookup / master-detail targets" + "name real objects" from AGENTS.md:141, the factory parenthetical from :62/:348, and the brief's own "defined in Phase 2" anchor kept ✅
    ⛔ test/** untouched ✅
    ⛔ governed paths untouched — AGENTS.md and .github/instructions/** not opened ✅
    CI 6/6 workflow runs on head 9b6ac5f completed / success. Nothing pending, nothing failed ✅
    draft held ⭐ yes — the dev did not flip it, exactly as ordered ✅

    ⭐ This closes the set. reference_to now has zero teaching sites repo-wide, and the dev proved it the right way — each zero paired with a control that must hit (reference_to = 0 under .github/, control Field.lookup = 2 there, so the pathspec is live), with the 10 surviving matches enumerated and each accounted for as non-teaching: 3 in PR #1809's changeset, 2 in docs/archive/, 5 across 4 fenced test/*.ts files.

    ⭐ It corrected the seat's own count

    The card and my dispatch both said "five test/*.ts files". Measured: four files, five lines — and one of those five is the stale comment at opportunity-line-item-add-picker.test.ts:91, not an alias read at all. I propagated that figure from #1686's dev without re-measuring it. ⇒ corrected here; ⛔ the "five files" figure is dead and should not be re-quoted.

    The one declared deviation — accepted

    The replacement carries the factory parenthetical in addition to :141's bare checklist text. Both fragments are verbatim from AGENTS.md, but the combination appears in no single landed sentence. Accepted, and the reason is the good one: this file is handed to an agent as a whole prompt, and the role file it loads (.github/instructions/architect.md) names no field factory at all — it is the sibling new-feature.md, not this brief, that points at metadata.md. ⇒ a bare :141 mirror would tell an agent to check something it has not been told how to write. ⛔ That is not a third phrasing; it is the same rule assembled for a reader who arrives without the other files.

    ⭐ And it refused to fold in the adjacent line

    #1818's first site is line 17 of this very file — one line above the one it changed, inside its declared surface. It filed rather than fixed, because it is a different defect class (a non-existent metadata type, ruled by #852) from this card's (a retired key, ruled by batch #74). ⭐ That is the harder call and it made the right one: convenience of proximity is not scope, and folding it would have widened a card whose landing question was already open.

    ⚠️ Landing — the veto-window default executes; the class question stays open

    I told this dev to hold the flip so a landing could not pre-empt the governance question. It held. Now the seat decides, which is what "reserved to the seat" meant.

    Landing it. Reasoning, stated so it can be overruled:

    ⛔ What this does NOT decide: the class. #1818's second site is .github/instructions/automation.md, which IS governed — so that card genuinely needs the answer, and it is not dispatched until it has one. The question stands with the maintainer, unchanged.

    ⭐ Note the ordering that made this safe, learned from #1808 an hour ago: arming auto-merge on a PR whose checks have already finished merges it immediately. So the review had to come first — and it did.


    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

Labels

documentationImprovements or additions to documentation

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions