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 }}
Repository navigation
Setup audit: the audit:log browser offers sys_audit_log's list views as presets and an "Open as list" link, so Setup can keep one audit entry (item 1 of objectstack#23803, the objectui half of objectstack#23890) #12667
"One audit entry: "Audit Log" opens the browser (filters by action, object, actor, date); the record list's views (Writes, Auth, …) become the browser's presets; the sys_audit_log list stays reachable from the browser's "Open as list" link, not from the nav."
Where
The browser is this repo's console component audit:log, registered at apps/console/src/registerSystemComponents.tsx:80.
The list views it should offer as presets are declared by objectstack's plugin-audit on sys_audit_log (packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts: writes_only at :60, auth_events at :73, and the rest). Read them from the served object metadata; ⛔ do not copy them as literals.
Done when
The browser offers each served list view of sys_audit_log as a preset filter.
An "Open as list" link reaches the sys_audit_log list.
Then objectstack#23890 (domain:services, blocked on this card) removes nav_audit_logs from Setup's nav, once this card is installable at objectstack's .objectui-sha.
Grade
p2, as objectstack#23803 and #23890.
Dedupe
MCP search_issues on objectstack-ai/objectui, all states: audit log browser presets open as list sys_audit_log Setup navigation one audit entry returned 1 hit, objectui#12475 (closed, a different gate on the History and Audit tabs).
Dedupe words: audit log browser presets; Open as list sys_audit_log; one audit entry Setup.
plugin-audit's list views themselves (objectstack).
Any spec change.
A route outside the surface stops and reports (stop on breach; explain in the report).
Container & model: M, mode:cloud, model: opus (default tier; no path-derived mandate)
Clause-②: no
Clause-② reason: the browser starts reading list views the platform already declares on sys_audit_log, and adds a link. If the PR adds published pack keys or exports, its body flips this line to Clause-②: yes, which the seat's TIER_DEFAULT ACCEPT covers.
Responsibility: n/a — not a defect card
Thread-read: none
The card has no comments.
Serial constraints cleared: read at objectui mainc41ce3f241.
{
"issue": 12667,
"status": "done",
"branch": "claude/issue-12667-audit-presets",
"pr": "https://github.com/objectstack-ai/objectui/pull/12750",
"session": "session_01ESLcqKU7sTVG6SNoeDrjME",
"premise_still_valid": true,
"summary": "The audit:log browser (apps/console/src/pages/system/AuditLogPage.tsx) now reads sys_audit_log's listViews from the console's object metadata (useMetadata().objects, the same composed read the object list's view switcher uses). It offers one preset per served view, by served label, in served order. No view is named in code. A preset sends the view's own filter, lowered by @object-ui/core's toFilterNodeSafely (the same lowering the object list runs), beside the bar's filters via mergeFilterNodes. Columns, sort and page size stay the browser's own. A view the lowering refuses, or one bound to another data source, is shown disabled with its reason and a link to that view in the list; it never sends a filter. The header gains 'Open as list': it links to /apps/APP/sys_audit_log, or to /apps/APP/sys_audit_log/view/KEY when a preset is active (KEY is the listViews key, the same id the list's view tabs use). Hypotheses: H1 confirmed (the page built its own Mongo-style $filter). H2 confirmed live: six served views, each filter a spec rule array of {field, operator, value}. H3 confirmed live: the named view route opens the same view (Writes: 32 rows in the browser, 32 records in the list). H4: no strings were added to packs; copy is English literals like the rest of the page, so Clause-② stays no. Live reading at 1280 px is on claude/issue-12667-evidence under evidence/12667/ (commit 694c35846f): four PNGs showing no preset, Auth, Writes, and Open as list landing on the Writes view. Backend: @objectstack/*@18.0.0-next.2 showcase via e2e/live/ci/start-backend.sh; it needed no fix. Setup: per the PM's recipe, the primary checkout was detached and the worktree objectui-issue-12667 was added on the existing branch, fast-forwarded from c41ce3f to origin/main b393152.",
"tests": "New file apps/console/src/pages/system/AuditLogPage.presets-12667.test.tsx, 7 tests. Its fixture is a sys_audit_log document whose views (night_shift, everything, broken, elsewhere) are keys no code names, so a literal copy cannot pass. It pins: every served view appears as a preset in served order; choosing a preset sends exactly [[\"action\",\"in\",[\"login\",\"logout\"]]] and choosing it again removes it; the preset joins the bar's filters; a view with no filter sends none; inexpressible views are disabled with a link and send nothing; Open as list reaches the list, and the preset's view when one is active. Three existing render sites were wrapped in MemoryRouter (actorName-11701, pageHeader-12553, consoleFaces.displayLocale-9909) because the page now renders a Link. Run at 5838608 (under the lock): `pnpm exec vitest run apps/console/src/pages/system apps/console/src/pages/consoleFaces.displayLocale-9909.test.tsx apps/console/src/__tests__/orphanedPageComponentRefs-10520.test.tsx scripts/__tests__/dollar-dialect-alias-census.test.ts` gave Test Files 35 passed (35), Tests 271 passed (271), VERDICT command-exit 0. Ablations used objectstack's scripts/ablation-replace.mjs on AuditLogPage.tsx (HEAD blob a835329adbb9); each mutation landed (anchor 1 to 0) and each was restored to blob a835329adbb99a6ae14d0e123f19deeab08a1fd9 == HEAD with git diff HEAD empty. No dist step: the tests import the page from source. A1, listViews replaced by a literal writes_only: 5 failed. A2, mergeFilterNodes(filter, presetNode) replaced by the bar filter alone: 2 failed ('sends the chosen view's own filter', 'joins the bar's filters'). The first A2 attempt was refused by the tool (replacement text not distinctive) and ran no test; it was re-run with a marked replacement. A3, Link to listHref replaced by '/': 2 failed (both Open-as-list tests). A4, refusal branch disabled so a refused view was approximated: 1 failed. Live wire check: core's actual merged output for the bar filters plus the Auth preset returned HTTP 200 with 3 login rows.",
"gates": "Local, at 5838608 (exit codes captured before any pipe). `pnpm --workspace-concurrency=2 --filter '@object-ui/console^...' build`: VERDICT command-exit 0 (needed before type-check; the first type-check before this build exited 2 with TS2307 on unbuilt workspace packages). `pnpm --filter @object-ui/console type-check`: 0. `VITE_BASE_PATH=/console/ pnpm --filter @object-ui/console exec vite build`: 0. vitest as in tests: 0, 271 passed. `pnpm check:changeset-claims`: 0. `pnpm changeset:check`: 0. `pnpm check:test-path-roots`: 0. `pnpm check:spec-symbols`: 0. `node scripts/check-changeset-presence.mjs`: 0. `pnpm check:new-line-citations`: 0 (0 new citations). eslint --no-inline-config on the 5 changed source and test files: 0 errors; AuditLogPage.tsx keeps the base file's 2 pre-existing warnings. My first draft added 4 warnings; commit 5838608 removed them. Not run: the i18n checks, because no pack changed. objectui has no scripts/pm/dispatch-gates.mjs, so there is no --ran reconciliation; the local set was derived by hand from package.json and ci.yml. CI families: NOT MEASURED, no PR yet; the seat opens it.",
"mcp_calls": "2 — mcp__github__issue_read (get, get_comments); no write tool",
"api_writes": "0 — git pushes only: claude/issue-12667-audit-presets (3 pushes) and claude/issue-12667-evidence (1 push, plumbing-built parentless commit)",
"open_questions": [
{
"question": "The active preset is component state, like the page's other filters, not a URL parameter. AGENTS.md #8 classes shareable or refresh-surviving state as URL state.",
"options": ["A keep it as component state, consistent with the page's existing filters (shipped)", "B move the preset, and later the whole filter bar, into URL params from app-shell's urlParams.ts in a follow-up"],
"recommendation": "A for this card, because the card asks for presets and a link, not addressable filters; adding URL state only for presets would split the page's state between two homes. B is a whole-page follow-up only if someone asks for it."
}
],
"out_of_scope_findings": [],
"deviations": [
"My first worktree command chain, which included `git branch -D`, was refused by the auto-mode classifier and nothing in it ran. I then used the PM's recipe: detach, worktree add on the existing branch, ff-only merge.",
"While building the evidence commit, a shell variable-expansion slip produced an empty sha, and one push went out as `git push origin :refs/heads/claude/issue-12667-evidence`, which is a delete refspec. The ref did not exist yet, so git answered 'Everything up-to-date' and nothing changed; git ls-remote showed no such branch beforehand. The real push followed behind a non-empty guard.",
"The worktree ../objectui-issue-12667 and its node_modules are kept, because the PR is not open yet; the role file's cleanup step runs after the PR opens. The vite dev server (:5167) and the backend (:4067) were stopped by their recorded PIDs, and the ports were checked free."
]
}
Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12750.
The seat's answers:
The open question: A. The preset stays component state, like the page's other filters. A URL-state move for the whole filter bar has no request behind it, so it gets no card.
The deviations are recorded. The empty-sha push named a ref that did not exist, so nothing was deleted. The PR head 5838608 and the evidence branch were both read on the server.
One note for the ACCEPT:listBase falls back to the setup app when the route carries no appName. The fallback is reached on a served route: systemRoutes (apps/console/src/AppContent.tsx) is mounted both under /apps/:appName and in the no-app table, so /system/audit-log renders on a zero-app deployment. There /apps/setup/sys_audit_log is the generic Setup object route, the same fallback ApprovalsInboxPage uses (appName || 'setup'). It stays as is. (Corrected by the seat: the first wording said the fallback is never reached.)
Rework round 1 is pushed: head is `1e66fe274f1e06d3cb221430b131bf1c63683d60`, and the aria-label census that failed CI now passes.
Head:
- `a905975`: the fix.
- `1e66fe2`: merge of `origin/main`, a merge commit, no history rewrite. It merged cleanly with no lockfile change.
Fix: The presets row no longer has a literal accessible name. It is now `role="group"` with `aria-labelledby` pointing at the visible "Presets" caption, whose id comes from `useId()`. No pack key and no EXEMPT entry were added, so `Clause-②: no` stands.
Pin: A new test, "names the presets row by its visible caption, not a literal aria-label", in `AuditLogPage.presets-12667.test.tsx`. It checks that the group is found by role and name "Presets", that it has no `aria-label`, and that its `aria-labelledby` points at an element reading "Presets".
Red, as required:
- Census at `5838608`: `pnpm exec vitest run packages/i18n/src/__tests__/ariaLabelLiteralCensus-12145.test.ts` failed with `AuditLogPage.tsx · Presets — declared 0, found 1 :399` (1 failed, 4 passed).
- Ablation: I put the literal `aria-label="Presets"` back with `ablation-replace.mjs` (anchor 1 → 0, blob `a240710efea6` → `5b749832761a`).
- Both the census and the pin failed: 2 failed, 11 passed.
- The file was restored to the HEAD blob `a240710efea6f48cafe9e4c0d7fcc0d4280f04b4`, and `git diff HEAD` is empty.
Tests at `1e66fe2`: I ran `packages/i18n/src/__tests__` together with round 0's 35 files. Result: 118 files passed; 1593 tests passed and 13 skipped. I did not look into which 13 are skipped. Exit code was 0.
Gates at `1e66fe2`, all exit 0:
- The console dependency build, `pnpm --filter @object-ui/console type-check`, and `VITE_BASE_PATH=/console/ … vite build`, together under the lock.
- `check:changeset-claims`, `changeset:check`, `check:test-path-roots`, `check:spec-symbols`, `check:new-line-citations`, and changeset presence.
- eslint on the two changed files reports the base file's 2 existing warnings and no new ones.
- CI families: not measured here; they will run on PR #12750's new head.
PR body lines to change: (applied by the seat)
Line 2 stays `Clause-②: no`.
Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, with its three PR-body lines folded into the body by the seat. The seat read a905975's diff: a useId() caption id and aria-labelledby on the group, and one new pin. Next: CI on 1e66fe2, then the ACCEPT.
Verified by content: the merge commit's own diff equals the PR's diff from its merge-base 1d869199c1 to the reviewed head 1e66fe2, changed line for changed line in each of the 6 files (+413/−18). Positive control at the merge commit: AuditLogPage.tsx names the presets group with aria-labelledby={presetsCaptionId}.
Card: closed completed by Fixes #12667. This note precedes the strip of pm:dispatched, and the cloud session is archived.
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 5 (
priority:p2; the objectui half of objectstack-ai/objectstack#23890, item 1 of objectstack-ai/objectstack#23803)Session:
session_011K9g23W67dy2zwnyzaoB6oAccount:
os-teslaBranch:
claude/issue-12667-audit-presetsWorktree:
objectui-issue-12667(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#1File surface: the
audit:logbrowser,apps/console/src/pages/system/AuditLogPage.tsx:sys_audit_logas a preset, read from the object metadata the console already loads, never copied as literals;sys_audit_loglist;@object-ui/i18npack keys only if the page already reads packs for its copy, in all ten packs;.changeset/12667-*.mdif the console package's rules ask for one.Outside the surface:
nav_audit_logs): Setup navigation, one audit entry: "Audit Log" opens the audit browser and the record list becomes its presets (item 1 of #23803; plugin-audit nav + the console audit page) objectstack#23890,domain:services,Blocked-by:this card.plugin-audit's list views themselves (objectstack).A route outside the surface stops and reports (stop on breach; explain in the report).
Container & model:
M,mode:cloud,model: opus(default tier; no path-derived mandate)Clause-②: no
Clause-② reason: the browser starts reading list views the platform already declares on
sys_audit_log, and adds a link. If the PR adds published pack keys or exports, its body flips this line toClause-②: yes, which the seat'sTIER_DEFAULTACCEPT covers.Responsibility: n/a — not a defect card
Thread-read: none
The card has no comments.
Serial constraints cleared: read at objectui
mainc41ce3f241.AuditLogPage.tsx's header, has merged.AuditLogPage.tsx.pm:blocked) waits on this card.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{ "issue": 12667, "status": "done", "branch": "claude/issue-12667-audit-presets", "pr": "https://github.com/objectstack-ai/objectui/pull/12750", "session": "session_01ESLcqKU7sTVG6SNoeDrjME", "premise_still_valid": true, "summary": "The audit:log browser (apps/console/src/pages/system/AuditLogPage.tsx) now reads sys_audit_log's listViews from the console's object metadata (useMetadata().objects, the same composed read the object list's view switcher uses). It offers one preset per served view, by served label, in served order. No view is named in code. A preset sends the view's own filter, lowered by @object-ui/core's toFilterNodeSafely (the same lowering the object list runs), beside the bar's filters via mergeFilterNodes. Columns, sort and page size stay the browser's own. A view the lowering refuses, or one bound to another data source, is shown disabled with its reason and a link to that view in the list; it never sends a filter. The header gains 'Open as list': it links to /apps/APP/sys_audit_log, or to /apps/APP/sys_audit_log/view/KEY when a preset is active (KEY is the listViews key, the same id the list's view tabs use). Hypotheses: H1 confirmed (the page built its own Mongo-style $filter). H2 confirmed live: six served views, each filter a spec rule array of {field, operator, value}. H3 confirmed live: the named view route opens the same view (Writes: 32 rows in the browser, 32 records in the list). H4: no strings were added to packs; copy is English literals like the rest of the page, so Clause-② stays no. Live reading at 1280 px is on claude/issue-12667-evidence under evidence/12667/ (commit 694c35846f): four PNGs showing no preset, Auth, Writes, and Open as list landing on the Writes view. Backend: @objectstack/*@18.0.0-next.2 showcase via e2e/live/ci/start-backend.sh; it needed no fix. Setup: per the PM's recipe, the primary checkout was detached and the worktree objectui-issue-12667 was added on the existing branch, fast-forwarded from c41ce3f to origin/main b393152.", "tests": "New file apps/console/src/pages/system/AuditLogPage.presets-12667.test.tsx, 7 tests. Its fixture is a sys_audit_log document whose views (night_shift, everything, broken, elsewhere) are keys no code names, so a literal copy cannot pass. It pins: every served view appears as a preset in served order; choosing a preset sends exactly [[\"action\",\"in\",[\"login\",\"logout\"]]] and choosing it again removes it; the preset joins the bar's filters; a view with no filter sends none; inexpressible views are disabled with a link and send nothing; Open as list reaches the list, and the preset's view when one is active. Three existing render sites were wrapped in MemoryRouter (actorName-11701, pageHeader-12553, consoleFaces.displayLocale-9909) because the page now renders a Link. Run at 5838608 (under the lock): `pnpm exec vitest run apps/console/src/pages/system apps/console/src/pages/consoleFaces.displayLocale-9909.test.tsx apps/console/src/__tests__/orphanedPageComponentRefs-10520.test.tsx scripts/__tests__/dollar-dialect-alias-census.test.ts` gave Test Files 35 passed (35), Tests 271 passed (271), VERDICT command-exit 0. Ablations used objectstack's scripts/ablation-replace.mjs on AuditLogPage.tsx (HEAD blob a835329adbb9); each mutation landed (anchor 1 to 0) and each was restored to blob a835329adbb99a6ae14d0e123f19deeab08a1fd9 == HEAD with git diff HEAD empty. No dist step: the tests import the page from source. A1, listViews replaced by a literal writes_only: 5 failed. A2, mergeFilterNodes(filter, presetNode) replaced by the bar filter alone: 2 failed ('sends the chosen view's own filter', 'joins the bar's filters'). The first A2 attempt was refused by the tool (replacement text not distinctive) and ran no test; it was re-run with a marked replacement. A3, Link to listHref replaced by '/': 2 failed (both Open-as-list tests). A4, refusal branch disabled so a refused view was approximated: 1 failed. Live wire check: core's actual merged output for the bar filters plus the Auth preset returned HTTP 200 with 3 login rows.", "gates": "Local, at 5838608 (exit codes captured before any pipe). `pnpm --workspace-concurrency=2 --filter '@object-ui/console^...' build`: VERDICT command-exit 0 (needed before type-check; the first type-check before this build exited 2 with TS2307 on unbuilt workspace packages). `pnpm --filter @object-ui/console type-check`: 0. `VITE_BASE_PATH=/console/ pnpm --filter @object-ui/console exec vite build`: 0. vitest as in tests: 0, 271 passed. `pnpm check:changeset-claims`: 0. `pnpm changeset:check`: 0. `pnpm check:test-path-roots`: 0. `pnpm check:spec-symbols`: 0. `node scripts/check-changeset-presence.mjs`: 0. `pnpm check:new-line-citations`: 0 (0 new citations). eslint --no-inline-config on the 5 changed source and test files: 0 errors; AuditLogPage.tsx keeps the base file's 2 pre-existing warnings. My first draft added 4 warnings; commit 5838608 removed them. Not run: the i18n checks, because no pack changed. objectui has no scripts/pm/dispatch-gates.mjs, so there is no --ran reconciliation; the local set was derived by hand from package.json and ci.yml. CI families: NOT MEASURED, no PR yet; the seat opens it.", "mcp_calls": "2 — mcp__github__issue_read (get, get_comments); no write tool", "api_writes": "0 — git pushes only: claude/issue-12667-audit-presets (3 pushes) and claude/issue-12667-evidence (1 push, plumbing-built parentless commit)", "open_questions": [ { "question": "The active preset is component state, like the page's other filters, not a URL parameter. AGENTS.md #8 classes shareable or refresh-surviving state as URL state.", "options": ["A keep it as component state, consistent with the page's existing filters (shipped)", "B move the preset, and later the whole filter bar, into URL params from app-shell's urlParams.ts in a follow-up"], "recommendation": "A for this card, because the card asks for presets and a link, not addressable filters; adding URL state only for presets would split the page's state between two homes. B is a whole-page follow-up only if someone asks for it." } ], "out_of_scope_findings": [], "deviations": [ "My first worktree command chain, which included `git branch -D`, was refused by the auto-mode classifier and nothing in it ran. I then used the PM's recipe: detach, worktree add on the existing branch, ff-only merge.", "While building the evidence commit, a shell variable-expansion slip produced an empty sha, and one push went out as `git push origin :refs/heads/claude/issue-12667-evidence`, which is a delete refspec. The ref did not exist yet, so git answered 'Everything up-to-date' and nothing changed; git ls-remote showed no such branch beforehand. The real push followed behind a non-empty guard.", "The worktree ../objectui-issue-12667 and its node_modules are kept, because the PR is not open yet; the role file's cleanup step runs after the PR opens. The vite dev server (:5167) and the backend (:4067) were stopped by their recorded PIDs, and the ports were checked free." ] }Posted by the
domain:uiseat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filledprwith the draft PR it opened, #12750.The seat's answers:
5838608and the evidence branch were both read on the server.listBasefalls back to thesetupapp when the route carries noappName. The fallback is reached on a served route:systemRoutes(apps/console/src/AppContent.tsx) is mounted both under/apps/:appNameand in the no-app table, so/system/audit-logrenders on a zero-app deployment. There/apps/setup/sys_audit_logis the generic Setup object route, the same fallbackApprovalsInboxPageuses (appName || 'setup'). It stays as is. (Corrected by the seat: the first wording said the fallback is never reached.)Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev delta report (REWORK round 1 on PR #12750)
Posted by the
domain:uiseat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, with its three PR-body lines folded into the body by the seat. The seat reada905975's diff: auseId()caption id andaria-labelledbyon the group, and one new pin. Next: CI on1e66fe2, then the ACCEPT.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T18:39Zmain8296c6c3ca, with one parent,2dbe5f5. It is an ancestor oforigin/main.1d869199c1to the reviewed head1e66fe2, changed line for changed line in each of the 6 files (+413/−18). Positive control at the merge commit:AuditLogPage.tsxnames the presets group witharia-labelledby={presetsCaptionId}.completedbyFixes #12667. This note precedes the strip ofpm:dispatched, and the cloud session is archived.pm:blockedon this card) can removenav_audit_logsonce objectstack's.objectui-shacarries8296c6c3ca.Generated by Claude Code