Warning, /swf-monitor/AGENTS.md is written in an unsupported language. File is not indexed.
0001 # swf-monitor
0002
0003 Start from the SWF workspace guide, `../swf-testbed/CLAUDE.md`
0004 (<https://github.com/BNLNPPS/swf-testbed/blob/main/CLAUDE.md>): the
0005 system, the workspace, how to work, production and collaboration. This
0006 file adds what is particular to swf-monitor, the platform's monitor, web
0007 and database services: the Django web app, REST API, MCP server, and the
0008 platform machinery (action stream, SysConfig, alarms, SSE relay), hosting
0009 the production applications installed from `swf-epicprod` and running
0010 the production operations agent. It is a core repository, developed on
0011 the current `infra/baseline-vNN` branch with swf-testbed and
0012 swf-common-lib. This file is the repository's doc index and carries the
0013 one pattern every designer and implementer holds in mind; its documents
0014 carry the implementation detail beneath the WFMS documentation
0015 (<https://epic-wfms-docs.readthedocs.io>).
0016
0017 ## Key pattern — credentialed async action with live browser push
0018
0019 The system is a live, automated, responsive production system. The standard way
0020 to add a credentialed, slow, or hang-prone capability is the prod-ops agent
0021 pattern — not a poller, not a blocking request, and never a credential in the web
0022 tier:
0023
0024 > a new `_handle_<msg_type>` + a `run_in_background` doer (the agent holds the
0025 > Rucio / PanDA / xrootd credentials) + a completion event on `/topic/epictopic` +
0026 > an `EventSource` on the triggering page → the action fires server-side and the
0027 > result is pushed to the browser the instant it is done — internally, and (via
0028 > the swf-remote streaming proxy) to remote collaborators.
0029
0030 Worked examples: payload-log fetch and PanDA submit. Read before designing any
0031 production-ops feature: **`swf-epicprod/docs/EPICPROD_OPS_AGENT.md`** (the
0032 agent and the pattern) and **`docs/SSE_PUSH.md`** (the browser push).
0033
0034 ## swf-remote tunnel flag
0035
0036 swf-monitor templates receive `is_tunnel` from
0037 `monitor_app.middleware.tunnel_context`. It is true for localhost requests from
0038 the swf-remote SSH tunnel and false for direct `pandaserver02` browser access.
0039 Use this flag for conditional template behavior that must differ on the external
0040 proxy face, such as disabling page-view POST controls that are only supported on
0041 `pandaserver02`. Do not infer tunnel/proxy mode from URL strings or implement
0042 HTML rewrites in `swf-remote` when `is_tunnel` can express the condition in the
0043 swf-monitor template.
0044
0045 ## corun-ai naming
0046
0047 The backing AI/document service is `corun-ai`. Do not write `CORUN` as a product
0048 or system name in prose, UI text, reports, MCP descriptions, logs, or commit
0049 messages. Existing compatibility names such as `CORUN_BASE_URL`,
0050 `CORUN_API_TOKEN`, and `corun_page_group_ids` are config/schema identifiers only.
0051
0052 ## Doc index (`docs/`)
0053
0054 The epicprod/PCS documentation set lives in `swf-epicprod/docs/` — see the
0055 index there (README and `ARCHITECTURE_MAP.md`); permanent stubs remain at
0056 the old paths here. This repo's docs cover the platform services:
0057
0058 - `ACTION_STREAM.md` — the action stream: structured action logging (sublevel/live axes, SysConfig live policy), live view, retrieval for LLMs (renamed from `EPICPROD_ACTION_STREAM.md`; the stream machinery is platform).
0059 - `AI_PROPOSALS.md` — AI proposals: LLM proposes, human approves, deterministic execution; record-resident v1, origin-stamped events, the `.ai-attr` UI convention.
0060 - `SSE_PUSH.md` — browser push of agent action completion (design).
0061 - `SSE_RELAY.md` — the ActiveMQ → remote SSE relay this builds on.
0062 - `EXTERNAL_ACCESS.md` — the swf-remote proxy contract, including write-action trigger rules.
0063 - `TEAMCOMMS.md` — embedded TeamComms, devcloud authentication, request binding, identity and stream revalidation.
0064 - `USER_VIEW.md` — the user view: the reduced epicprod face behind the universal `user_view` parameter, its nav and conventions, and how a page tailors itself.
0065 - `SYSTEM_STATUS.md` — cached system status record and page.
0066 - `COMP_SNAPSHOT.md` — the comp snapshot: the computing centre room's live record (`swf_comp_snapshot`, `panda/comp/snapshot.json`).
0067 - `PROD_DASHBOARD.md` — the production dashboard for collaborators, fed by the comp snapshot, the room as its proving ground (plan).
0068 - `SNAPPER.md`, `SNAPPER_ERRORS.md`, `SNAPPER_PLATFORM.md`, `SNAPPER_STORAGE.md`, `SNAPPER_CATALOG.md`, `PANDA_SERVER_REPORTER.md` — Snapper operations in SWF; the error-state component and errors view; the platform-health component, Platform view, and the pandaserver01 reporter; the Storage view over the storage record; the JLab Rucio catalog component and Catalog view. All four are in production.
0069 - `ERROR_ATTRIBUTION.md` — correcting unreliable PanDA error labels at a single service root: rule lifetimes, evidence grades, representative-job digs, payload/pilot channels.
0070 - `CACHED_PRODUCTS.md` — uniform long-build caching: serve stored, rebuild behind, Update button; use this, never a new hand-rolled cache.
0071 - `COMPUTE_EFFICIENCY.md` — retained successful-job core-hour history, site heatmap and month/week trends, and scheduled refresh.
0072 - `EVENT_SERVICE_PLOTS.md` — task and job core timelines from finished reports and timestamped harness snapshots.
0073 - `INCLUSIVE_FILTER.md` — the two house facet filters: the inclusive filter (every value stays listed, selections widen, one URL key `f`) for views that assemble a set, and the narrowing filter (one parameter per facet, the intersection, every bar counted within the selection) for the operations views; pages switch to them one at a time.
0074 - `PRODUCTION_DEPLOYMENT.md` — deploying swf-monitor.
0075 - `SCRIPTS.md` — the standalone scripts in `scripts/`: the Django header, arguments, stderr progress and the JSON summary line, the action record, and how to run one by hand.
0076 - `API_REFERENCE.md` — REST API surface.
0077 - `MCP.md`, `MCP_TOOL_REFERENCE.md`, `MCP_CLIENTS.md`, `PANDA_BOT.md` — MCP server overview, tool catalog, client setup, and the DISpatcher Mattermost bot (MCP client).
0078 - `alarms.md`, `ALARM_QUEUE.md` — the alarm engine; the alarm queue design: lifecycle transitions, per-subscriber feeds with read state, automated response (design).
0079 - `PINGS.md` — pings: dated obligations at severity ping in the alarm system, entered by hand or by AI proposal, overdue becomes alarm, cleared on fulfilment (design).
0080 - `NOTICE_ROUTING.md` — notice routing: named incidents matched to self-registered subscribers and delivered per subscriber, so emitting code declares the incident and never names a recipient.
0081 - `WRANGLER_AGENT.md` — the wrangler agent: BaseAgent identity with a wrangle-ai work loop (durable bullpen, Postgres bell), the LLM-doer executor beside the production ops agent; first handler is the alarm responder (design).
0082 - `SETUP_GUIDE.md`, `TEST_SYSTEM.md`, `POSTGRES_MCP.md` — setup, tests, Postgres MCP.
0083 - `FASTMON_FILES.md`, `TFSLICE.md` — testbed fast-monitoring docs.
0084
0085 ## Editing discipline (AI sessions)
0086
0087 Material production findings and resolutions must be reported in
0088 `epicprod-live`, with affected scope, current status and supporting evidence.
0089 Private dialog, LLM messages and commits are not substitutes. Follow
0090 `docs/NOTICE_ROUTING.md` (Findings and resolutions); this is forward-only,
0091 not a requirement to backfill historical investigations.
0092
0093 - The app is served under the `/swf-monitor/` script prefix, which exists
0094 only in request context. Never bake `reverse()` output into values built
0095 outside a request — cached products, background threads, shell probes,
0096 agents — the path comes out prefix-less and dead. Store query strings or
0097 names; resolve the path at render time (`{% url %}`).
0098 - Templates and HTML are edited with precision edits (the Edit tool), never
0099 stream editors (`sed`/`awk`) — a regex that clips one attribute quote
0100 renders as a silently truncated page.
0101 - Before every commit: `bash scripts/pre-commit-checks.sh` — compiles
0102 changed `.py`, one Django system check, lints changed templates; under
0103 ten seconds, and it encodes the manage.py/venv invocation so no session
0104 rediscovers it.
0105 - After any deploy that touched templates: smoke-check the affected page's
0106 content (fetch and confirm a marker below the changed region), not just
0107 the deploy's HTTP 200 health check.
0108 - Any new or edited doc gets a separate re-read at doc voice before the
0109 commit — dialog phrasings leak into docs under momentum.
0110
0111 ## Button roles
0112
0113 One role → one treatment, everywhere (all `btn-sm`, solid variants):
0114
0115 | Role | Class | Examples |
0116 |---|---|---|
0117 | Constructive: create / save / new / import / match | `btn-primary` | Save, New Task, Import |
0118 | Object verbs on existing items: edit / copy | `btn-dark-green` | Edit, Copy |
0119 | Consequential commits: submit / lock / publish / approve-and-execute | `btn-success` | Submit to PanDA, Lock, Publish, Approve |
0120 | Suggestion adoption (yellow suggestion bars only) | `btn-warning btn-apply` | Apply |
0121 | Destructive: delete | `btn-danger` | Delete |
0122 | Neutral dismiss / utility: cancel / clear / open-close all | `btn-secondary` | Cancel, Clear |
0123 | Stateful toggles ONLY (fill = on/off) | `btn-outline-*` | Catalog/Progress switch |
0124
0125 Outline is never the default reflex — anything that acts is solid, colored
0126 by role.
0127
0128 ## House UI helpers (base template)
0129
0130 Shared page utilities live at the bottom of `src/templates/base.html` and
0131 are available on every page. Use these — never reimplement them in a
0132 page template:
0133
0134 - **Relative time**: give any element
0135 `data-relative-time="<ISO timestamp>"` and its text renders and ticks
0136 every second as `just now` / `Ns ago` / `Nm ago` / `Nh ago` / `Nd ago`
0137 (`window.swfFormatElapsed` is the formatter). Optional
0138 `data-relative-time-interval="<seconds>"` slows that element's redraw
0139 to every N seconds.
0140 - **Poll gate**: `window.swfPollGate.attended()` reports whether the page
0141 is attended — visible, and either its window holds focus or it was
0142 interacted with within five minutes — and
0143 `swfPollGate.onReturn(fn)` registers a catch-up callback for when
0144 attention returns. Gate every recurring client-side fetch on it;
0145 `document.hidden` alone is not sufficient, because the frontmost tab
0146 of an unfocused window reports itself visible and polls forever.
0147 - **Editor fit**: `swfFitEditor(el)` (or class `swf-fit-editor` on the
0148 textarea) grows an in-page document editor to the visible window.
0149 - **AI attribution**: `.ai-attr` / `.ai-attr-text` (purple-on-lavender
0150 chip) and `.ai-fill` (lavender container) mark AI-origin content; the
0151 classes are defined in the base template's style block.
0152 - **Page tabs**: `.swf-page-tabs` renders first-class page views as an
0153 underlined tab row. Every tab is an ordinary server-routed link whose URL
0154 contains the selected view state; do not use hidden Bootstrap panels,
0155 client-only state, or a remembered preference for these tabs.
0156 - **Update-button feedback**: class `swf-update-btn` on a cached-product
0157 Update link shows `Updating...` while its navigation is in flight,
0158 restoring on pageshow and by a 20 s timeout so the label never sticks.
0159 - **Sortable tables**: DataTables is loaded globally in `base.html`
0160 and is the house table widget. Big list pages use the
0161 `_datatable_base` / `_datatable_dynamic_base` templates (ajax);
0162 static server-rendered tables get class `swf-sortable`, which the
0163 base template initializes as a chrome-free DataTable (sort headers
0164 only, no paging/search). Table columns are sortable by default
0165 everywhere; a non-sortable table is the special case and needs
0166 Torre's say-so. Static tables use the house table classes
0167 (`table table-striped table-bordered table-sm align-middle w-auto`).
0168 - **Latching and pinned tables**: DataTables and `swf-sortable` tables use
0169 the adaptive house table frame; class `swf-latch-head` opts in any other
0170 table. A table that fits the page keeps window scrolling and latches its
0171 header beneath the nav bar. A table wider than the page gets a fitted
0172 two-axis scroll region, with its header pinned at the region top and its
0173 first two columns pinned left. Set `data-swf-pin-columns="0"` or `"1"`
0174 only when two pinned columns are unsuitable for a particular table. Do
0175 not add an outer overflow wrapper; the house helper owns overflow.
0176 - **Status cells**: state values render with the BigMon fill classes
0177 via `{% load swf_fmt %}` and
0178 `<td class="{{ value|state_class }}">{{ value }}</td>` (or
0179 `task_badge`/`job_badge` for badge form). Never a bare status cell.
0180 - **Short names**: a concise setting (the computing-centre floor, board
0181 lines, compact tables, titles) shows a site, queue or resource name
0182 through the one filter, `{{ name|short }}` in templates or
0183 `monitor_app.short_names.short_name` in code (ComputeCanada-Fir reads
0184 Fir). A new abbreviation is added there, never in a page or view.
0185 - **Names and fields**: do not wrap human-facing names, identifiers, field
0186 paths, policies, publishers, or resolvers in `<code>`. The active theme
0187 renders code text red, which signals an error. Use a descriptive title and,
0188 when needed, a plain muted label such as “Internal name: health”.
0189
0190 ## Deploy
0191
0192 Maintainers deploy on the production host (pandaserver02):
0193 `sudo bash deploy-swf-monitor.sh branch <current infra/baseline-vNN>` — pulls from
0194 git, so commit + push first. Run it in the foreground.
0195
0196 The standard script creates an isolated release copy; “cloning” in its output
0197 does not mean it is changing the shared development checkout. Before running
0198 it, inspect every local package tree it freezes into the release, including
0199 swf-epicprod, snapper-ai, site-canary, and swf-common-lib, so another session's
0200 uncommitted work is not shipped.
0201
0202 For UI/template/view-only or MCP-tool-only changes, prefer the fast in-place
0203 sync: `sudo ./deploy-lightweight-ui-mcp.sh --ui` and/or `--mcp` (add
0204 `--static` when assets changed). Use the full deploy whenever migrations,
0205 requirements, Apache config, systemd units, ops-agent code, or bot code are
0206 involved. Commit first either way.