You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
console: the Packages sheet offers Edit, Publish, Revert, Disable, Duplicate and Delete app on a package badged "Read-only · code" #13157
Filing gate ③ a task the maintainer set: objectstack-ai/hotcrm#2188, the maintainer's browser pass of 2026-10-20. Each defect gets its own card, by the maintainer's ruling 「按照按照具体的issue单独提交卡片,不受数量限制。」 (recorded on objectstack-ai/hotcrm#2188, 6283467378). This is finding F-06 of track 2 (Setup as the system administrator), by the cloud tester session_01VuXyJvhGKJy8qeUvhKyxzv. It was measured on HotCRM mainf22dfa52 with @objectstack/* 18.0.0-next.5, in Chromium at 1440×900 on a locally booted, seeded install. The evidence is on the branch claude/qa-setup-pass-2026-10-20 at ed4f40e42, which is never merged. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r). ⛔ Not a claim. Grade: triage's.
Reader (who acts): objectui triage routes it. Paths under src/ are HotCRM's (objectstack-ai/hotcrm).
The finding, as measured
Persona / URL: dev admin, Setup → Apps → Packages → the HotCRM package's sheet.
Expected: the sheet's own scope badge, "Read-only · code". A read-only package offers no write action. The platform refuses Publish and Revert on it with 422 [writable_package_required] … it is read-only (provided by code or an installed app).
class: a. Reach: every admin opening a code-provided or installed package.
Seat review
Landing: objectui's Packages sheet does not gate its actions on the package's scope.
The server-side half of this finding (the update door's own read-only check) is objectstack#24705, closed 2026-10-20, after 18.0.0-next.5. This card is the console half only: offer no write action on a read-only package.
Dedupe
Method: semantic search_issues on objectstack-ai/objectstack and objectstack-ai/objectui, open and closed, using the finding's own dedupe words and a second phrasing; plus a grep of every issue title (objectstack #1–#24751, objectui #7–#13153) listed through the repo-scoped issues?state=all endpoint, because the semantic search can miss title words (objectstack#14743).
10 hits in objectstack, 9 + 20 in objectui. objectstack#24705 is closed and covers the server only. No card covers the sheet's actions. New.
Claim: PM loop round 16 (priority:p2)
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-13157-readonly-package-actions
Worktree: objectui-issue-13157
Domain: domain:ui
Seat: domain:ui#2
File surface:
packages/app-shell/src/views/metadata-admin/PackagesPage.tsx (the package sheet's action set): on a package the sheet already badges read-only (provided by code or an installed app), it offers no write action that the platform refuses there (Edit, Publish, Revert, Disable, Duplicate-as-write, Delete). The read-only verdict comes from the sheet's existing scope source (package-scope.ts), not a new one.
Tests beside it.
One .changeset/13157-readonly-package-actions.md (@object-ui/app-shellpatch).
⛔ No new export, no server change. Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate over this surface)
Clause-②: no (an internal Setup sheet; no export, key or prop moves)
Responsibility: the Packages sheet does not gate its actions on the package's scope | the sheet already badges the scope (Read-only · code) and the platform refuses writes with 422 writable_package_required (objectstack#24705) | every admin opening a code-provided or installed package
Thread-read: none
Serial constraints cleared: objectui#13057 (cd4623d, PackagesPage publish pulse) landed. No in-flight objectui card or open PR touches PackagesPage.tsx (read at 07:16Z).
Claimed at: 2026-10-20T07:15Z
os-dev-report
{
"issue": 13157,
"status": "done",
"branch": "claude/issue-13157-readonly-package-actions",
"pr": "#13181",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "PackageDetailSheet gated its actions on manifest.scope being system or cloud (isKernel), a second rule beside the Scope badge's served writable verdict. It now gates on pkg.writable === true, the verdict the badge reads. On a read-only package it hides Edit, Publish, Revert, Disable, Duplicate, Adopt loose items and Delete app, and keeps View info and Export. Enable is still shown on a disabled read-only package, because the server does not refuse it. Duplicate was checked against the server source: the duplicate arm refuses a read-only source with 422 DUPLICATE_SOURCE_NOT_A_BASE before it creates anything, so it is a refused action and is hidden. Every refused action is hidden rather than disabled: a tooltip would need new strings in i18n.ts, which is outside the claimed file surface, and the badge already says read-only on the sheet. A writable package's sheet is unchanged. Mechanism-assumption correction: the badge's verdict is the row's writable, not package-scope.ts, which filters Studio's authoring destinations by scope alone and is not touched.",
"tests": "All at 8804d71. New PackagesPage.readOnlyActions-13157.test.tsx, run with vitest under the lock: Tests 8 passed (8). Every test file naming PackagesPage (21 files): Test Files 21 passed (21), Tests 306 passed (306). Closure build pnpm --filter '@object-ui/app-shell^...' build: exit 0. pnpm --filter @object-ui/app-shell type-check: exit 0 (tsconfig.test.json includes src/**/*.test.tsx). eslint --no-inline-config --format json on the 2 changed source files: 2 files, 0 errors; the 15 warnings are on untouched lines; no type-aware linting (no parserOptions.project or projectService in the root eslint.config.js). All exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence. Ablation with objectstack scripts/ablation-replace.mjs on the committed fix: anchor 'const writable = pkg.writable === true;' replaced by 'const writable = true;'; anchor count 1 to 0; blob d374aafcc4bd to fad646251e9d. The new file went red: Tests 6 failed | 2 passed (8); the 2 that passed are the writable controls. Restore: blob d374aafcc4bda1d5730e6aa9f1bd09739300ecc3 equals the HEAD blob, and git diff HEAD is empty. No dist rebuild was needed, because the test imports src by relative path. Declared to CI: the whole packages/app-shell test directory, under the dispatch's lock clause ('No whole-package-directory runs'). That clause conflicts with the Gates line ('each touched package's dir under the lock'); the lock clause was followed. CI: in_progress, not awaited.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, which made draft PR #13181 and posted assignee baozhoutao via POST /repos//issues/13181/assignees; (2) this os-dev-report comment, POST /repos//issues/13157/comments. A first pr_create attempt was refused by write-pace (exit 10, nothing written) and sent again once the window reopened. git push (empty probe, then 1 commit) is not REST. Zero label writes: objectui, and the dispatch named none.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed · objectstack packages.ts POST /packages/ID/adopt-orphans arm calls no requireWritablePackage, so from the source it can bind loose items into a read-only package. Read from source only, not reached through a public door. Dedupe words: adopt-orphans read-only package writable gate",
"carrier: none · noted, not filed · package-scope.ts buildPackageScopeOptions keeps every package whose scope is not system or cloud, so a read-only scope-less package (a marketplace install) can be offered as a Studio authoring destination. Read from source only, not measured. Dedupe words: package scope options writable marketplace authoring destination",
"carrier: none · noted, not filed · PackageDetailSheet's pending-drafts Publish (N) and Discard changes (N) still gate on isKernel (scope). Out of this card's action list; the server does not gate the draft doors on writability."
],
"gates": "all exit 0 (listed under tests); check:spec-floors not run (not in the dispatch's battery)",
"files_changed": [
"packages/app-shell/src/views/metadata-admin/PackagesPage.tsx",
"packages/app-shell/src/views/metadata-admin/PackagesPage.readOnlyActions-13157.test.tsx",
".changeset/13157-readonly-package-actions.md"
],
"deviations": "Deviation 1, mechanism assumption disproved: the badge's verdict is pkg.writable, not package-scope.ts; the gate follows the ruling's intent of one verdict. Deviation 2: system and cloud packages now also show View info and Export (reads), beside the existing kernel sentence. Deviation 3: the package-wide test directory is declared to CI instead of being run locally (the lock clause)."
}
Clause-②: no. This is an internal Setup sheet; no export, key or prop moves. No contract review is owed, and the seat read the report.
Seat review against the rulings:
(1) One verdict: PackageDetailSheet gated its actions on manifest.scope (system or cloud), a second rule beside the Scope badge. It now gates on pkg.writable === true, the verdict the badge reads.
Mechanism correction accepted: the claim named package-scope.ts, but the badge reads the row's served writable.
(2) On a read-only package the sheet hides Edit, Publish, Revert, Disable, Duplicate, Adopt loose items and Delete app; View info and Export stay.
Duplicate was checked against the server source: it refuses a read-only source with 422 DUPLICATE_SOURCE_NOT_A_BASE before creating anything, so it is hidden.
Enable stays on a disabled read-only package, because the server does not refuse it.
Hidden rather than disabled: the badge already says read-only, and no new strings are needed.
(3) A writable package is unchanged.
Pins: 8, including the writable controls. The ablation (writable = true) turned 6 red with the 2 writable controls green, and the restore was proven by blob. All 21 PackagesPage files are green.
Changeset: @object-ui/app-shellpatch.
CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
Acceptance notes: package-scope.ts's buildPackageScopeOptions keeps any package whose scope is not system or cloud, so a read-only scope-less install could be offered as a Studio authoring destination. Source reading only, not measured.
Acceptance notes: the sheet's pending-drafts Publish (N) and Discard (N) still gate on scope. They are outside this card's action list, and the server does not gate the draft doors on writability.
Next: ready + auto-merge; landing is verified by content on main.
Verified by content: each of the 3 files the PR changes has the same blob at f7aac4ce7a as at the accepted head 8804d718b0. The merge message carries no model identifier.
Landed: the Packages sheet gates its actions on the package's served writable verdict, the one its scope badge reads. A read-only package offers no write action the platform refuses (Edit, Publish, Revert, Disable, Duplicate, Adopt loose items, Delete). View info and Export stay.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 16 (
priority:p2)Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-13157-readonly-package-actionsWorktree:
objectui-issue-13157Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/metadata-admin/PackagesPage.tsx(the package sheet's action set): on a package the sheet already badges read-only (provided by code or an installed app), it offers no write action that the platform refuses there (Edit, Publish, Revert, Disable, Duplicate-as-write, Delete). The read-only verdict comes from the sheet's existing scope source (package-scope.ts), not a new one..changeset/13157-readonly-package-actions.md(@object-ui/app-shellpatch).⛔ No new export, no server change. Stop on breach; explain in the report.
Container & model:
S,mode:subagent,model: opus(default tier; no path-derived mandate over this surface)Clause-②: no (an internal Setup sheet; no export, key or prop moves)
Responsibility: the Packages sheet does not gate its actions on the package's scope | the sheet already badges the scope (
Read-only · code) and the platform refuses writes with422 writable_package_required(objectstack#24705) | every admin opening a code-provided or installed packageThread-read: none
Serial constraints cleared: objectui#13057 (
cd4623d,PackagesPagepublish pulse) landed. No in-flight objectui card or open PR touchesPackagesPage.tsx(read at 07:16Z).Claimed at: 2026-10-20T07:15Z
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 13157,
"status": "done",
"branch": "claude/issue-13157-readonly-package-actions",
"pr": "#13181",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "PackageDetailSheet gated its actions on manifest.scope being system or cloud (isKernel), a second rule beside the Scope badge's served
writableverdict. It now gates on pkg.writable === true, the verdict the badge reads. On a read-only package it hides Edit, Publish, Revert, Disable, Duplicate, Adopt loose items and Delete app, and keeps View info and Export. Enable is still shown on a disabled read-only package, because the server does not refuse it. Duplicate was checked against the server source: the duplicate arm refuses a read-only source with 422 DUPLICATE_SOURCE_NOT_A_BASE before it creates anything, so it is a refused action and is hidden. Every refused action is hidden rather than disabled: a tooltip would need new strings in i18n.ts, which is outside the claimed file surface, and the badge already says read-only on the sheet. A writable package's sheet is unchanged. Mechanism-assumption correction: the badge's verdict is the row'swritable, not package-scope.ts, which filters Studio's authoring destinations by scope alone and is not touched.","tests": "All at 8804d71. New PackagesPage.readOnlyActions-13157.test.tsx, run with vitest under the lock: Tests 8 passed (8). Every test file naming PackagesPage (21 files): Test Files 21 passed (21), Tests 306 passed (306). Closure build pnpm --filter '@object-ui/app-shell^...' build: exit 0. pnpm --filter @object-ui/app-shell type-check: exit 0 (tsconfig.test.json includes src/**/*.test.tsx). eslint --no-inline-config --format json on the 2 changed source files: 2 files, 0 errors; the 15 warnings are on untouched lines; no type-aware linting (no parserOptions.project or projectService in the root eslint.config.js). All exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence. Ablation with objectstack scripts/ablation-replace.mjs on the committed fix: anchor 'const writable = pkg.writable === true;' replaced by 'const writable = true;'; anchor count 1 to 0; blob d374aafcc4bd to fad646251e9d. The new file went red: Tests 6 failed | 2 passed (8); the 2 that passed are the writable controls. Restore: blob d374aafcc4bda1d5730e6aa9f1bd09739300ecc3 equals the HEAD blob, and git diff HEAD is empty. No dist rebuild was needed, because the test imports src by relative path. Declared to CI: the whole packages/app-shell test directory, under the dispatch's lock clause ('No whole-package-directory runs'). That clause conflicts with the Gates line ('each touched package's dir under the lock'); the lock clause was followed. CI: in_progress, not awaited.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, which made draft PR #13181 and posted assignee baozhoutao via POST /repos//issues/13181/assignees; (2) this os-dev-report comment, POST /repos//issues/13157/comments. A first pr_create attempt was refused by write-pace (exit 10, nothing written) and sent again once the window reopened. git push (empty probe, then 1 commit) is not REST. Zero label writes: objectui, and the dispatch named none.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed · objectstack packages.ts POST /packages/ID/adopt-orphans arm calls no requireWritablePackage, so from the source it can bind loose items into a read-only package. Read from source only, not reached through a public door. Dedupe words: adopt-orphans read-only package writable gate",
"carrier: none · noted, not filed · package-scope.ts buildPackageScopeOptions keeps every package whose scope is not system or cloud, so a read-only scope-less package (a marketplace install) can be offered as a Studio authoring destination. Read from source only, not measured. Dedupe words: package scope options writable marketplace authoring destination",
"carrier: none · noted, not filed · PackageDetailSheet's pending-drafts Publish (N) and Discard changes (N) still gate on isKernel (scope). Out of this card's action list; the server does not gate the draft doors on writability."
],
"gates": "all exit 0 (listed under tests); check:spec-floors not run (not in the dispatch's battery)",
"files_changed": [
"packages/app-shell/src/views/metadata-admin/PackagesPage.tsx",
"packages/app-shell/src/views/metadata-admin/PackagesPage.readOnlyActions-13157.test.tsx",
".changeset/13157-readonly-package-actions.md"
],
"deviations": "Deviation 1, mechanism assumption disproved: the badge's verdict is pkg.writable, not package-scope.ts; the gate follows the ruling's intent of one verdict. Deviation 2: system and cloud packages now also show View info and Export (reads), beside the existing kernel sentence. Deviation 3: the package-wide test directory is declared to CI instead of being run locally (the lock clause)."
}
objectstack-fleet commentedon Oct 20, 2026
ACCEPT — PR #13181 @
8804d718b0b317e2d9b85b27f71d26476c3446bc·domain:uiseat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)PackageDetailSheetgated its actions onmanifest.scope(system or cloud), a second rule beside the Scope badge. It now gates onpkg.writable === true, the verdict the badge reads.package-scope.ts, but the badge reads the row's servedwritable.422 DUPLICATE_SOURCE_NOT_A_BASEbefore creating anything, so it is hidden.writable = true) turned 6 red with the 2 writable controls green, and the restore was proven by blob. All 21PackagesPagefiles are green.@object-ui/app-shellpatch.POST /packages/:id/adopt-orphansarm calls norequireWritablePackage. Seat-verified on objectstackmain9d13b5fc83:packages/runtime/src/domains/packages.ts:2138, while every sibling arm calls it.package-scope.ts'sbuildPackageScopeOptionskeeps any package whose scope is not system or cloud, so a read-only scope-less install could be offered as a Studio authoring destination. Source reading only, not measured.Next: ready + auto-merge; landing is verified by content on
main.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gBmainf7aac4ce7a.f7aac4ce7aas at the accepted head8804d718b0. The merge message carries no model identifier.writableverdict, the one its scope badge reads. A read-only package offers no write action the platform refuses (Edit, Publish, Revert, Disable, Duplicate, Adopt loose items, Delete). View info and Export stay.requireWritablePackage.pm:dispatchedis removed.Generated by Claude Code
fix(app-shell): offer no write action on a read-only package in the P…