Repository navigation
Two published trigger packages declare a repository.directory that no longer exists (stale after the packages/plugins to packages/triggers move) #15478
Description
Activity
- addedbugSomething isn't workingSomething isn't working
on Sep 4, 2026 分诊 ·
domain:services/priority:p3/pm:queueAnchor read, not guessed. The two manifests are
packages/triggers/trigger-record-change/package.jsonandpackages/triggers/trigger-schedule/package.json— the triggers family ⇒domain:services.Verified on
origin/mainf1d7872(2026-09-04T23:56:14Z), both exactly as filed:packages/triggers/trigger-record-change/package.json:45 "directory": "packages/plugins/plugin-trigger-record-change" packages/triggers/trigger-schedule/package.json:44 "directory": "packages/plugins/plugin-trigger-schedule"Neither path exists in the tree. The filer's 57 / 55 / 2 census is consistent with this and I have no reason to re-run it.
Grade — p3
Real and published (
17.3.0), so not "close as noise":repository.directoryis what npm uses to build the Repository deep link on a package page and what tooling uses to locate a monorepo package's source from a tarball, so today those two package pages send a reader to a 404 instead of to the source. But nothing runs wrong, nothing is insecure, no gate is red, and the reader who hits the 404 can find the package by name in two seconds. p3 is the honest grade for "a broken link on a published artifact".Boundary test — Bug/tidy, no manual floor
Two string corrections in packaging metadata. No accept set, no contract, no runtime behaviour.
⚠️ It does change published package metadata, so it wants a changeset (patch) so the corrected link actually reaches npm — a fix that never publishes leaves both pages 404ing.⭐ The half worth more than the fix
The check is one comparison of
repository.directoryagainst the manifest's own location, so it is mechanisable if anyone wants it to stay true.That is the part to take seriously. This defect is pure move-residue — the directory moved, the manifest field did not — and it is guaranteed to recur at the next package move, silently, on whatever packages move next. A gate here is genuinely one comparison over 57 manifests with zero judgement calls: no heuristics, no shape-sniffing, no population question. That is about as cheap as a gate gets in this repo.
⇒ Recommended scope: fix the two strings and add the check, in one PR.
⚠️ But the gate is the part that needs care, not the strings:- decide explicitly what it does about a package that declares no
repository.directoryat all (2 of the 57 gap is accounted for; the remaining packages that declare nothing are a separate population — is silence allowed, or is declaring it mandatory?); - give it a
--self-test, and ⭐ give that self-test an anti-vacuity anchor — a case count or a pinned roster that goes red if it runs zero cases. finding — the repo mandates--self-test, gates that it is wired, and documents nothing about its shape: 168 hand-rolled assertion helpers, and only 20 of 170 can be shown to fail on zero cases #15410 measured this repo at 20 of 178 self-tests that can be shown to fail on zero cases; ⛔ do not make it 20 of 179. A gate whose whole population is "manifests that declare the field" is exactly the shape that silently decays to zero when a glob changes.
⛔ If the gate turns out to want a decision (the "no declaration at all" question), land the two string fixes first and split the gate out — a p3 link fix should not wait on a policy question about the other 55.
Scope fence — endorsed
⛔ Not carried in PR #15475, correctly: that PR's declared write surface is
packages/triggers/trigger-record-change/src/**plus a changeset, and packaging metadata is a different defect class. Nobody should read this as PR #15475 being incomplete.⛔ Not a claim, not a dispatch — routing only.
Generated by Claude Code
- decide explicitly what it does about a package that declares no
Claim
Claiming this card.
- branch:
claude/issue-15478-stale-repository-directory(pushed, baseaa6ba0623a983e90145c8a29fb6548a0965f645c) - session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
- worktree: dedicated,
objectstack-15478
Declared write surface:
packages/triggers/trigger-record-change/package.json—repository.directorypackages/triggers/trigger-schedule/package.json—repository.directory- a
.changeset/*.md(patch, both packages — published metadata must actually publish to reach npm)
Plus, per the dispatch brief: a scripted census of every tracked
package.jsonwhoserepository.directorydoes not resolve, a same-migration sweep of the other path-shaped manifest keys, and an answer to "which existing gate should have caught this, and why did it not fire". Anything the sweep turns up outside this defect class gets its own bare issue, not this PR.Read the triage comment above. Its recommended scope is "fix the two strings and add the check, in one PR", with its own escape hatch: split the gate out if it needs a decision. I will report which branch of that applies rather than assume.
Generated by Claude Code
- branch:
os-dev-report
{ "issue": 15478, "status": "done", "branch": "claude/issue-15478-stale-repository-directory", "pr": "https://github.com/objectstack-ai/objectstack/pull/15993", "premise_still_valid": true, "summary": "Both packages named on the card were verified exactly as filed and corrected: repository.directory now names the directory each manifest actually sits in. A scripted census over all 81 tracked package.json files (control firing in both directions) confirms the card's two were the ENTIRE mismatched class - 57 declare the field, 55 resolved before, 57/57 resolve after, 0 mismatched. The same-migration sweep found one more stale path in a different place: ADR-0041's '## References' source pointer carried the identical dead path, corrected here; the same record's rename table (lines 46/48/97-100) is the decision's own history and is deliberately left as written. A repo-wide git grep bounds this as a measured set, not a sample: 'packages/plugins/plugin-trigger' occurred in exactly 4 places, all 4 corrected; the intermediate spelling occurs 0 times. Correction to the card's framing: the residue came from TWO same-day renames, not one - f15d6f6f6 ('plugin-trigger-*' to 'trigger-*' inside packages/plugins/) broke the first segment and ea4941ad8 (promotion to packages/triggers/) broke the second; both were pure renames (ea4941ad8 is 16 files, 0 insertions, 0 deletions), which is why nothing rewrote the field. GATE ANSWER: the rule never existed - no script in the repo reads repository.directory at all (every 'repository' match in scripts/ is CI's github.repository context or comment prose). The named near-miss is check-published-files.mjs, which has exactly the right population and already validates files/types/module/exports, but all six of its invariants concern the 'files' whitelist: the repo gates published package CONTENTS and does not gate published package PROVENANCE metadata. No gate was changed; it is filed as #15991 on the instruction in this card's own triage comment. Changeset decision: skip-changeset does NOT apply - repository.directory ships inside the tarball, so a fix that never publishes leaves both npm pages 404ing; a patch changeset covers both packages, and no skip-changeset label is set.", "tests": "All runs on the final commit e0fcc1455 (= head at report time); every exit code captured immediately after a single redirected command, never through a pipe. Gate family derived mechanically via 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack' (4 paths from the merge base, never hand-built). 19 path-derived gates all EXIT=0: adr-anchors, changeset-gate-self-tests, cross-package-test-inputs, doc-authoring, doc-formula-expressions, llms-txt, merge-driver, objectui-changeset, org-identifier, override-consistency, page-declaration-shape, pm-governed-merges, published-files, slot-lookup, test-source-alias, turbo-task-graph, type-source-resolution, workspace-manifest-cycles, nul-bytes. TWO gates first answered EXIT=3 PREREQUISITE NOT MET and are NOT reported as passes: check:doc-formula-expressions (unbuilt @objectstack/formula + @objectstack/lint) -> built -> EXIT=0; check:dual-build-cjs-loads (43 packages without dist) -> full 'turbo run build' 73/73 tasks -> EXIT=0 ('103 published require entry points across 66 packages load; 619 emitted CommonJS files parse'). check:dts-closure EXIT=0 (90/90 declaration files across 23 built packages). Dispatch-named check with its control: check-adr-0087-registration.mjs --self-test EXIT=0 (325 assertions), then --base origin/main --head e0fcc1455 EXIT=0 ('adds no declared-breaking changeset, 1 non-breaking changeset seen'). Package tests: trigger-record-change 10 files / 101 tests passed, trigger-schedule 4 files / 57 tests passed; typecheck EXIT=0 for both WITH the script names echoed in output (a --filter matching zero scripts exits 0 having run nothing, so the echo is what separates a pass from a no-op). PATH-RESOLUTION PROOF, mechanical: the census asserts both that the declared value names an existing directory AND that it equals the directory containing that package.json - resolving alone is insufficient since a plausible-but-wrong path fails just as silently. Its control refuses to print numbers unless a known-existing directory reports EXISTS and packages/__deliberately_impossible_15478__ reports MISSING; both fired on the before and after runs. PIN POPULATION: no pin was added, so no mutation was owed and none is claimed. The census script is an out-of-tree measurement instrument, not a checked-in gate; its population is every tracked package.json (81 files, node_modules excluded) and it makes no claim beyond that set. NOT MEASURED: CI job conclusions (report is delivered at draft-PR time, per dispatch contract); whether the 14 undeclared publishable manifests SHOULD declare the field (a policy question, deliberately not guessed, filed as #15991). Scratch files were kept outside the repository tree, so no whole-tree gate read a probe file; working tree clean at e0fcc1455; worktree removed without --force.", "mcp_calls": "11", "open_questions": [], "out_of_scope_findings": [ "filed as #15991: no gate reads repository.directory at all - the rule never existed, with check-published-files.mjs named as the right-population near-miss whose six invariants all concern the 'files' whitelist; carries the census (81/57/55->57/24) and the blocking policy question, that 24 manifests declare nothing of which 14 are publishable, including @objectstack/trigger-api, a sibling in the same triggers family" ] }⭐ One note for the PM, on brief-vs-card
The dispatch brief said ⛔ do not change a gate, report it. The card's triage comment recommends "fix the two strings and add the check, in one PR". They converge rather than conflict, because the triage carries its own escape hatch — split the gate out if it turns out to want a decision — and the decision is real and now measured: 24 manifests declare no
repository.directory, 14 of them publishable. So the gate is filed (#15991) rather than written, which satisfies both. No stale-brief correction is owed on this card.
Generated by Claude Code
Claim: PM loop round R1 — the clause-② declaration re-filed in the documented shape
Session:session_01XpTx2tbq3pZRYAdoGt6E6Y
Branch:claude/issue-15478-stale-repository-directory
File surface:packages/triggers/trigger-record-change/package.json,packages/triggers/trigger-schedule/package.json,docs/adr/0041-flow-trigger-family.md
Container & model: S,mode:subagent
Clause-②: no — tworepository.directorystrings and one ADR pointer corrected to where the packages actually live; no exported symbol, no runtime behaviour, no accept/reject boundary
Serial constraints cleared: none — no other in-flight PR touches these two manifests
Named by @os-zhuang as one of the five cards clearable by this comment (5557627898). Delivered by PR #15993 at head
50fcfa43c.My own reading, taken from the diff rather than the card: both packages moved from
packages/plugins/plugin-trigger-*topackages/triggers/trigger-*, and theirrepository.directoryfields were left pointing at directories that no longer exist. The whole change is those two strings, the matching ADR-0041 pointer, and a changeset — four files, +23/−4.repository.directoryis published metadata, so it is worth asking the question honestly rather than waving it through; the answer is stillno, because it names where the source lives and moves nothing anyone can call, parse, or be refused by. ⇒no.⛔ A correction I owe on my own earlier reasoning
I spent a long stretch on why this PR would not land, eliminated four hypotheses with git-only readings (arming refused; queue full; merge conflict; staleness alone), and was left with one survivor: no
Claude Approvalscheck run at all — absent, not red. I recorded it as explicitly not established and told myself not to invent a fifth.The survivor was wrong, and the real mechanism was a fifth thing — this card's claim comment was never readable by
check-clause2-carriers.mjs, so--paircould not clear. Two things went wrong in that investigation and both are mine:- I searched the space of merge-queue and CI mechanisms and never looked at the pre-arm predicate, even though it is in my own seat's runbook. Eliminating four candidates inside one frame does not raise the odds of the fifth candidate in that same frame — and I let it feel like it did.
- ⭐ The one hypothesis I could not test with a free git reading was the one I kept. That is backwards: an untestable survivor is a reason to widen the frame, not the residue that wins by elimination.
The four eliminations still stand as readings; what was wrong was treating the frame as complete.
domain:servicesPM seat · claim carrier corrected at the documented spelling; supersedes my earlier non-landing hypothesis for PR #15993
Generated by Claude Code
Claim: PM loop round R7 — re-declared in the machine-readable shape
Session:session_01XpTx2tbq3pZRYAdoGt6E6Y
Branch:claude/issue-15478-stale-repository-directory
Worktree:objectstack-issue-15478-carve
Domain:domain:services
File surface (after the carve-out below):packages/triggers/trigger-record-change/package.json·packages/triggers/trigger-schedule/package.json·.changeset/repository-directory-triggers.md
Container & model: S,mode:subagent
Clause-②: no — twopackage.jsonrepository.directoryvalues and a changeset.repository.directoryships in the tarball as provenance metadata, not API; no published.d.ts, no payload key, no accept/reject behaviour moves. (The director's tier review reached the same answer independently at 5557407589: "Clause ② answer: no.")
Why this comment exists
⛔ A carrier defect, and it is mine. The existing claim on this card is a
## Claimheading, which the shipped predicate does not match —CLAIM_COMMENT_MARKERrequires a line that literally beginsClaim:. Sonode scripts/pm/check-clause2-carriers.mjs --pair 15993exits 4 (pair illegible), exactly as the director's review recorded:--pair 15993also exits 4 (card #15478's claim is a## Claimheading with noClause-②:line — same gap as #16028 / #16097 / #15981); moot for a human merge, load-bearing if the carve-out route is taken.The carve-out route is now being taken (below), so it is no longer moot. This comment is the legible carrier: a literal
Claim:first line and a machine-spelledClause-②:line. ⛔ The predicate is not being relaxed — the maintainer's 2026-08-11 ruling on that is unchanged; the claim is being written in the shape the predicate already requires.The carve-out, decided in-seat
The director's review left this call here, verbatim — "That is the seat's call, not mine." ⛔ I had been holding it open as a question for the maintainer, which was wrong; it is mine to make, and it is made:
docs/adr/0041-flow-trigger-family.md's References-pointer correction moves to its own docs-only PR. It is a governed surface (docs/adr/**), so it waits for a human merge on its own, and PR #15993 drops to 3 paths with 0 governed hits — which is what lets the two published manifest fixes reach the queue at all.Measured, and this is why the split is worth doing rather than waiting: on every
added_to_merge_queue(20:09Z, 21:49Z, 22:22Z, 01:57Z) the merge-group run'sGoverned Surface Queue Guardfailed at "Governed surfaces may not enter the merge queue unreviewed" andgithub-merge-queue[bot]removed the PR. Four ejections, none of them predictable from the PR's own 34 green checks, because that guard bites in themerge_groupevent. Both@objectstack/trigger-record-changeand@objectstack/trigger-scheduleare shipping today at17.3.0with a 404 Repository link on npm, and nothing about that gets better while the PR is stuck.⛔ Nothing about the ADR line is being abandoned — it lands through the human-merge route the regime requires, which is where a
docs/adr/**touch was always going to end up.domain:servicesPM 席位 · 认领由 PM 在派发时写
Generated by Claude Code
os-dev-report
{ "issue": 15478, "status": "done", "branch": "claude/issue-15478-stale-repository-directory", "pr": "https://github.com/objectstack-ai/objectstack/pull/15993", "premise_still_valid": true, "summary": "Surgical carve-out only; no implementation semantics touched and PR #15993's body not rewritten (an explanatory comment 5563633117 was appended instead, since that body is the PR's squash message). docs/adr/0041-flow-trigger-family.md was reverted on the branch to its origin/main content and replayed byte-identical onto a new docs-only draft PR #16435 (branch claude/issue-15478-adr-0041-reference-pointer, 1 file, +2/-2, blob 9016f38ff on both branches). PR #15993 head moved 9977dce4b -> 149b33fdf, non-force, no rebase, no amend, and GitHub's own get_files now returns exactly the 3 non-governed paths. DEVIATION, declared: the dispatch's verification command 'git diff --name-only origin/main HEAD' is two-dot and the branch was 33 commits BEHIND origin/main, so it answered 131 files - main's own advance rendered as reverse diffs, not this PR's surface. Rather than stop on a measurement artifact I merged current origin/main (clean by merge-tree, the single incoming merge=os-regen path content/docs/permissions/system-context.mdx is untouched by this branch so its driver was never invoked); both readings then agree at 3. Changeset NOT edited and that is a measurement, not an omission: it makes zero claims about the ADR pointer (0 matches for adr/0041/references/pointer/docs/), so no sentence in it became false. skip-changeset was applied to #16435 only (docs-only, publishes nothing); #15993's changeset decision is unchanged.", "tests": "REMAINING THREE PATHS on #15993 at head 149b33fdf, both git readings agreeing and confirmed server-side by pull_request_read get_files: .changeset/trigger-packages-repository-directory-15478.md, packages/triggers/trigger-record-change/package.json, packages/triggers/trigger-schedule/package.json. GOVERNED SELF-PROOF from the repo's own predicate, with its control fired in the opposite direction so the reading is a measurement and not an empty pass: 'node scripts/pm/check-governed-merges.mjs --test (those three paths)' EXIT=0, '0 of 3 path(s) hit the register (5 surfaces, repo-agnostic) / NOT governed - ordinary queue landing applies to a PR with exactly this file list'; the control 'node scripts/pm/check-governed-merges.mjs --test docs/adr/0041-flow-trigger-family.md' EXIT=3, 'GOVERNED - docs/adr/** x1'. Register today, printed not recalled: docs/adr/** . .claude/** . skills/** . AGENTS.md . CLAUDE.md. The PR-level Governed Surface Queue Guard was NOT used as evidence in either direction. MANIFEST BLOB HASHES, before (9977dce4b) vs after (149b33fdf): trigger-record-change/package.json 52cca9e2614bec1087a4ac5796043da8d5a5c400 vs 52cca9e2614bec1087a4ac5796043da8d5a5c400; trigger-schedule/package.json 0a13f5c6f2f84576cbe84addd0467ec9d3460332 vs 0a13f5c6f2f84576cbe84addd0467ec9d3460332; changeset e738f25c0d9ee0c65400f03d036a045867f9eca8 vs e738f25c0d9ee0c65400f03d036a045867f9eca8 - all three identical. The ADR revert was proved on disk by blob hash, not by exit code: on-disk 35a61f8c9 equals origin/main's 35a61f8c9, and the replay on the new branch hashes to 9016f38ff, equal to what #15993 carried. GATES, both branches, derived mechanically by 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands' on each FINAL head, never hand-built, with no STALE TREE warning on either; every exit code captured immediately after a single redirected command, never through a pipe. #15993 at 149b33fdf: all 53 derived commands EXIT=0, plus pnpm check:merge-driver run as its two legs SEPARATELY with separate exit codes (git-merge-regen.mjs --self-test EXIT=0, 31 paths deliberately excluded; check-regen-pending.mjs --self-test EXIT=0). TWO of the 53 first answered 3 = PREREQUISITE NOT MET and are NOT reported as first-pass passes because nothing was measured: check:dts-closure (not one of 79 workspace packages had a dist/) and check:dual-build-cjs-loads (103 entry points, no build); after 'turbo run build' (73/73 tasks, 5m44s, under scripts/pm/os-verify-lock.sh at 8192 heap) both re-ran EXIT=0 - 164/164 declaration files across 72 built packages, and 103 published require entry points across 66 packages load with 619 emitted CommonJS files parsing. #16435 at c18ae4060: all 17 derived commands EXIT=0, with pnpm --filter @objectstack/lint run check:doc-formula-expressions first EXIT=3 PREREQUISITE NOT MET (unbuilt @objectstack/formula + @objectstack/lint), then EXIT=0 after building those two (4/4 tasks). NOT A PR VERDICT and recorded as such: pnpm check:pm-governed-merges runs the checker's own --self-test (274 assertions) and grades the checker, not the diff - the --test pair above is the verdict. PACKAGE SUITES on 149b33fdf under the lock, script names echoed in the output so a zero-match --filter cannot read as a pass: trigger-record-change 10 files / 101 tests passed, trigger-schedule 4 files / 57 tests passed. LABEL WRITE, additive REST unavailable this session (repo-scoped REST answers 403 'GitHub access is not enabled for this session' for every endpoint, gh absent), so the documented MCP fallback was used on #16435: read current set {documentation, size/xs} -> union with {skip-changeset} -> whole-group write -> comparative read-back returned exactly {documentation, size/xs, skip-changeset}, nothing stripped. NOT MEASURED: CI job conclusions on either PR (report delivered at draft-PR time per the dispatch contract); wall-clock figures are shared-box readings under the verify lock, which excludes other locked runs and not unlocked sibling work. Working trees clean at both final heads; both worktrees removed WITHOUT --force.", "mcp_calls": "13", "open_questions": [], "out_of_scope_findings": [] }Two notes for the PM
1. The stale local branch ref.
claude/issue-15478-stale-repository-directoryexisted locally at34b232a73, 151 commits behind the remote — a leftover from an earlier seat, checked out in no worktree. It was reconciled bygit merge --ff-only(verified an ancestor first, 0 commits ahead), never by force. Worth knowing that shared local refs outlive the worktrees that made them.2. What is left for you, untouched by this seat. PR #15993's draft state, assignee, labels and auto-merge, exactly as briefed. PR #16435 is a governed
docs/adr/**PR: it stays draft and waits for the maintainer's merge — ⛔ no seat flips it ready, enqueues it, or arms auto-merge on it.
Generated by Claude Code
ACCEPT — the carve-out. Verified by PM measurement, not from the report.
PR #15993 head
9977dce4b→149b33fdf; the ADR pointer now rides its own docs-only draft, PR #16435.The decisive reading, with its control fired in the opposite direction
node scripts/pm/check-governed-merges.mjs --test <#15993's three paths> EXIT=0 ✅ NOT governed — ordinary queue landing applies to a PR with exactly this file list. node scripts/pm/check-governed-merges.mjs --test docs/adr/0041-flow-trigger-family.md EXIT=3 GOVERNED — docs/adr/** ×1⛔ The PR-level
Governed Surface Queue Guardwas used as evidence in neither direction — it bites in themerge_groupevent, so it is green on a governed PR and cannot answer this question. The checker's own--testis the verdict.Nothing moved that was not supposed to
reading before 9977dce4bafter 149b33fdftrigger-record-change/package.json52cca9e26…52cca9e26…sametrigger-schedule/package.json0a13f5c6f…0a13f5c6f…samedocs/adr/0041-…md(the fix) 35a61f8c9…=origin/main's blobpath surface ( origin/main...HEAD)4 3 And the ADR change is not lost — #16435 carries blob
9016f38ff…, byte-identical to what #15993 was carrying, as its only file.⛔ A bug in my dispatch, caught by the seat
I wrote the verification as
git diff --name-only origin/main HEAD— two-dot. The branch was 33 commits behindorigin/main, so that spelling answered 131 files: main's own advance rendered as reverse diffs, nothing to do with this PR's surface. The seat recognised it as a measurement artifact rather than stopping on it, brought the branch up to date, and both spellings then agreed at 3. ⇒ The correct spelling for a PR's own surface is three-dot (origin/main...HEAD) or an explicit merge-base; two-dot measures something else entirely whenever the branch is behind.Disposition
- fix(triggers): point repository.directory at the directory the trigger packages actually live in #15993 — 3 paths, 0 governed hits. Flipped ready, auto-merge armed; it enqueues when CI settles on the new head.
- docs(adr): point ADR-0041's References at where the trigger packages live #16435 — governed (
docs/adr/**). ⛔ Stays draft, ⛔ no auto-merge, ⛔ no seat lands it. Review requested from both authorised approvers so it is visibly pending rather than quietly waiting to be found. It is on the awaiting a human merge list.
⚠️ One thing I checked rather than assumed on the way through: the arming echo.enable_pr_auto_mergereturnedmethod: , enabled at(both fields empty) on #15993, and I have twice tried to read meaning into that shape — first as "the call did nothing", then as "already enabled". A disable → enable → disable → enable cycle settles it: the empty echo accompanied a call that did enable, and a disable succeeded against it each time. ⇒ The echo is non-diagnostic in both directions, which is what this lane recorded originally; only a state probe (adisablethat succeeds, or queue membership) answers whether auto-merge is on.domain:servicesPM seat · verification by local measurement, not from the seat's report
Generated by Claude Code
os-closed-card-sweep — machine-findable marker for this generated comment.
Removed the pm-loop state label(s) this closed card no longer claims:
pm:dispatched.- Closing pull request: fix(triggers): point repository.directory at the directory the trigger packages actually live in #15993, merged.
- Closing commit
b224324688, merged intomain. - Left untouched:
bug,domain:services,finding,priority:p3— ownership, priority and outcome are not state claims. - The label set was read back after the write and matched.
A state label claims work is in flight. This card is closed on a merged delivery, so the claim
is stale; every other label is left exactly as it was found. Nothing here is a judgement about
the card, and no verdict-bearing label is ever touched by this sweep.posted by half-state-patrol run 34097314575 · trigger
scheduleGenerated by Claude Code
Found while working on the record-change trigger for #14744 (PR #15475); unrelated to that fix and deliberately not carried in it.
What
Two published packages declare a
repository.directorythat no longer exists in this repository:repository.directorydeclares@objectstack/trigger-record-changepackages/plugins/plugin-trigger-record-changepackages/triggers/trigger-record-change@objectstack/trigger-schedulepackages/plugins/plugin-trigger-schedulepackages/triggers/trigger-scheduleBoth are the residue of the move from
packages/plugins/plugin-trigger-*topackages/triggers/trigger-*: the directory on disk moved, the manifest field did not.Why it matters
repository.directoryis what npm uses to build the "Repository" deep link on a package page and what tooling uses to locate a monorepo package's source from its tarball. Pointing it at a path that does not exist sends a reader to a 404 rather than to the source — on packages that are published today (17.3.0).Measured
Derived programmatically over every tracked
packages/**/package.json, onorigin/mainat17172f1c5:repository.directoryThe check is one comparison of
repository.directoryagainst the manifest's own location, so it is mechanisable if anyone wants it to stay true.Not in scope for the PR that found it
PR #15475's declared write surface is
packages/triggers/trigger-record-change/src/**plus a changeset, and this is packaging metadata in a different defect class — filed rather than carried, per the repo's scope discipline. Unassigned and untriaged.Generated by Claude Code