Compare commits

...
Author SHA1 Message Date
weichen 7a6cfeefeb merge: dev to test (rc-v1.0.0-beta.6 promotion) 2026-09-20 07:22:42 +00:00
weichen 9f29b0badb merge: docs/bug-hunt-2026-09-20-closeout 2026-09-20 07:05:51 +00:00
weichenandCursor c7ee6b825e docs(ops): close bug-hunt permissions-uploads task after merge to dev
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 07:05:51 +00:00
weichen 032fdb050f merge: fix/bug-hunt-2026-09-20-permissions-and-uploads 2026-09-20 07:05:34 +00:00
weichenandCursor 6800a2af29 docs(ops): record permissions/uploads bug-hunt audit and short-term task
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 07:05:06 +00:00
weichenandCursor c8dbefe8a1 fix(web): align settings CAS, PDF preview, and collaboration UX guards
Wire expected_revision, blob PDF framing, mustChangePassword session rewrite,
client_key project create, no-project send disable, and right-rail persistence.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 07:05:06 +00:00
weichenandCursor 5cd22c7327 fix(authz): harden permissions, chat gate, and project create idempotency
Add project:manage_members, CSP frame-src, task-run member view, CreateUser
tx error handling, ERR_NO_PROJECT chat gate, and creator-scoped project
name/client_key uniqueness to stop duplicate creates and auth gaps.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 07:04:57 +00:00
weichen 8fdcd983a6 docs(ops): record test promotion rc-v1.0.0-beta.5 and release integration slot 2026-09-20 01:10:43 +00:00
weichen dec963c16f merge: dev to test (rc-v1.0.0-beta.5 promotion) 2026-09-20 01:07:10 +00:00
weichen 0fd765a392 docs(test): record full deep test report for dev and test promotion 2026-09-20 00:48:11 +00:00
weichen bcbf4eba1c fix(pi-agent): register both MiniMax-M2.7-highspeed and MiniMax-M3 in models.json 2026-09-20 00:47:50 +00:00
weichen f47e40edad test(server): align test_manager task key to tm_system_verification in e2e test 2026-09-20 00:45:33 +00:00
weichen 97b868a942 docs(arch): allow squad in intent and workflowdef in squad and template 2026-09-20 00:44:47 +00:00
weichen 24bc4e6a2f merge: fix/audit-remainder-closeout (audit remainder closeout M1-M15, web modularization, rdev matching, schema 53) 2026-09-20 00:43:33 +00:00
weichen 89e8fb92b0 docs(ops): occupy integration slot for dev sub-branch merge, deep test and test promotion 2026-09-20 00:43:28 +00:00
weichenandCursor 3ae13bfae2 docs(test): record the U7 restart matrix and the gate follow-up
Postgres and app reach ready in about a second. Vite cold cache is not the old ten-second stall, and the login form was not measured.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 15:39:49 +00:00
weichenandCursor b48a832281 fix(squad): score only the first review-minutes table
A later standards table in the same section was counted as issue rows and failed the saved P3 sample.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 15:39:49 +00:00
weichenandCursor 6bd338e273 test(rdev): record the three real PI samples on dev
Software-plan N/A stayed closed and the proposal completed, but the planning review finished quality_failed at score 20. The poller now treats that status as terminal so it does not spin until timeout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 14:33:25 +00:00
weichenandCursor 56a8719863 refactor(web): move the workbench shell out of App
Session state stays in App. The shell, rights dialogs, and project modals now render from WorkbenchView, so App no longer mounts AppShell itself.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 14:11:32 +00:00
weichenandCursor 8a9599fbb0 refactor(web): render the chat column outside App
The workbench shell still owns session and modal state. Message stream, filters, and the composer now live in ChatColumn so App stops assembling that column inline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:57:10 +00:00
weichenandCursor b3a1305e46 docs(test): record twenty-run slow-network login and app restart
The rebuilt bundle stays under the draft login budgets on this machine. Restart-to-health is under half a second, and the wider restart matrix is still open.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:35:52 +00:00
weichenandCursor 69e2cd259d refactor(web): render the active document column outside App
The revision toolbar, file preview, and governance bars stay with the document pane so the workbench shell no longer owns that column.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:32:39 +00:00
weichenandCursor 26d14b534b docs(test): record schema 53 rebuild and login fanout on dev
The rebuilt workbench issues one member request and one session list request. Slow-network samples improved, but twenty-run percentiles and the restart matrix are still open.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:22:38 +00:00
weichenandCursor 404defced2 test(server): reject non-member comment and audit reads on postgres
The in-memory authorizer treats any positive user id as a member, so the HTTP negative has to run against a real project row.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:22:37 +00:00
weichenandCursor c49637cbb5 fix(db): restore applied goose files so fresh migrate can parse
The checksum-immutable note inside 00001 contained a goose annotation and would fail a new database. Keep that warning out of files goose already applied.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:22:37 +00:00
weichenandCursor 4b2d92a1be docs(test): record login-load baseline against Vite and deployed dev
The current workbench stays at one member fetch across 20 logins, while the deployed bundle still fans out. Slow-network samples stay diagnostic until the container is rebuilt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 13:00:39 +00:00
weichenandCursor eabaadd2a0 test(web): record login waterfall and init request counts
Give the initial-load baseline a repeatable probe that strips query strings and can assert the login member fanout stays on the current project.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:57:12 +00:00
weichenandCursor 95f0e7bcf9 refactor(web): share and save freeform docs from one hook
Keep private-library share, revoke, delete, and save-to-private off the workbench shell so those side effects stay testable without growing App.tsx.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:57:12 +00:00
weichenandCursor 8de29466e1 refactor(web): persist project members from one hook
Refresh the roster and workflow documents only after the member write succeeds, so a failed add does not invent a local session.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:11:52 +00:00
weichenandCursor a29e98096a refactor(web): create projects from one hook
Remember the new project id as soon as create succeeds so a later member failure retries members instead of creating a second project.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:09:28 +00:00
weichenandCursor 9f39fbaaf3 refactor(web): handle interactive cards from one hook
Keep plan confirmation, reject, undo, and approval on the same card so a revision conflict still reconciles before the card changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:07:08 +00:00
weichenandCursor 57873f6c84 refactor(web): retry chat and task runs from one hook
Keep reconnect on the existing run id so a dropped stream does not start a second task.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:05:01 +00:00
weichenandCursor f9c2b3acdf refactor(web): edit document blocks from one hook
Apply a controlled block only after the server patch succeeds, and keep insert, move, delete, and comments on the same document state.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 12:00:43 +00:00
weichenandCursor 52f69fe180 refactor(web): send chat messages from one hook
Keep attachment registration, task dispatch, and the demo shortcuts on the same path so a failed upload still blocks before any local message is stored.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:46:07 +00:00
weichenandCursor c22faecfcb refactor(web): move document lifecycle actions into a hook
Keep claim, review, and approval on one server record so the open document and the sidebar stay in the same state.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:40:03 +00:00
weichenandCursor 22ea4c31ed refactor(web): sync server documents from one hook
Keep freeform append, workflow reconcile, and lease polling together so a failed list cannot wipe local docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:33:03 +00:00
weichenandCursor 113dea4ac5 refactor(web): hydrate controlled documents from one hook
Keep the editor gate, cancel, and error skeleton together so App no longer owns the fetch path.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:29:40 +00:00
weichenandCursor 27c1be86d5 refactor(web): move login workspace sync out of App
Project list, member roster, and session fetch ran as four effects inside the workbench component. They now share one hook so the entry file is not the only place that knows the login startup order.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:05:29 +00:00
weichenandCursor bfe8cb1407 refactor(web): persist the workbench from one hook
Session, project, and deliverable caches were written from scattered effects, and the legacy message migration ran twice on mount. One hook keeps that write path in a single place.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 11:01:44 +00:00
weichenandCursor 63b0f72081 feat(web): load the formula engine only when math appears
The login entry no longer ships KaTeX. Chat bubbles and document text render formulas after a dynamic import, and rich-text copy does the same.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:57:49 +00:00
weichenandCursor dba8139d56 feat(workflow): namespace task keys without breaking old instances
Published manifests now use bd_/pm_/tm_/sw_ prefixes so workflows cannot share a doc id. Frozen instances keep the old keys; lookup, templates, and duty checks treat the two names as the same task.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:50:25 +00:00
weichenandCursor 2a0f8b4549 docs(ops): record the frontend test and build gate
npm test and the production build passed on this branch. The entry bundle stays near 1 MB, and CURRENT still correctly says schema 52 until the containers are rebuilt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:34:50 +00:00
weichenandCursor 7e0f3cbf9c feat(web): show the rdev start prerequisite before activation
Selecting the design-control workflow now repeats the server rule: business handover must finish with an approved CDO quote first. Other workflows stay quiet.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:33:11 +00:00
weichenandCursor 6367f865d5 feat(web): fold long workflow stages and batch their approval
Later stages with more than four documents start collapsed, and one action can put the whole stage under human approval or take it back out. The workflow chip still names the design-control flow when the catalog has not loaded.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:30:32 +00:00
weichenandCursor 5bf10c7536 docs(ops): keep the login fan-out note next to the rdev matcher
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:27:08 +00:00
weichenandCursor 2fbb5bab49 feat(intent): match rdev document names when the user asks to generate
生成项目建议书 now resolves to rd_proposal. Longer titles win, so 系统设计方案 is not mistaken for the shorter business-stage phrase, and an explicit generate command is no longer swallowed by a progress question.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:26:57 +00:00
weichenandCursor 890d2fd14e fix(web): stop login from fetching every project member list
The project list is already limited to the current user, so other rosters wait until the member panel opens. Session reload no longer follows project updates, and a newer response cannot overwrite an older user.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:22:04 +00:00
weichenandCursor b550911667 feat(squad): load rdev overlays and enforce document gates
Each rdev step now gets a role-filtered overlay so writing discipline stays out of the template. User needs, system requirements, review minutes, and upload indexes fail the quality gate when IDs, decisions, or attachment indexes are incomplete.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:12:10 +00:00
weichenandCursor 93ee98af0e feat(squad): apply rdev stage step overrides and aliases
Stage-specific squad steps now win over the kind default, including always-on regulatory and searcher roles. Each of the 60 tasks carries its writing hint and Chinese alias so lookup and the writer accept line use them.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:05:26 +00:00
weichenandCursor 8365de3426 docs(ops): keep the load and auth notes next to the rdev remainder
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:58:51 +00:00
weichenandCursor 754cba764c feat(squad): gate rdev regulatory steps on complexity tier
Listed tasks still get a regulatory step when complexity is unset or high. Medium and low skip it, and the squad model now comes from SQUAD_MODEL_ID or MINIMAX_MODEL_ID instead of a fixed name.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:58:40 +00:00
weichenandCursor 32d838285d fix(auth): resolve session and user status once per request
/auth/me was authenticating again after the middleware had already done it, and the session lookup queried user status in a second round trip. Reuse the request principal and join status into the session read so a revoked token still fails on the next request.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:54:10 +00:00
weichenandCursor 17f7fed1db feat(web): load export, preview, and charts only when opened
The login shell was downloading the document engines with the workbench. Those modules now load on click or when a matching block appears, and a failed chunk can be retried without submitting an edit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:51:04 +00:00
weichenandCursor 1b17e01ce7 docs(ops): record frontend gate and the memory authz limit
The branch frontend suite and production build passed. Cross-user document comments still need a Postgres negative because the in-memory authorizer is intentionally open.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:42:30 +00:00
weichenandCursor 952a94b6d5 fix(docrevision): ack content projection only after the fact source is written
The human ledger and the document body are different stores. Record the projection intent in the same transaction as the ledger, and clear it only when the body write succeeds so a retry cannot append a second revision.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:35:14 +00:00
weichenandCursor fc32ba3dc3 fix(web): version chat window cache and cover cross-user session list
Drop window-cache payloads that lack a schema field. Prove a non-owner listing another user's sessions is forbidden. Correct the stale test schema note in CURRENT.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:28:11 +00:00
weichenandCursor 2a666df3c1 fix(events): hold aggregate gaps on production claim
PostgreSQL claim now uses the same next-version rule as MemoryBus, and checkpoints only move forward. A later version cannot be leased while an earlier one is still missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:24:51 +00:00
weichenandCursor 01ca861e94 docs(ops): record which audit remainder items are closed
Keep M7, M15, the frontend split, and the red-line features open so the next pass does not treat them as done.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:20:07 +00:00
weichenandCursor d4041a4f0c fix(coordinator): use the caller name and reject non-decimal user ids
Ambiguous consult only redirects on low confidence, and the testing template greets the signed-in user instead of a hardcoded name. Session tokens no longer parse as user id 0. Live chat sessions now evict the oldest entry at a hard cap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:19:36 +00:00
weichenandCursor 265f09c1f2 fix(server): cache health probes, surface SSE marshal errors, fail closed on missing duties
Health checks reuse a two-second snapshot and bound the schema query. Task SSE writes an error frame when an event cannot be encoded. ResolveDocTask errors when the frozen plan has no duty row, while explicit none-duties stay zero. Drop the unwired semantic-summary replace env, record the intentional dev versus release model split, document the test/main cutover path, and archive pre-goose SQL.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:16:18 +00:00
weichenandCursor 4c34e8a503 fix(server): close security headers, lease clamp, replay digest, double start
Add nosniff, frame denial, referrer policy, and a self-origin CSP. Clamp human and squad lease TTLs and require author edit rights before a human lease. Include DryRun in replay digests so a dry-run approval cannot authorize apply. Stop Server.Start from swallowing a second Runtime.Start.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 09:12:17 +00:00
weichenandCursor 62ce2781ae docs(ops): record pre-test promotion readiness review
Capture the read-only check that planned capabilities are wired, while dev is not ready to merge into test until the container is rebuilt and the remaining gates run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 08:36:58 +00:00
weichen 66421b162d merge: docs/audit-remediation-backlog (audit batch 4 report + medium backlog) 2026-09-19 07:55:48 +00:00
weichenandCursor d9cd7ebb82 docs(ops): close audit batch 4 report and park medium leftovers
Critical/high fixes are already on dev. Record the frontend test report, restore the audit note, and move remaining medium/low items into long-term so they are not treated as release blockers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 07:55:43 +00:00
weichen d73bc79800 merge: fix/audit-b4-frontend (audit batch 4: markdown XSS, unread rollback, excel preview cap) 2026-09-19 07:53:36 +00:00
weichenandCursor 6c28fca98f fix(web): close markdown placeholder XSS and unread/excel edge cases
- Escape KaTeX fallback HTML and salt math/code placeholders per render
- Roll back optimistic unread marks when POST /chat/read fails
- Reset MessageStream scroll baseline when the session changes
- Preview only the first 1000 Excel rows and say so in the sheet header

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 07:53:31 +00:00
weichen 84ba1c97d7 docs(test): audit batch 3 test report and slot release 2026-09-19 07:49:45 +00:00
weichen a2a49a64f5 merge: fix/audit-b3-sse-events (audit batch 3: sse heartbeat, task idempotency, write deadline, fencing log) 2026-09-19 07:49:15 +00:00
weichenandCursor b65e8fb642 docs(db): mark baseline and seed migrations as checksum-immutable
Goose checksums forbid rewriting applied files. Document that 00001-00009
have no down migration and that 00012's unconditional DELETE is demo-only.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 07:49:01 +00:00
weichenandCursor 0531462acc fix(sse): bound heartbeat lifetime and reuse idempotent task streams
- Wait for the chat SSE heartbeat goroutine to exit before the handler
  returns, so it cannot write a recycled connection
- Extend /tasks/run write deadline to 75m so long sync runs are not cut
  by the global 120s WriteTimeout before the response is written
- Reuse an existing task run on the SSE path when the idempotency key
  already belongs to the same user/session/project
- Log stale fencing on event ack so unbounded replay is observable

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 07:49:01 +00:00
weichen 9fa29bec42 docs(test): audit batch 2 test report 2026-09-19 06:03:31 +00:00
weichen c3c2b39abd docs(ops): record audit batch 1+2 merges and slot release 2026-09-19 06:02:38 +00:00
weichen 08f4e0bbf8 merge: fix/audit-b2-authz-hardening (audit batch 2: principal identity, docgov access, rate limit, compose secrets) 2026-09-19 06:01:00 +00:00
weichenandCursor 2dd8f46e64 fix(server): login/register rate limiting + compose secret hygiene (H4/H8/M8)
- H4: sliding-window rate limiter (10 attempts / 5min per IP+username)
  on login and register; successful login resets the counter; pure
  stdlib, no new dependency
- H8: docker-compose.test.yml DB/ADMIN passwords now :?required (align
  with main); docker-compose.main.yml AUTH_REGISTRATION_ENABLED
  defaults to false
- M8: fix FAV_PUBLISHER_ENABLE -> FAV_PUBLISHER_ENABLED typo so the
  gate test actually guards the real flag

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 06:00:30 +00:00
weichenandCursor d2903a1662 fix(server): enforce principal identity and docgov project access (H1-H3)
- H1: log legacy test-principal fallback (path/method/remote_addr) via
  slog.Warn so silent unauthenticated access is observable
- H2: AddComment/Claim now derive actor ID/Name/Role from the auth
  principal and server-side doc duty resolution (resolveDocGovRole),
  never from request body; GetDocument/ListComments/ListAuditLogs now
  require project membership via requireDocGovDocAccess
- H3: handleGetChatTurn asserts session ownership; handleListChatSessions
  and handleGetUserContext reject cross-user user_id (403) and stop
  defaulting to user id=1

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 05:33:38 +00:00
weichen 844f757af3 merge: fix/audit-b1-data-consistency (audit batch 1: docgov persist errors, session race, workflow plan tx, ctx threading) 2026-09-19 05:04:18 +00:00
weichenandCursor a81db16cdd fix(server): thread request ctx through session bootstrap, drop Background DB calls
- getOrCreateSession now takes ctx; GetSessionOwnerID/
  RestoreSessionContext/CompilePromptGuidance run under
  context.WithTimeout(5s) instead of context.Background()
- SyncRecentDialogue's rolling summary uses a 30s timeout context
  instead of Background, so client disconnect cancels the LLM call

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 05:03:01 +00:00
weichenandCursor e2b13406db fix(projectinstance): atomic plan save and correct completed_by attribution
- Add Store.SavePlanWithRevision: single-transaction planning upsert +
  revision bump (bump first with optimistic lock, conflict rolls back
  before any plan write), closing the SaveWorkflowPlan split-transaction
  race where plan content and revision could diverge
- AdvanceStage now takes operatorID and writes completed_by explicitly
  instead of SELECT activated_by, so the completing operator is the
  actual advancing user, not the original activator
- Service.SaveWorkflowPlan/AdvanceStage pass userID through; memStore
  implements SavePlanWithRevision under its single mutex

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 05:00:01 +00:00
weichenandCursor c7eab1f7d1 fix(chat): add RWMutex to Session and snapshot accessors to close data race
- Session gains mu sync.RWMutex + SnapshotMessages/AppendMessage/
  TouchLastAccessed/SetProjectID/Project accessors
- sendMessageInternal, hydrateVisibleHistory, getOrCreateSession,
  cleanStaleSessionsLocked, handleChat, handleChatStream,
  enrichSessionWorkflowStage, bindSessionDocumentSummaryReader all use
  locked accessors instead of raw field access
- ProjectID mutation now goes through SetProjectID (only when changed),
  closing the cross-project pollution window in handleChat/handleChatStream

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 04:55:55 +00:00
weichenandCursor 11f375f53d fix(docgov): surface lease/audit persist failures and read back fencing token
- persistLeaseLocked now returns error; AcquireLease rolls back in-memory
  lease on DB failure so memory and PG stay consistent
- appendAuditLocked uses request ctx and logs audit INSERT failures
  instead of swallowing them with context.Background()
- loadDocumentFromDBLocked now SELECTs lease_fencing_token so fencing
  survives process restart
- SaveDocumentContent/RecordDocumentViewed/RecordDocumentEdited/
  DecideModificationProposal/SetDocumentWorkDir log persist failures
  via slog.Error instead of silent _, _

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 04:50:40 +00:00
weichen e8ed33b0aa merge: fix/remove-control-center leftover cleanup 2026-09-19 03:55:40 +00:00
weichenandCursor 597aa76e60 docs: record leftover Control Center cleanup
The untracked node_modules tree and the local feature branch are gone.
The remote branch was left in place.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:55:40 +00:00
weichen d21f024dbe merge: fix/remove-control-center health closeout 2026-09-19 03:43:22 +00:00
weichenandCursor 9f2c510b62 docs(test): record dev health after Control Center removal
The rebuilt dev service returned 200 with schema 52.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:43:22 +00:00
weichen 03ec351643 merge: fix/remove-control-center 2026-09-19 03:42:23 +00:00
weichenandCursor 87f6b68001 docs(test): record Control Center removal verification
The short tests, archtest, and product web build passed after the
module was deleted.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:42:23 +00:00
weichenandCursor 14f75df1ac refactor: remove Control Center from this repository
Progress tracking now lives in a separate project. Drop the server,
docs, and module-boundary entries without restoring engineering-dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:40:00 +00:00
weichen 2641045547 merge: feature/control-center-server (supersede engineering-dashboard) 2026-09-19 03:21:12 +00:00
weichenandCursor 55fa8ddfcd docs(test): keep the merge-gate command log
*.log is ignored, so the vet/test/build transcript is stored as verify.txt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:21:05 +00:00
weichenandCursor be0a71cf7f docs(control-center): close the merge gate
Record the unit, live LLM, and SPA walkthrough evidence, and mark the
control-center row done now that engineering-dashboard is superseded.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:20:22 +00:00
weichenandCursor 0929f58aef chore(control-center): bind the database port to loopback
The compose file published 5440 on all interfaces. Match the other
environment databases and listen only on 127.0.0.1.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:20:22 +00:00
weichenandCursor 69524205b0 fix(audit): ignore MiniMax think blocks when parsing findings
Real highspeed responses wrap reasoning in think tags that contain
brackets, which made the JSON span extractor fail before the array.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 03:04:25 +00:00
weichenandCursor 049a18d5bc test(controlcenter): cover config pick, store, and leases
Gate the merge on unit coverage for the three packages that previously
had none: env precedence, migrate/query, and claim/heartbeat/reap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 02:58:03 +00:00
weichenandCursor b3093f1b60 merge: dev into feature/control-center-server
Keep Control Center and drop engineering-dashboard. Resolve CURRENT
claim rows and module-boundaries by removing the superseded dashboard
entry.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 02:55:35 +00:00
weichen 283f39df34 merge: fix/user-manual-dist 2026-09-18 09:53:32 +00:00
weichen 0d94556c4f docs(ops): 记录 dist 补录合入 2026-09-18 09:53:32 +00:00
weichen 65df9d13ed docs(user-manual): 强制纳入 dist 交付物(html/pdf/docx)并补充重建说明 2026-09-18 09:53:17 +00:00
weichen 8142389b4b merge: feature/user-manual slot release 2026-09-18 09:51:32 +00:00
weichen f38e1d5ee6 docs(ops): 释放集成槽位(user-manual 冒烟 PASS) 2026-09-18 09:51:10 +00:00
weichen 6c2fbc45a3 merge: feature/user-manual 2026-09-18 09:49:04 +00:00
weichen f746a59862 docs(ops): 占用集成槽位(feature/user-manual 合入 dev) 2026-09-18 09:48:13 +00:00
weichen f6f34b87cb merge: docs/wave7-roadmap-orchestration 2026-09-18 04:43:32 +00:00
weichenandCursor 60120b7977 docs(test): archive Wave 7 orchestration confirmation report
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:43:19 +00:00
weichenandCursor e64bf5ca8b docs(ops): mark Wave 0-7 done and flag Control Center conflict
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:22:22 +00:00
weichenandCursor a42e7902d7 docs(remediation): mark Wave 7 done and link orchestration record
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:21:56 +00:00
weichenandCursor 7d8029978e docs(ops): record Wave 7 roadmap orchestration confirmations
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:21:37 +00:00
weichen a88ed85cf3 merge: docs/wave6-doc-drift 2026-09-18 04:13:48 +00:00
weichenandCursor 4d7b1b5d25 docs(ops): close Wave 6 doc-drift D-1~D-6 and update SSOT
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:13:29 +00:00
weichenandCursor 28e1fa2e4b docs(project): align remaining-blocker section with gap-matrix production_ready=yes
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:11:15 +00:00
weichenandCursor 6b70d28b2e docs(backlog): sync D3/D7 status with FEATURE-MATRIX
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:11:15 +00:00
weichenandCursor 447b830ff5 docs(ops): backfill closure note on intent dual-tab handoff
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:11:15 +00:00
weichenandCursor 8e17814cea docs(adr): accept modular-monolith-decoupling ADR (Phase 1/2 landed)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:11:15 +00:00
weichenandCursor eee392d93d docs(ops): archive completed PU8/W4 U9-U12 short-term tasks
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:10:53 +00:00
weichenandCursor ca0d334d57 docs(ops): flip PU8 U9-U12 contracts to status done
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:10:48 +00:00
weichen 688d9d30eb docs(user-manual): 新增系统使用说明书(33 张 dev 真实截图 + md/html/pdf/docx 四格式) 2026-09-18 04:08:49 +00:00
weichen 2ce2625c94 merge: fix/wave5-deadcode-decisions 2026-09-18 04:02:26 +00:00
weichenandCursor 60b17c03ab docs(ops): close Wave5 deadcode decisions
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:19 +00:00
weichenandCursor 2e14b3563c fix(web): remove dead notification/workflow/settings components and orphaned APIs (X-5)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichenandCursor da62c49952 docs(sysadmin): annotate unwired system_settings keys as phase-2 backlog (X-4)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichenandCursor 527e6daa99 docs(swboot): mark 00048 tables deferred to SWBOOT-10 (X-3)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichenandCursor 6c61a5bc37 docs(ctxmgr): seal SEMANTIC_SUMMARY_REPLACE with decision link (X-2)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichenandCursor a41836dec0 fix(intent,sysadmin): delete dead SEMANTIC_FALLBACK_ENABLED flag (X-1)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichenandCursor e0f6d5991c docs(ops): plan Wave5 deadcode decisions (X-1~X-5)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 04:02:18 +00:00
weichen a12c94700f merge: fix/wave4-hardening-r1-r8 (slot release) 2026-09-18 03:47:59 +00:00
weichenandCursor e30ae4b96b docs(ops): 释放 Wave4 集成槽位为 idle
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:47:59 +00:00
weichen c4db565c40 merge: fix/wave4-hardening-r1-r8
Wave 4 隐患加固 R-1~R-8 合入本地 dev。
2026-09-18 03:47:46 +00:00
weichenandCursor e4c53a4ccd docs(ops): Wave4 R-1~R-8 收口
归档 test-report 与 assets;CURRENT/remediation 标 Wave 4 done;勾选跨用户会话挂靠负例。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:47:46 +00:00
weichenandCursor e8d2d86542 test(docrevision): hydrate 负例写入类型错误 JSONB 并先落 blob
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:46:22 +00:00
weichenandCursor c1ea8f156c fix(server): 清除 NewSession ProjectID=1 占位以免误触发项目鉴权
非项目会话创建时 ProjectID 归零,避免跨用户负例在 PG 上被 ERR_FORBIDDEN 误挡。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:46:21 +00:00
weichenandCursor 4473a2ae10 test(web): 补 401 fail-fast、单帧容错、abortAllSessions 单测
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor be9b855783 fix(web): 登出主动 abort 所有会话在途流(R-8)
新增 abortAllSessions;logout 先中止全会话再清 session。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor 21049607f4 fix(web): SSE 重连 401/404 fail-fast,单帧解析容错(R-7)
TaskRunHttpError 携带 status;非法 JSON 帧跳过并保留 seq。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor ce7d1b8ac5 fix(server): 后台 ticker 纳入 Shutdown;vault Drain 告警;bizdev 心跳超时(R-6)
reminder/vault 可停止;Drain 失败 slog.Warn;心跳/释放 lease 使用 10s 超时。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor 58b69a2b08 fix(docrevision): pg_store JSONB 反序列化失败显式报错(R-5)
hydrateDocLocked 损坏字段不再静默零值化;补 PG 负例测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor e25a197410 fix(ctxmgr): memTurns 改为实例作用域并加 TTL/容量淘汰(R-4)
消除跨 ContextManager 实例共享;超过容量时淘汰 2h 陈旧回合。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor 207e26241c fix(events): dispatcher Handlers 读路径加 RWMutex(R-3)
Register 写锁不变;shadowScan/handle 读路径 RLock,消除导出字段无锁读隐患。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:44:08 +00:00
weichenandCursor 9038c65329 fix: 补齐 rows.Err() 检查(R-2,其余包)
覆盖 kb/storage/projectworkflow/docgov/freedoc 与两个 document CLI。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:40:24 +00:00
weichenandCursor b53a97b36d fix(ctxmgr): 补齐 rows.Err() 检查(R-2,ctxmgr 包)
A 类硬失败返回;manager 降级读路径用 slog.Warn 保持既有容忍语义。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:40:24 +00:00
weichenandCursor ba1fc71f16 test(server): 跨用户会话挂靠负例测试(PG + 内存双实现)
覆盖 chat / chat/stream / chat/sessions 三条路径;受害者续用不受影响。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:39:08 +00:00
weichenandCursor a805a6bfd7 fix(server): chat/sessions upsert 与任务创建强制取 principal(R-1b)
upsert 忽略客户端自报 user_id;EnsureChatSessionOwned 拒绝跨用户挂靠。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:39:08 +00:00
weichenandCursor ecdf1fc833 fix(server): getOrCreateSession 增加会话归属校验(R-1a)
调用方传入 callerUserID;持久层与内存会话归属不匹配时返回 SESSION_FORBIDDEN;覆盖 NewSession 默认 UserID=1 占位。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:39:08 +00:00
weichenandCursor 426af51365 fix(ctxmgr): EnsureChatSession 归属 COALESCE 改为已有值优先(R-1c)
防止跨用户通过 upsert/消息落库覆盖已绑定的 chat_sessions.user_id;新增 EnsureChatSessionOwned。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:39:08 +00:00
weichen 32932e468e merge: fix/wave3-test-debt-blindspots 2026-09-18 03:02:59 +00:00
weichenandCursor 2ebf6adb2d docs(ops): close Wave 3 test-debt-blindspots (S-1/S-2/S-4/S-5)
Archive isolated PG reconcile evidence, mark gap-matrix debt closed, and
release the integration slot for Wave 4 hardening.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:02:59 +00:00
weichenandCursor 17f430b267 fix(web): reuse projectSettingsError envelope across API clients
Prefer error_code when present and route projectMembers/freeformDoc/
taskRuns/chatSessions failures through the shared structured parser.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:02:06 +00:00
weichenandCursor 3b4c9cfddf test(web): add npm scripts for all e2e specs; retire redundant revision smoke
Eliminate DOCREV_E2E_BASE_URL dual gating by deleting the one-assert smoke
spec covered by document-revision-runtime UI-10, and expose per-spec scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:02:06 +00:00
weichenandCursor a99e3f725f test(server,app): delete dead resume-workspace test; clarify plan_owner redirect
Remove the skipped client work_dir resume coverage that targeted a deleted
entry point, and document why the real-PI stop-gate stays redirected to
internal/server to avoid an import cycle.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 03:02:06 +00:00
weichenandCursor c6e7656f8e docs(ops): sync Wave 2 closeout checklist into dev lineage
Carry the done checklist and test-report link that lagged the Wave 2
merge tip so Wave 3 starts from a consistent ops state.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:59:03 +00:00
weichen 423f7e7413 merge: fix/wave2-config-flag-align 2026-09-18 02:29:07 +00:00
weichenandCursor 24c0e5b16a docs(ops): close Wave 2 config flag alignment (E-3/E-4/E-6/E-7/E-9)
Archive three-env compose/env smoke evidence, mark remediation Wave 2
done, and release the integration slot for Wave 3.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:29:07 +00:00
weichenandCursor 8d97dd6b18 test(config): add compose flag declaration regression tests
Pin E-3/E-4/E-6 compose declarations so dead runner config and missing
flag wiring cannot silently regress.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:26:47 +00:00
weichenandCursor 55a539c551 chore(infra): drop CURSOR_RUNNER_PORT from env examples
Placeholder cursor-agent service is gone; keep CURSOR_API_KEY/MODEL/BIN
for the local cursor-cli subprocess backend.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:26:47 +00:00
weichenandCursor e0aabecf59 fix(infra): declare MULTI_INTENT_PLAN_TIER and U9-U12 flags in all compose envs
Also declare SEMANTIC_SUMMARY_SHADOW and PI_CHANGE_REPORT_NARRATIVE on
test/main, remove dead CURSOR_RUNNER_URL/cursor-agent, and set main
SEED_DEMO_USERS=false. Defaults stay legacy/false (no behavior change).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:26:47 +00:00
weichenandCursor 07fc0ecf55 fix(intent): fail closed INTENT_V2_DECISION_TIER unknown values to none
Align illegal-tier fallback with PlanTier's conservative policy so
unrecognized values never silently enable V2 query routing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 02:26:47 +00:00
weichen e35f106162 merge: Wave 1 docs closeout 2026-09-17 17:08:12 +00:00
weichenandCursor c61963633e docs(test): archive Wave 1 main env fix acceptance evidence
Close short-term task, mark remediation Wave 1 done, release integration
slot, and record main env=main / schema 52 / modes-off smoke evidence.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:08:12 +00:00
weichen 805aa1259f merge: Wave 1 events secrets unblock 2026-09-17 17:06:24 +00:00
weichenandCursor fb4a4f263d fix(infra): supply main events secrets so ENV=main can boot
validateProductionSecrets rejected events under ENV=main without
KB/admin passwords; depends_on events healthy then blocked app forever.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:06:24 +00:00
weichen 27ccd12116 merge: fix/wave1-main-env-fix
Wave 1: align main app/events ENV=main, app depends_on events healthy,
fail-closed empty-Env chat import.
2026-09-17 17:03:54 +00:00
weichenandCursor 053bfe234b docs(ops): occupy integration slot for Wave 1 main env merge
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:03:54 +00:00
weichenandCursor e286fca71b fix(server): fail-closed chat import when Env is empty
Drop Env==\"\" as a dev alias; pin compose app/events ENV alignment and
main depends_on events with unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:03:08 +00:00
weichenandCursor db964da21a fix(infra): align main app ENV with events and gate on events health
Set app ENV=main (was prod) and require events service_healthy before
app starts so goose migrations finish before app queries new columns.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:03:08 +00:00
weichenandCursor 5ad2585ed7 docs(ops): claim Wave 1 main env fix branch
Register short-term task and CURRENT mutex=infra for E-1/E-2/E-5.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 17:03:08 +00:00
weichen af0912b0b3 merge: Wave 0 SSE evidence asset 2026-09-17 16:49:48 +00:00
weichenandCursor 7aca97e9b3 docs(test): store Wave 0 SSE evidence as txt (log gitignored)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 16:49:48 +00:00
weichen 4bccedb4ad merge: docs Wave 0 P0 closeout 2026-09-17 16:49:32 +00:00
weichenandCursor 40a9c1b285 docs(test): archive Wave 0 P0 bug-fix acceptance evidence
Close short-term task, mark remediation Wave 0 done, release integration
slot, and attach real pi-agent SSE heartbeat log plus suite results.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 16:49:32 +00:00
weichen 810fb96e76 merge: fix/wave0-p0-sse-chat-cache-bugs
Wave 0 P0: SSE heartbeat/deadline, run/stream 400+pre-flush start,
chat window cache key/LRU, IndexedDB restore merge.
2026-09-17 16:43:01 +00:00
weichenandCursor 2620d808c4 fix(web): unify chat window cache keys and merge IndexedDB restore
Pass userId on every saveSessionWindowCache write, LRU-evict full cache
keys, and applyRestoredFileRaw so mount restore cannot drop newer deliverables.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 16:42:56 +00:00
weichenandCursor 54244ed97a fix(server): extend SSE write deadline for chat and run/stream
Wire heartbeat + SetWriteDeadline into handleChatStream and
handleRunTaskStream; reject malformed run/stream JSON with 400; move
CreateAndStart/Subscribe before SSE Flush so failures stay JSON errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 16:42:56 +00:00
weichenandCursor 64efaa32c8 docs(ops): register system health audit and claim Wave 0 fix branch
Archive the 2026-09-17 health-check audit/remediation and short-term Wave 0
task so P0 SSE/cache fixes can proceed under mutex chat+web.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 16:42:55 +00:00
weichen dfa2d2d4bd merge: chore/release-s1c-integration-slot
CI / go-vet-and-short-test (push) Failing after 0s
CI / backup-restore-drill (push) Failing after 0s
CI / web (push) Failing after 0s
2026-09-17 15:52:53 +00:00
weichenandCursor 1dd1a8d23f docs(ops): release integration slot after S1-continued smoke
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 15:52:53 +00:00
weichen e58c707df6 merge: feature/rdev-template-depth-s1-continued
S1 continued: deepen remaining 46 rdev templates, lint 60/60, real-PI samples, instance_no fix.
2026-09-17 15:51:41 +00:00
weichenandCursor 36261e9d13 docs(ops): claim merge slot and archive S1-continued short-term
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 15:51:30 +00:00
weichenandCursor 9b35c1abd1 docs(test): archive S1-continued rdev template depth report and sync matrix
Record real-PI samples for review and verification templates, mark S1 continued done across writing-spec/backlog/FEATURE-MATRIX/CURRENT.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 15:51:09 +00:00
weichenandCursor 12608c21ef fix(projectinstance): allocate next instance_no for planning drafts
Avoid unique (project_id, instance_no) collisions when saving a new
workflow plan after a completed main instance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:56:50 +00:00
weichenandCursor 04243e64d8 feat(rdev-templates): deepen stage-10–13 transfer/validation templates (S1 batch 5)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:37:19 +00:00
weichenandCursor 7c50128bd1 feat(rdev-templates): deepen stage-08 verification templates (S1 batch 4)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:37:18 +00:00
weichenandCursor 05629721f0 feat(rdev-templates): deepen stage-06 software/inspection/list templates (S1 batch 3)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:37:18 +00:00
weichenandCursor 1692a57175 feat(rdev-templates): deepen stage-06 hardware/process templates (S1 batch 2)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:37:18 +00:00
weichenandCursor 8c37ac0cd5 feat(rdev-templates): deepen 6 review-record templates (S1 batch 1)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:37:03 +00:00
weichenandCursor 535eb442b5 docs(ops): add short-term for rdev-template-depth-s1-continued
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:34:45 +00:00
weichenandCursor b800f9adf9 docs(ops): claim rdev-template-depth-s1-continued and open short-term
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:34:34 +00:00
weichen f8c4a61922 merge: chore/archive-proposal-http-task
CI / go-vet-and-short-test (push) Failing after 0s
CI / backup-restore-drill (push) Failing after 0s
CI / web (push) Failing after 0s
2026-09-17 14:12:13 +00:00
weichenandCursor 51d6d53ede docs(ops): archive proposal-http short-term after closeout
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:12:13 +00:00
weichen 21fb95458a merge: chore/closeout-claim-cleanup
CI / go-vet-and-short-test (push) Failing after 1s
CI / backup-restore-drill (push) Failing after 0s
CI / web (push) Failing after 0s
2026-09-17 14:12:02 +00:00
weichenandCursor fc227f339c docs(ops): clear closed feature worktree claims after closeout
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:12:02 +00:00
weichenandCursor dcc859ecb0 docs(test): archive proposal HTTP live evidence and release slot
CI / go-vet-and-short-test (push) Failing after 0s
CI / backup-restore-drill (push) Failing after 0s
CI / web (push) Failing after 0s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:11:23 +00:00
weichen 1f2fcd0727 merge: feature/docgov-modification-proposal-http 2026-09-17 14:08:06 +00:00
weichenandCursor c89a58e026 docs(ops): occupy integration slot for proposal-http merge
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:08:02 +00:00
weichenandCursor d01694b556 docs(ops): record author-only pilot and proposal-http task claim
Archive CAS evidence for workflow.allow_author_only_approval on dev,
mark proposal HTTP audit resolved, and claim the feature branch in CURRENT.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:07:52 +00:00
weichenandCursor c0e7df5abf feat(docgov): expose proposal HTTP and wire frontend decide flow
Add POST /api/v1/docgov/proposal for ProposeModification, harden decide
status mapping, and replace App pendingProposal local mock with real API calls.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:07:52 +00:00
weichen bea70b064b docs(control-center): strengthen agent integration spec — onboarding protocol, per-stage entry/exit criteria, decision quality bar, event cadence 2026-09-17 14:06:24 +00:00
weichen b5bacee331 refactor(control-center): remove legacy engineering-dashboard, superseded by control-center
- delete cmd/engineering-dashboard, internal/engineeringdashboard, scripts/engineering-dashboard.sh
- archive old design doc to .doc/archive/design/ with deprecation banner
- FEATURE-MATRIX: mark old row removed, add removed to status contract
- system-design README: section 8 now points to Control Center SSOT
2026-09-17 14:00:38 +00:00
weichenandCursor ba92a8b3a5 docs(status): note author-only merged to dev in FEATURE-MATRIX
CI / go-vet-and-short-test (push) Failing after 0s
CI / backup-restore-drill (push) Failing after 0s
CI / web (push) Failing after 0s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:58:30 +00:00
weichenandCursor cbeefdb9ed docs(ops): release integration slot after author-only merge smoke
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:58:19 +00:00
weichenandCursor 09a9921e87 merge: feature/document-author-only-plan
Close out document author_only U1–U6 into dev (default policy off).
Resolved CURRENT claim table and bizdev service conflicts with rdev prior-doc injection.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:57:12 +00:00
weichenandCursor 4f1bb1f02d docs(ops): archive author-only U1–U6 and close remediation DoD
Move short-term tasks to archive, update MATRIX/INDEX/CURRENT, and hand off merge to dev.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:55:17 +00:00
weichenandCursor 472f845a88 docs(test): track U6 API evidence as txt (logs gitignored)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:49:12 +00:00
weichenandCursor 7b09da1f99 docs(ops): close document-author-only U6 and note proposal HTTP gap
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor 58b785e110 docs(test): add document-author-only U6 closed-loop report
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor cf7f55a1b9 test(web): cover author_only action visibility and docgov client shapes
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor 916931f5d8 feat(web): surface duty_policy author_only badge end-to-end
Propagate summary.duty_policy into deliverables/AST and show 编制人兼任 on the action bar.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor b87fc5007f feat(web): call real docgov lifecycle APIs from action handlers
Replace local lifecycleState mocks; add handleRejectApprove; use holdsDocDuty for chat shortcuts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor aed7f3f9b5 fix(web): gate docgov actions by duty id, not folded role
author_only A/A/A users were stuck as author-only under resolveCurrentDocRole priority.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor 3c6342bfee feat(web): add docgov claim/submit/review/approve API client
Wire frontend to existing lifecycle HTTP so approval actions can leave local mock state.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:48:59 +00:00
weichenandCursor 8658a135ab docs(ops): claim and close document-author-only U4 and U5
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor 7ccb821d6c test(web): cover author_only duty resolution and validation
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor 72686d13cb feat(web): add per-document author_only toggle in project settings
Show a single author picker when兼任 is enabled, respect the system
capability flag, and surface author_only docs in activation preview.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor be128602e4 feat(web): resolve client duty_policy for author_only plans
Align TypeScript types and projectSettingsDuties with backend
ResolveDocTaskDuty so author_only no longer fails as partial.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor 2c012ee59f test: cover author_only access matrix and duty_policy audits
Prove A can run the full action chain and outsiders stay denied; assert
audit Details carry duty_policy on all five transitions.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor 3f7358d454 feat(docgov): record duty_policy on lifecycle audit details
Surface the document duty mode on submit/review/approve transitions for
consistent logs under author_only.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichenandCursor f02600d75c fix(projectinstance): resolve author_only duties in ABAC gates
Use ResolveDocTaskDuty so normalized author-only plans (author ID only)
are treated as full A/A/A for access, stage visibility, and readiness.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:15:05 +00:00
weichen 87bcf05043 feat(control-center): allow LAN bind with mandatory fixed console token (serve-lan) 2026-09-17 13:11:52 +00:00
weichen 6714081b12 docs(control-center): P6 design spec, agent integration guide, acceptance report
Also fixes ListTasks ?q= filter 500 (duplicate $%d placeholder rendered as
%!d(MISSING)) found in P6 smoke; adds TestTaskListQueryFilter regression.
2026-09-17 12:59:12 +00:00
weichen 07a8e126fc feat(control-center): P5 scheduled repo audits — deterministic checks, LLM review, findings UI 2026-09-17 12:39:46 +00:00
weichen f79956c498 feat(control-center): P4 .doc importer, agent CLI, task doc export
- internal/controlcenter/importer: scan .doc/ops/{short-term,long-term}
  and .doc/backlog for task docs, upsert cc_tasks keyed by slug; maps doc
  status/stage, auto-creates the three plans, follows doc status only
  while a task is planned/in_progress (terminal statuses never regress),
  skips unchanged docs, and resolves cross-directory slug collisions by
  fixed directory precedence with a warning
- cmd/control-center: import-docs subcommand (also runs at serve startup
  and on the doc-sync ticker) plus the agent CLI: next / instruction /
  claim / heartbeat / release / event / artifact / advance-request /
  decision / report, thin net/http client, compact JSON output
- console API POST /api/v1/tasks/{id}/export-doc renders a task per
  .doc/ops/templates/short-term-task.md into .doc/ops/short-term/, refuses
  overwrite (409) and unsafe slugs, then backfills doc_path
- fix pre-existing TestAgentHasNoAdvanceRoute: SPA catch-all GET / makes
  the mux answer 405 for unmatched POST paths; accept 404 or 405
- archtest allowlist: controlcenter/importer -> pipeline, store
2026-09-17 11:57:47 +00:00
weichen b0095de398 feat(control-center): P3 web SPA — overview, stage kanban, task pipeline, decisions, docs search
- control-center/web: Vite+React+TS SPA (hash routing, token login via
  localStorage, marked-lexer markdown rendering without raw HTML injection)
- pages: overview (stage x state matrix, SSE feed w/ 10s poll fallback),
  8-lane kanban + task create, task detail stepper/pipeline/ops
  (assign/advance/send-back/external-submit), decision inbox, docs browse
  + semantic/keyword/hybrid search, global stage settings, audit placeholder
- internal/controlcenter/webui: //go:embed dist, SPA fallback, index no-store;
  dist committed so go build works without node
- server: GET / serves embedded SPA; pipeline view now includes artifact
  content for console rendering
- archtest: allowlist controlcenter/server -> controlcenter/webui
2026-09-17 10:13:16 +00:00
weichenandCursor c6c07263c7 docs(ops): claim and close document-author-only U3
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 67b3b5e070 test: cover duty lock, heal/revoke skip, and instance duty adapter
Unit evidence for AE5a/AE5b filters; optional PG cases when
TEST_DATABASE_URL is set.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 750b904439 feat(app): wire projectinstance duties into bizdev
Composition-root adapter maps live instance DocTasks to bizdev's narrow
InstanceDutySource without crossing module boundaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 5b9b46ee8d feat(bizdev): prefer instance-governed duties when generating docs
Inject InstanceDutySource, resolve governed bindings, lock duties after
create, and skip in-memory HealBinding overwrite for governed docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 42a3b1e56c feat(docduty): skip duty_locked rows in heal and revoke
Keep instance-governed A/A/A (or separated) bindings immune to project
default heal and member-slot revocation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 89484177ee feat(docgov): lock document duties and project duty_policy
Add LockDocumentDuty for PG/memory and expose duty_policy on workflow
document summaries for later UI marking.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 7d3474816b feat(db): add document_records duty_locked and duty_policy columns
Stamp instance-governed document duties at create time so heal/revoke can
skip locked rows without importing projectinstance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:59:38 +00:00
weichenandCursor 748df016b2 docs(ops): release rdev merge slot, archive P0/P1 task, register S1续批
Also record the ad-hoc verification Path("") join pitfall as a low-severity
audit note so future sampling scripts fail closed instead of scanning bizdev/.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:52:24 +00:00
weichenandCursor 7e6860f861 docs(ops): smoke phase for rdev merge
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:47:57 +00:00
weichen 68f63d3c30 merge: feature/rdev-template-depth 2026-09-17 09:47:49 +00:00
weichen 9bb4ec3665 merge: feature/rdev-core 2026-09-17 09:47:44 +00:00
weichen 63f1fa5f87 feat(control-center): P2 document vector store — ingestion, chunking, embedding, hybrid search
- internal/controlcenter/embed: OpenAI-compatible /embeddings client
  (batch<=16, 30s timeout, 5xx/network retried once, 4xx not), Embedder
  interface, deterministic offline Stub, pgvector literal formatting
- internal/controlcenter/docs: .doc/**/*.md sync into cc_documents with
  sha256 diffing and vanished-file removal; YAML front matter -> jsonb,
  title fallback, taxonomy from first .doc dir; heading-based chunking
  with paragraph bisection over ~1800 est. tokens; chunk_hash idempotent
  inserts (unchanged chunks keep embeddings); embedding failures degrade
  to NULL vectors without failing the sync; IndexArtifact for
  cc_stage_artifacts; StartPeriodic ticker (CC_DOC_SYNC_SECONDS)
- server: GET /api/v1/docs (taxonomy/q filters), /api/v1/docs/{id},
  /api/v1/docs/search (semantic|keyword|hybrid, ts_rank+ILIKE keyword
  fallback, 0.6/0.4 max-normalized fusion, degraded flag when embedding
  unavailable); async artifact indexing hooked into agent artifacts and
  external-submit handlers
- archtest module-boundaries allowlist updated for new packages
2026-09-17 09:47:29 +00:00
weichenandCursor 7f30a5049e docs(ops): occupy slot to merge rdev-core and template-depth
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:47:14 +00:00
weichenandCursor 4e271c54bb docs(test): archive rdev template-depth S0/S1 real-PI evidence
Record true PI samples (intake + rd_design_input_spec), update FEATURE-MATRIX
remaining work, backlog S1续批/S2/S3, and allowlist engineeringdashboard for
archtest green on this branch lineage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:47:05 +00:00
weichenandCursor ca7b7da237 docs(ops): claim rdev-template-depth short-term and CURRENT mutex
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:52 +00:00
weichenandCursor 93ad80b9a7 feat(rdev): deepen phase 01-05 templates with ISO 13485 sections
Replace generic placeholders for 14 rd_* docs, add writing-norm doc and
allowlist lint so structure and per-section instructions stay enforceable.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:37 +00:00
weichenandCursor dc3aef4607 fix(squad): inject rdev_leader InstructionsFile for DHF final review
Prefer AgentSpec.InstructionsFile when building AGENTS.md so rd_* leader
steps no longer fall back to business-tone leader.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:37 +00:00
weichenandCursor aba38ef7a9 fix(engineering-dashboard): drop startup token for personal local use
Rely on loopback bind plus Host/Origin checks; open http://127.0.0.1:8787/
without a query token after SSH tunnel.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:26 +00:00
weichenandCursor 37b1aaa3ae feat(rdev): add medical design-control workflow (13 stages / 60 docs)
Seed rdev.v2.json, rd_ templates, catalog policy (order 40), squad
kind orchestration, and hard precheck requiring completed main (CDO).
Includes StageKey dynamicization from P0 and docs for P2–P4 skeleton.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:26 +00:00
weichenandCursor a39823da38 fix(docgov): pass dynamic StageKey into document ledger create
Stop hardcoding V0.5_feasibility when creating docgov records; prefer
frozen-instance StageKey from TaskRunRequest with main-task fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:09 +00:00
weichenandCursor c03d0a3a6e docs(ops): claim and close document-author-only U2
Record short-term evidence and mark the CURRENT claim done.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor 68dbe8a6b2 test(projectinstance): cover author_only planning and activation
Verify resolve/normalize/hash stability, policy gating, stale token
rejection, and HTTP error mapping for the new duty policy path.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor 1651c30e90 feat(api): map author-only policy errors on workflow settings
Return 403/409/503 for disabled, changed, and unavailable governance
policy conditions during plan save and activation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor 0b67a901a9 feat(app): wire sysadmin author-only policy into projectinstance
Adapt sysadmin.AuthorOnlyPolicySource at the composition root so
projectinstance stays within module-boundary allowlists.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor a2aa3d41bd feat(projectinstance): support per-doc author_only duty policy
Add ResolveDocTaskDuty, require the system policy on save/preview,
lock the policy row during activation, and derive A/A/A assignments.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor ba57c9a4de feat(db): bind activation tokens to author-only policy revision
Prevent preview tokens from activating after the governance switch
revision changes by storing the revision on each confirmation token.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:39:59 +00:00
weichenandCursor 3b6def256e docs(ops): claim and close document-author-only U1
Record short-term task evidence and mark the CURRENT claim done.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:15:15 +00:00
weichenandCursor 430a47ad8c test(sysadmin): cover author-only CAS, audit rollback, and HTTP gates
Verify concurrent revision conflicts, null/string rejection, plain-user
denials, and PG lock/read paths for the new policy key.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:15:15 +00:00
weichenandCursor a2cbaf1e33 feat(sysadmin): CAS author-only policy with transactional audit
Register the workflow total switch, require expected_revision for
updates, and expose AuthorOnlyPolicySource for activation locking.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:15:15 +00:00
weichenandCursor b4b300bb8a feat(db): add author-only approval policy revision and audit
Seed workflow.allow_author_only_approval closed, add monotonic
revision on system_settings, and a narrow policy audit table.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:15:15 +00:00
weichen b11cc64845 feat(control-center): P1 pipeline core — stage machine, decisions, artifacts, leases, SSE
- pipeline: 8-stage order, NextStage (testing skippable), gate pure
  functions (agents may never advance; only in_progress->awaiting_review)
- tasks: domain layer over cc_* tables — CRUD, claim/heartbeat/release
  leases, advance-request, decisions with strict suggestion validation,
  stage transitions, external submit, stage settings, overview, lease reaping
- server: agent + console routes, SSE broker broadcasting every event
  insert, 60s lease reaper goroutine, 1MB body limit, domain error mapping
- archtest: allowlist controlcenter/* and engineeringdashboard packages
2026-09-17 09:13:36 +00:00
weichenandCursor 7a590670e9 docs(workflow): approve R9/R10 and harden heal acceptance
Mark lifecycle boundaries reviewed; require HealProjectDocuments
projection stability across list/generate/member triggers, and
explicitly exclude emergency stop from the global switch scope.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:06:51 +00:00
weichen f6c9638e60 docs(workflow): plan per-document author-only approval policy 2026-09-17 08:49:46 +00:00
weichen 2be43efddd feat(control-center): P0 skeleton — standalone server, pgvector compose, goose schema, token auth 2026-09-17 08:38:50 +00:00
weichen cf805a73a7 docs(ops): claim control-center-server task and register in CURRENT 2026-09-17 08:33:10 +00:00
weichen adb48c86a5 merge: feature/initial-load-perf-u2 (docs acceptance) 2026-09-17 08:25:43 +00:00
weichenandCursor ae219955ab docs(test): archive initial-load U2 acceptance evidence
Record curl/browser before-after metrics, mark U2 done, and release the
integration slot while leaving U1/U3–U7 open.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 08:25:43 +00:00
weichen bc01781438 merge: feature/initial-load-perf-u2 2026-09-17 08:18:18 +00:00
weichenandCursor 9335c4c90c feat(server): negotiate static compression and fix asset SPA fallback
Serve precompressed .br/.gz with Cache-Control and Vary, and return 404
for missing /assets and /fonts instead of index.html.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 08:18:11 +00:00
weichenandCursor 3dbd9770b5 feat(web): precompress dist assets to .br and .gz at build time
Use Node zlib in a post-vite step so the Go server can serve negotiated
variants without per-request compression cost.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 08:18:02 +00:00
weichenandCursor dc769686a9 feat(web): self-host Inter and JetBrains Mono for login shell
Remove blocking Google Fonts stylesheet so the login form is not gated
on an external CSS request; keep unicode-range subsets and OFL license.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 08:18:02 +00:00
weichen 59e6fade72 merge: feature/initial-load-performance-plan 2026-09-17 08:08:23 +00:00
weichenandCursor 3445d386ea docs(perf): archive initial-load diagnosis and remediation plan
Capture audit evidence, performance baseline, and U1–U7 remediation plan
without business code changes so the work can land on dev before U2.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 08:08:20 +00:00
weichenandCursor d0ef6961b4 docs(ops): release slot after engineering-dashboard CSP fix
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:40:28 +00:00
weichen 0a1302eab0 merge: fix/engineering-dashboard-csp-token 2026-09-17 07:40:27 +00:00
weichenandCursor 2319138800 docs(ops): occupy slot to merge engineering-dashboard CSP fix
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:40:27 +00:00
weichenandCursor 7fd7fb8a2a fix(engineering-dashboard): read token from URL/meta under CSP
Remove the inline token script blocked by script-src 'self', so the
live page no longer calls the snapshot API with token=undefined.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:39:21 +00:00
weichenandCursor ce2a561d4d docs(ops): release slot after engineering-dashboard merge
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:11:18 +00:00
weichenandCursor f47161131c merge: feature/engineering-dashboard
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:11:17 +00:00
weichenandCursor fd1659a416 docs(ops): occupy slot to merge engineering-dashboard
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:10:36 +00:00
weichenandCursor 7e05473cf5 docs(engineering-dashboard): closeout report matrix and launcher
Add test report, FEATURE-MATRIX row, archive the short-term task,
mark CURRENT claim done, and ship the thin serve/export script.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:10:04 +00:00
weichenandCursor e251ce325a feat(engineering-dashboard): U6-U7 serve UI and offline export
Add loopback-only HTTP server with startup token, Host/Origin/CSP
guards, embedded live UI, CLI serve/export, and safe single-file HTML.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:08:27 +00:00
weichen dd887bb08f merge: feature/system-admin-console closeout docs 2026-09-17 07:08:07 +00:00
weichen 62d6241348 docs(test): system admin console acceptance report and closeout
- test report: dev smoke (schema 48->49), 4 admin endpoints, settings
  write-read roundtrip, anon 401 / unknown-key 400 / non-admin 403
- task status done; FEATURE-MATRIX row done; release integration slot;
  env snapshot dev schema 49
2026-09-17 07:08:07 +00:00
weichenandCursor 79ee72267c feat(engineering-dashboard): U5 reconcile and snapshot publisher
Merge docs/git/runtime facts into an immutable snapshot with conflict
retention, last-known stale handling, and acceptance-sample coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:04:46 +00:00
weichenandCursor a07ba1065b feat(engineering-dashboard): U2-U4 docs git and runtime collectors
Add allowlisted markdown indexing, read-only git plumbing via injected
runners, and docker/readiness collection with path and loopback guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:03:32 +00:00
weichen dc7c31edc9 merge: feature/system-admin-console 2026-09-17 06:59:21 +00:00
weichen 0088ae7d44 docs(ops): occupy integration slot for system-admin-console merge 2026-09-17 06:59:21 +00:00
weichenandCursor e46ec0e4e7 feat(engineering-dashboard): U1 freeze snapshot and facet model
Define versioned Snapshot/Fact/Conflict/TaskState contracts with
independent plan/git/verification/deployment axes and acceptance fixtures.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:59:02 +00:00
weichen e7fa6fb023 docs(status): add system admin console row to FEATURE-MATRIX 2026-09-17 06:58:08 +00:00
weichen e310f06504 docs(ops): register system-admin-console task and claim 2026-09-17 06:57:13 +00:00
weichen 0eaca61545 feat(web): full-screen system admin console, absorb AdminSettingsModal
- top-level view switch workbench|admin in App.tsx (no router; hash #turn
  anchors untouched)
- new admin/console/AdminConsoleView with left group nav in the existing
  token/inline-style idiom, plus 8 self-fetching sections: overview, kb,
  features, settings, workflows, roles, users, docs
- absorb the six AdminSettingsModal tabs into sections and delete the modal
- new api/systemAdmin.ts + types for /api/v1/admin/system/* endpoints
- playwright smoke spec web/e2e/admin-console.spec.ts (skip by default)
2026-09-17 06:57:03 +00:00
weichen f1404d5bd2 feat(sysadmin): add system admin aggregation API and system_settings store
- new internal/sysadmin package (overview/kb/features/settings) with small
  port interfaces; business packages stay unaware of sysadmin
- new routes /api/v1/admin/system/{overview,kb,features,settings} guarded
  by requireSystemAdmin
- goose 00049: system_settings table (key/jsonb value, updated_by/at)
- SettingSpec whitelist registry with DB > env > default precedence
- register sysadmin in module-boundaries.yaml (archtest rules)
2026-09-17 06:56:46 +00:00
weichenandCursor fa5e10542a docs(ops): claim engineering-dashboard implementation
Register CURRENT mutex and mark short-term in_progress on the
feature/engineering-dashboard worktree before coding.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:56:20 +00:00
weichenandCursor 12884a1710 docs(ops): release slot after engineering-dashboard plan merge
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:55:44 +00:00
weichen c336de59b8 merge: feature/project-control-center-plan 2026-09-17 06:55:44 +00:00
weichenandCursor 44fa8d5059 docs(ops): occupy slot to merge engineering-dashboard plan
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:55:44 +00:00
weichenandCursor ed4a49bfa6 docs(engineering-dashboard): add personal control center design plan
Freeze the independent local readonly engineering-dashboard design,
short-term task entry, and system-design index before implementation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:55:32 +00:00
weichen 15881cd0e6 docs: sync null-fk promote closeout onto test 2026-09-17 06:20:40 +00:00
weichen 173a512c28 merge: docs/promote-null-fk-to-test-closeout 2026-09-17 06:20:40 +00:00
weichenandCursor ef5f0fdef9 docs(ops): close null-fk promote to test at rc-v1.0.0-beta.4
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 06:20:40 +00:00
732 changed files with 56307 additions and 7010 deletions
@@ -2,7 +2,7 @@
## 状态
提议(2026-09-14;架构与实施计划已修订,等待用户确认后进入首个实现里程碑)
已接受(2026-09-14 提议;2026-09-18 确认——Phase 1 纵向绞杀与 Phase 2 持久事件交付已落地并验收,见 gap-matrix `DOC-RELIABILITY-PILOT` PASS、[Phase 1 计划](../remediation/2026-09-14-module-decoupling-refactor-plan.md)、[Phase 2 修订计划](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md)、[Track E 复盘](../ops/research/2026-09-15-track-e-retrospective.md))
## 背景
@@ -0,0 +1,609 @@
---
title: "个人工程中控台:实时项目看板与离线 HTML 快照"
type: feat
date: 2026-09-17
artifact_contract: ce-unified-plan/v1
product_contract_source: ce-plan-bootstrap
execution: code
---
> **已废弃(2026-09-17;2026-09-19 更新)**:旧版只读工程中控台代码已移除。后来短暂合入的 Control Center 也已移出本仓库,进度管理由独立项目承担。本文仅作历史证据保留。
# 个人工程中控台:实时项目看板与离线 HTML 快照
## Goal Capsule
为仓库所有者提供一个独立于产品后台的本地只读中控台。打开一个页面即可判断当前系统由什么组成、哪些任务正在计划或实施、真实分支和 worktree 在哪里、各环境实际运行了什么,并能在两次点击内到达对应的设计、审计、整改、任务和测试材料。
中控台同时提供两种输出:
1. `serve`:持续采集本地仓库、Git 和运行环境,提供自动刷新的 HTML 页面与机器可读 JSON;
2. `export`:基于同一份不可变快照生成单文件 HTML,便于归档、离线查看和交接。
这不是产品功能,不接入产品后台、产品数据库或产品权限体系;它也不是发布系统,不执行 Git、Docker、部署或文档写操作。
### 成功标准
- 在当前仓库规模下,首次可用页面目标为 2 秒内出现;慢数据源可随后标记为 `degraded`,不得拖垮整页。
- 正常情况下,本地文件、Git 或运行态变化在 5 秒内反映到新快照。
- 页面分别展示“文档声明、Git 实施、验证证据、环境实装”,不把任务文档的 `done` 翻译为已合并或已部署。
- 每个关键结论均显示来源、采集时间、新鲜度和可信类型;冲突保留双方证据,不静默选边。
- 在线模式检索 allowlist 内未截断的 Markdown 正文;离线导出同时给出 included、truncated 和 metadata-only 清单,二进制附件只索引路径、类型、大小和归属。
- 单文件 HTML 默认权限为 `0600`,可脱离仓库阅读已纳入 inclusion manifest 的 Markdown 正文,并醒目标出截断或仅元数据条目;不打包 `.doc/**/assets`。
- 任一采集源失败时仍可查看最近成功数据,并明确显示 `stale/error/last_success_at`。
---
## Product Contract
### 用户与使用场景
唯一主要用户是仓库所有者。典型使用包括:
- 每天开始工作时查看焦点任务、阻塞、集成槽和环境异常;
- 从模块进入设计、任务、测试和部署证据链;
- 判断某项工作究竟只是有计划、正在实现、已经验证,还是已在某环境实装;
- 查看本地分支、远端跟踪引用、ahead/behind、worktree 和未提交变更;
- 发现 `CURRENT`、功能矩阵、发布门禁、Git 与 Docker 之间的漂移;
- 导出一个自包含 HTML,作为某一时点的项目快照。
### 已确定的产品决策
#### PKD-1:独立本地工具
采用独立 Go CLI 和本地 Web 页面,不加入现有产品后台。
(session-settled: user-approved — chosen over product-admin integration: the console is for the repository owner’s local engineering management and the production image excludes `.doc` and `.git`)
#### PKD-2:只读实时页与离线快照共用数据模型
实时服务和导出文件必须由同一份版本化快照生成,避免在线页面与离线报告出现两套口径。
(session-settled: user-approved — chosen over a static-only report: the requested console must follow agent tasks and project state as they change)
### 核心需求
| ID | 需求 |
|---|---|
| R1 | CLI 默认解析当前 Git 仓库根,也接受显式 `--repo`;页面始终显示绝对根路径、当前分支、HEAD 和采集时间。 |
| R2 | 仅监听 `127.0.0.1`,不依赖产品容器、产品数据库或产品登录。 |
| R3 | 架构与模块页聚合 `module-boundaries.yaml`、系统设计索引和 `FEATURE-MATRIX`,展示模块、能力、依赖和证据链。 |
| R4 | 任务状态至少拆为 `doc_status`、Git facets、`verification_result`/`verification_freshness`、deployment facets;可并存事实不得压成单值枚举。 |
| R5 | Git 页展示本地/跟踪分支、ahead/behind、最近提交、worktree、dirty/untracked 和任务声明匹配情况;不得隐式 `fetch`。 |
| R6 | 部署页按 shared/dev/test/main 分别展示容器状态、应用 readiness、服务完整性、schema、镜像与 promotion receipt;不得计算未经定义的综合绿灯。 |
| R7 | 文档页支持按 taxonomy、状态、模块和关键词筛选,展示正文、正向链接、反向链接、broken、orphan 与 unindexed 状态;查询状态可通过 URL 恢复。 |
| R8 | 一个不可变快照包含 `schema_version`、`generation_id`、`revision_id`、`generated_at`、仓库/提交身份、来源状态、事实与冲突。 |
| R9 | 自动刷新采用完整快照原子切换;每个来源独立超时,失败时保留最近成功数据并标注过期。 |
| R10 | 每条关键事实标注 `declared`、`observed`、`verified` 或 `inferred`,并保留来源路径和采集时间。 |
| R11 | 单 HTML 内嵌结构化模型、页面资源和允许导出的 Markdown 正文;附件只保留元数据及相对链接,并显示内容覆盖清单。 |
| R12 | 对 Agent 暴露稳定的只读 JSON,而不是让 Agent 解析 HTML;JSON 与页面引用同一 `generation_id` 和 `revision_id`。 |
| R13 | TaskState 显示声明的 owner/Agent 类型/认领/mutex 与基于 Git 的最近活动证据;Herdr 工程 Agent 和产品 PI Agent Runner 使用不同类型。没有运行态来源时必须显示 unknown,不得把“已认领”写成“正在执行”。 |
| R14 | 文件、命令和 HTTP 均采用 allowlist;拒绝路径穿越、symlink 越界、原始 HTML 执行、远程资源加载和凭证读取。 |
### 事实源与权威边界
| 领域 | 权威来源 | 中控台处理方式 |
|---|---|---|
| 发布门禁 | `.doc/remediation/gap-matrix.md` | 只解释发布 blocker,不替代能力完成度。 |
| 能力成熟度 | `.doc/status/FEATURE-MATRIX.md` | 显示功能完成度,不据此推断是否部署。 |
| 当前焦点、认领、集成槽 | `.doc/ops/CURRENT.md` | 作为团队声明,与 Git 和运行态对账。 |
| 任务计划 | `ops/short-term`、`ops/long-term`、backlog front matter | 作为计划状态,不据此推断实现。 |
| 分支与 worktree | Git plumbing | 作为本地观测;远端状态注明“基于本地 refs,未联网刷新”。 |
| 环境运行态 | Docker/Compose 元数据与 `/ready` | 分开展示容器、应用与服务完整性。 |
| 验收证据 | `.doc/test-reports` 及 promotion receipts | 显示证据存在性与身份,不以文件名替代内容校验。 |
来源之间不设全局覆盖顺序。各来源回答自己的问题;值不一致时生成 drift,并并列展示原值、时间和来源。
### 用户流程
```mermaid
flowchart LR
Start[启动 serve 或 export] --> Root[解析显式 repo root]
Root --> Collect[并行采集文档 Git 运行态]
Collect --> Snapshot[构建不可变快照]
Snapshot --> Reconcile[按领域对账]
Reconcile --> Live[本地实时页面和 JSON]
Reconcile --> Export[单文件 HTML]
Live --> Refresh[定时生成下一快照]
Refresh --> Snapshot
```
总览默认优先显示 `in_progress`、`blocked`、`planned`、`partial/deferred`、drift 和 degraded。`done` 与 archive 默认收起,避免历史材料淹没当前工作。
任务详情按照以下证据链导航:
```mermaid
flowchart LR
Audit[audit 问题] --> Remediation[remediation 方案]
Remediation --> Task[任务声明]
Task --> Git[分支 worktree commit merge]
Git --> Test[测试与验收报告]
Test --> Deploy[环境 artifact 与 readiness]
```
显式 Markdown 链接和既定 taxonomy 属于强关系;仅由文件名或 slug 推断的关系标为“候选”,不得参与完成度计算。
### 状态模型
```mermaid
flowchart TB
D[doc_status: planned/in_progress/blocked/done] --> View[并列状态视图]
G[Git facets: branch/worktree/merge/cleanliness/ahead-behind] --> View
V[Verification: result + freshness + bound identity] --> View
P[Deployment facets: container/readiness/services/artifact identity] --> View
View --> Drift{来源是否一致}
Drift -->|是| Consistent[consistent]
Drift -->|否| Conflict[drift + 双方证据]
```
“实装”定义为存在可核对的环境观测证据,而不是任务文档为 `done`。容器可达但 artifact identity 无法核对时显示“运行可见、版本未验证”,不得提升为 verified deployment。当文档声明 healthy、Docker 显示异常而 `/ready` 为 ok 时,页面保留多值并标记 drift,不输出统一绿灯。
### 真实验收样本
1. rdev:存在调研、设计、任务与 backlog,但若没有 CURRENT 认领和真实分支,应显示“已计划、未认领、未实施、未实装”。
2. main 环境:若 CURRENT 声明整体 healthy,而 events 容器实际 restarting、应用 `/ready` 仍为 ok,应同时显示三项证据与 drift。
3. 本地 dev:若分支领先 `origin/dev`,必须显示“本地已具备、远端未确认可用”,不得写成已远程发布。
4. `system-admin-console`:作为产品管理后台能力,与本计划的个人工程中控台分开展示,名称和边界不得混淆。
### 安全与非目标
一期明确不做:
- 不写文档,不修改任务状态,不占用集成槽;
- 不创建、切换、合并、删除或推送 Git 分支;
- 不执行 `git fetch`,不调用远端托管平台 API;
- 不启动、停止、重建或部署容器;
- 不控制 Herdr 或向 Agent 派发任务;
- 不读取 `.env`、`.secrets`、Docker `Config.Env`、数据库数据或 `.git` 内部文件正文;
- 不加入产品 API、产品前端、产品数据库或生产镜像;
- 不执行 Markdown 原始 HTML、脚本、Mermaid 或远程资源。
后续候选包括跨快照历史、远端 CI/Gitea 聚合、受限 Markdown/Mermaid 渲染、Agent 查询 API 和修复建议。任何写操作继续保持在本工具之外。
---
## Planning Contract
### High-Level Technical Design
以下图示冻结边界和协议,不规定具体函数签名。
```mermaid
flowchart LR
Docs[.doc sources] --> DC[Document collector]
Git[Git/worktrees] --> GC[Git collector]
Run[Docker/ready/receipts] --> RC[Runtime collector]
DC --> Build[Snapshot builder]
GC --> Build
RC --> Build
Build --> Rec[Reconcile facts and conflicts]
Rec --> JSON[Read-only JSON]
Rec --> Web[Local HTML]
Rec --> File[Offline HTML]
```
```mermaid
sequenceDiagram
participant UI as Browser
participant C as Collection coordinator
participant S as Sources
participant P as Snapshot publisher
UI->>C: poll with revision_id
C-->>UI: current snapshot immediately
C->>S: singleflight collection with deadlines
S-->>C: facts or source error
C->>P: publish complete generation atomically
P-->>UI: new revision or not-modified
```
```mermaid
stateDiagram-v2
[*] --> Loading
Loading --> Fresh: first collection succeeds
Loading --> ErrorUnknown: first collection fails
Fresh --> Refreshing: TTL expires
Refreshing --> Fresh: new generation succeeds
Refreshing --> Stale: source fails and last-known exists
Stale --> Fresh: source recovers
ErrorUnknown --> Fresh: source first succeeds
```
### 技术决策
#### KTD-1:采用仓库内独立 Go CLI
新增 `cmd/engineering-dashboard` 与 `internal/engineeringdashboard`,复用仓库 Go 工具链但不导入产品业务包。Go 标准库足以提供本地 HTTP、资源嵌入、JSON、并发和原子文件输出;现有 `yaml.v3` 可用于已定义的 YAML 契约。
#### KTD-2:快照是唯一交付模型
采集器只生产事实,reconcile 层只生产派生状态和冲突,HTTP/API/export 只消费已完成的不可变快照。快照至少包含:
```text
schema_version, generation_id, revision_id, generated_at, collection_duration
repository { root, branch, head, dirty }
sources[] { name, status, observed_at, last_success_at, error }
facts[] { subject, field, value, provenance, source_ref, observed_at, confidence }
conflicts[] { subject, field, kind, fact_refs[] }
documents[], modules[], tasks[], git[], environments[]
```
`generation_id` 唯一标识一次采集,包含采集批次语义;`revision_id` 只由 schema、仓库身份和规范化的非易变事实、冲突、来源状态确定,明确排除 `generated_at`、`observed_at` 和采集耗时。HTML 与 JSON 必须展示同一对标识,HTTP ETag 和前端是否重绘使用 `revision_id`。一期不读取旧 schema 的外部 JSON;离线 HTML 自带对应 renderer,因此不依赖未来二进制迁移。
#### KTD-3:专用解析器与容错索引并存
对 CURRENT、FEATURE-MATRIX、gap-matrix、任务 front matter 和 module boundaries 编写契约化解析器。文档层只索引 promotion receipt 的路径与链接,结构化部署凭证由运行态采集器唯一负责。对其余 Markdown 只提取安全元数据、标题、正文与链接。专用解析器失败时保留原文入口并标记 degraded,不凭模糊规则编造状态。
#### KTD-4:命令执行采用固定 argv 和超时
Git 与 Docker 采集通过注入式 command runner 执行固定程序和分离 argv,不通过 shell 拼接。`--repo` 先转为绝对、symlink-resolved 的 Git 根并作为单个参数传递。每个来源默认 2 秒超时;错误输出做长度限制和敏感字段清理。Git 使用 porcelain/plumbing 输出,例如 `status --porcelain=v2`、`worktree list --porcelain`、`for-each-ref`、`rev-list`、`merge-base`。
#### KTD-5:一期采用短轮询,不引入持久数据库
服务端由单一采集协调器按 TTL 触发完整重采集,2–5 秒刷新;同一仓库最多一轮采集在途,请求只读取当前快照,不直接叠加扫描。每轮带单调 generation 序号和整轮 deadline,只有当前有效轮次能原子发布。页面使用 ETag/`revision_id` 避免重复传输。last-known 只在同一 `serve` 进程内有效;冷启动或单次 export 首次采集失败时显示 unknown/error,不伪造历史值。文件监听、SSE 通知、持久缓存和历史数据库均后置。
#### KTD-6:安全阅读优先于富渲染
在线详情页一期将 Markdown 全部作为纯文本安全转义,并保留换行和空白;标题、列表、链接、代码、图片和 Mermaid 均显示源码,不生成 HTML 节点或发起资源请求。静态导出内嵌同一正文和内部导航。所有文档 ID 都是规范化仓库相对路径,只允许 `.doc/**/*.md` 及明确列入 allowlist 的根 Markdown;读取前后都校验解析路径,直接拒绝 symlink,并对 `.git`、`.env*`、`.secrets`、`data` 等敏感路径执行最终目标 denylist。
#### KTD-7:导出为自包含、有限尺寸的证据快照
导出将模型、CSS、JS 和允许的 Markdown 正文写入单 HTML,采用临时文件加 rename 原子落盘,默认 `0600`。数据使用 HTML-safe JSON 或等价编码封装,正文只通过 `textContent`/DOM API 写入;CSP 禁止网络、外部资源和内联事件执行。默认只嵌入 Git tracked、allowlist 内的 Markdown;untracked Markdown 只列元数据,除非用户显式选择。导出前输出 inclusion manifest 与敏感模式告警;`.doc/**/assets`、数据库、构建产物和二进制报告不嵌入。
### 建议目录
```text
cmd/engineering-dashboard/
main.go
internal/engineeringdashboard/
model.go
collector.go
source_docs.go
source_git.go
source_runtime.go
reconcile.go
server.go
export.go
assets/
index.html
app.js
app.css
testdata/
docs/
git/
runtime/
scripts/
engineering-dashboard.sh
.doc/test-reports/
YYYY-MM-DD-engineering-dashboard-test-report.md
```
### 风险与缓解
| 风险 | 缓解 |
|---|---|
| 文档结构并不完全统一 | 只对 SSOT 和任务 front matter 使用严格契约;其余文档容错索引并暴露解析告警。 |
| 看板制造“假完成” | 多轴 facets、事实 provenance、验证身份绑定、冲突不覆盖、真实反例测试。 |
| Docker/Git 卡住或不可用 | 独立超时、并行采集、last-known 状态、degraded 页面。 |
| 文档 XSS 或路径穿越 | 纯文本渲染、HTML-safe 数据封装、CSP、路径 allowlist、拒绝 symlink、最终目标敏感路径 denylist。 |
| `.doc` 附件导致扫描/导出失控 | 默认跳过 assets 内容,只采集元数据;设置单文档和总正文上限并报告截断。 |
| 导出副本离开本机后 `0600` 不再提供保护 | 页面首部标明敏感快照、仓库身份和生成时间;输出 inclusion manifest,交接者自行控制接收者、保留期与删除。 |
| worktree 与主 checkout 混淆 | 只管理 `--repo` 指定/解析出的根,页面常驻显示根与 HEAD;其他 worktree 仅作为 Git 元数据。 |
| 本地 remote refs 被误认为远端实时状态 | 显示 refs 观测时间和“未联网刷新”,不自动 fetch。 |
| 与产品 `system-admin-console` 命名冲突 | CLI、包和文档统一使用 `engineering-dashboard` / “个人工程中控台”。 |
---
## Implementation Units
### U1:冻结快照、事实与状态契约
**目标**:先建立不会把计划、实现、验证、部署混为一谈的模型与测试夹具。
**覆盖需求**:R4、R8、R10、R12、R13;承接 PKD-2 的同源快照决策。
**依赖**:无。
**文件**:
- `internal/engineeringdashboard/model.go`
- `internal/engineeringdashboard/model_test.go`
- `internal/engineeringdashboard/testdata/**`
**实施要点**:
1. 定义版本化 `Snapshot`、`SourceState`、`Fact`、`Conflict`、`TaskState`、`AgentClaim`、`EnvironmentState`。
2. provenance 固定为 `declared|observed|verified|inferred`;freshness 固定为 `fresh|stale|error|unknown`。
3. 状态使用可组合 facets:Git 分为 branch/worktree/merge/cleanliness/ahead-behind;验证分为 result/freshness/subject identity;部署分为 container/readiness/services/artifact identity。
4. TaskState 保留 owner、agent kind、claim、mutex、声明分支、观测 worktree、最近活动时间及证据;声明与观测不可互相提升。
5. 建立 rdev、dev ahead、main events restarting、CURRENT/worktree 不匹配等夹具。
**测试场景**:
- 文档 `done` 但无 merge/deploy 时,Git 与部署 facets 不改变;
- `claimed` 但无可观测运行信号时,Agent 活动保持 unknown;Herdr 与产品 PI Runner 不共享类型;
- 同字段多来源不一致时生成 conflict 并保留所有 fact 引用;
- JSON round-trip 保留 schema 与 snapshot identity;
- 枚举未知值失败且错误可定位。
**完成证据**:模型测试通过,schema 示例落入 Go fixture,不存在页面专用的第二套状态类型。
### U2:实现文档图谱与领域解析器
**目标**:将 `.doc` taxonomy、模块、任务、测试和链接转换为可追溯文档图谱。
**覆盖需求**:R3、R7、R10、R11、R14。
**依赖**:U1。
**文件**:
- `internal/engineeringdashboard/source_docs.go`
- `internal/engineeringdashboard/docs_test.go`
**实施要点**:
1. 扫描 allowlist 内 Markdown,默认跳过任何 `assets` 目录正文;记录附件元数据。
2. 解析 front matter、标题、显式 Markdown 链接和反向链接。
3. 为 CURRENT、FEATURE-MATRIX、gap-matrix、任务文、module boundaries 和 test report 建立专用适配器;receipt 只在文档图谱中作为文档与链接,结构化解析归 U4。
4. 区分 `broken`、`orphan`、`unindexed`;slug 相似只形成候选关系。
5. 规范化路径并阻止 `..`、绝对路径和任何 symlink;最终目标再次应用扩展名 allowlist 与敏感路径 denylist。
**测试场景**:
- taxonomy 内文档可检索且反向链接正确;
- broken link 不导致整个索引失败;
- front matter 缺失或非标准时产生告警并仍可阅读;
- assets 不读正文,越界 symlink 被拒绝;
- rdev 文档链被发现,但没有被推断为已实现。
**完成证据**:文档索引能从 fixture 生成稳定 JSON,路径安全负例通过。
### U3:实现 Git 与 worktree 采集
**目标**:以只读 Git plumbing 形成可复现的分支、提交和 worktree 观测。
**覆盖需求**:R1、R4、R5、R10、R14。
**依赖**:U1。
**文件**:
- `internal/engineeringdashboard/source_git.go`
- `internal/engineeringdashboard/git_test.go`
**实施要点**:
1. 抽象 command runner,固定 argv、工作目录、超时和输出上限。
2. 收集当前分支/HEAD、dirty/untracked、local/remote-tracking refs、ahead/behind、merge-base 和 worktree。
3. 不执行 fetch;remote tracking ref 始终带本地观测时间与免责声明。
4. 对账任务声明的 branch/worktree,但不因路径名相似而认定一致。
**测试场景**:
- 本地分支领先 origin 时显示 ahead 且不显示“远端可用”;
- worktree 目录名与真实检出分支不一致时生成 drift;
- 命令超时、Git 不存在、非 Git 目录时单源 degraded;
- runner 记录中不存在 shell、fetch、push 或写命令。
**完成证据**:临时 Git 仓库集成测试和 fake runner 单元测试通过。
### U4:实现运行态与部署证据采集
**目标**:按环境独立呈现容器、应用 readiness、服务完整性、schema、镜像和晋升凭证。
**覆盖需求**:R4、R6、R10、R14。
**依赖**:U1。
**文件**:
- `internal/engineeringdashboard/source_runtime.go`
- `internal/engineeringdashboard/runtime_test.go`
**实施要点**:
1. 从仓库内批准的 Compose 静态配置和 allowlist labels 映射环境与服务;无法明确映射时显示 unknown,不用名称猜测。容器 JSON 只提取容器名、image/digest、状态、restart count、health,以及 allowlist 内的 Compose project/service labels;不复制 Env、Mounts、完整 NetworkSettings 或任意 labels。
2. 对 allowlist 中的本地 `/ready` 端点执行短超时、响应大小受限的请求;禁用重定向,或对每一跳重新校验 scheme、解析后 IP、端口和 host。
3. 解析 promotion receipt/candidate image 等仓库证据,保留 artifact identity。
4. 将 container health、app readiness、required-service completeness 分开建模。
**测试场景**:
- app ready 且 events restarting 时同时保留两项状态;
- Docker 不可用或 HTTP 超时时,其他数据源仍可输出;
- receipt 与容器 image 不一致时生成 deployment drift;容器可达但 identity 缺失时标记“运行可见、版本未验证”;
- readiness 重定向到外网或非 allowlist 本地端口时拒绝访问;
- 输出中不存在容器环境变量或凭证。
**完成证据**:fixture 和 fake HTTP/Docker runner 测试通过,main 分叉场景被覆盖。
### U5:实现对账、派生视图与新鲜度
**目标**:把来源事实组合成用户可判断的视图,但不替来源做未经定义的裁决。
**覆盖需求**:R3、R4、R6、R8、R9、R10、R13。
**依赖**:U2、U3、U4。
**文件**:
- `internal/engineeringdashboard/reconcile.go`
- `internal/engineeringdashboard/reconcile_test.go`
**实施要点**:
1. 按领域 SSOT 规则构建 module、task、environment 和 evidence-chain 视图。
2. 实现 conflict 分类:declared-vs-observed、task-vs-git、test-vs-subject、receipt-vs-runtime、stale-source、missing-evidence。
3. 快照构建期间每个来源独立记录 `observed_at`、持续时间和错误;成功后一次性发布。
4. 失败源只可复用同一 serve 进程的 last-known,并标注 stale、age 与 last-success;冷启动无缓存时为 unknown/error。过期数据不隐藏,但按年龄提升告警级别。
5. 测试报告只有在 commit/artifact identity 与当前 subject 对齐时才能派生 pass;身份缺失为 unbound,身份不匹配为 stale/drift。
**测试场景**:
- 三个真实样本得到预期多轴状态;
- 同一组输入顺序变化不改变规范化快照;
- 单源失败不会删除其他源,也不会重写 last-known 的观测时间;冷启动失败没有伪造 last-known;
- 旧测试报告、新 HEAD 与不同 image 不会派生当前验证通过;
- 恢复后 stale 自动清除并产生新 snapshot ID。
**完成证据**:reconcile table tests 覆盖一致、漂移、缺失、过期和恢复。
### U6:实现本地服务、总览与文档导航
**目标**:提供能快速判断异常并下钻证据的本地只读页面和 JSON。
**覆盖需求**:R1、R2、R3、R7–R10、R12–R14;承接 PKD-1 和 PKD-2。
**依赖**:U5。
**文件**:
- `internal/engineeringdashboard/server.go`
- `internal/engineeringdashboard/server_test.go`
- `internal/engineeringdashboard/assets/index.html`
- `internal/engineeringdashboard/assets/app.js`
- `internal/engineeringdashboard/assets/app.css`
- `cmd/engineering-dashboard/main.go`
**实施要点**:
1. `serve --repo <path> --addr 127.0.0.1:<port>`;一期无条件拒绝所有非 loopback 地址,包括通配、IPv6 非 loopback 和显式传入值。
2. 暴露 `/api/v1/snapshot`、`/api/v1/doc/<id>`、`/healthz`;所有接口只读。严格校验 Host/Origin/Fetch Metadata,不信任代理转发头;页面和 API 使用每次启动生成的不可预测访问令牌,降低 DNS rebinding 与跨站读取风险。
3. 页面分为总览、架构/模块、任务、Git、部署、文档和证据链。
4. 自动刷新完整快照,保留当前筛选、滚动位置、焦点和选中文档;ETag 未变化时不重绘。
5. 明确一级视图状态:initial loading、fresh empty、fresh success、partial/degraded with last-known、hard error without cache、refreshing、recovered。刷新中继续展示上一完整快照,直到下一版本原子替换。
6. 搜索覆盖标题、仓库相对路径、front matter 和未截断正文;不同维度用 AND、同一维度多选用 OR,默认先排当前任务和异常证据,再按匹配度与路径稳定排序。筛选、查询和选中文档写入 URL 参数,支持浏览器前进/后退与深链。
7. 桌面优先;窄屏下侧栏变为可关闭抽屉,宽表格保留可横向滚动的语义表头,详情区单列。所有功能可键盘完成,使用 landmark/标题/表格语义,drift/degraded 不只靠颜色表达,自动刷新通过非打断式 live region 报告且不抢焦点。
8. Markdown 正文只进入文本节点;在线页与导出页均设置限制性 CSP,不执行 HTML、脚本、SVG、远程 URL 或事件属性。
**测试场景**:
- 只监听 loopback,方法 allowlist 拒绝写请求;Host/Origin/token、DNS rebinding 和跨 Origin 负例被拒绝;
- HTML 与 JSON 的 generation/revision identity 一致;
- 文档 ID 越界、symlink 越界、未知 ID 返回安全错误;
- degraded source 在总览可见且页面仍可导航;
- 任务状态四轴、drift 和来源时间在浏览器中可见。
- 首次加载、空数据、无缓存错误、刷新、恢复状态可区分;键盘、焦点、语义结构、窄屏和非颜色告警验收通过。
- 搜索组合逻辑、排序、无结果、URL 深链和刷新后的视图保持通过。
**完成证据**:HTTP tests、基本无障碍检查和真实浏览器验收通过。
### U7:实现离线导出、启动脚本与治理文档
**目标**:生成安全、可携带、可追踪的单文件快照,并完成仓库治理接线。
**覆盖需求**:R1、R8、R9、R11、R14;承接 PKD-1 和 PKD-2。
**依赖**:U6。
**文件**:
- `internal/engineeringdashboard/export.go`
- `internal/engineeringdashboard/export_test.go`
- `scripts/engineering-dashboard.sh`
- `.doc/status/FEATURE-MATRIX.md`
- `.doc/ops/CURRENT.md`
- `.doc/test-reports/YYYY-MM-DD-engineering-dashboard-test-report.md`
**实施要点**:
1. `export --repo <path> --output <file>` 构建一次不可变快照并原子写入;首次采集失败的来源显示 unknown/error。
2. 以 HTML-safe JSON/等价编码内嵌允许的 Markdown 正文、索引和页面资源;附件保持元数据与相对链接,所有正文只写入文本节点。
3. 默认权限 `0600`,输出页显示生成时间、repo、HEAD、snapshot ID 和 degraded/drift。
4. 薄脚本只负责定位仓库与调用 Go CLI,不隐藏参数或执行安装/部署副作用。
5. 实施期间按仓库规范更新 CURRENT、FEATURE-MATRIX 和 test report;完成后再迁移任务生命周期状态。
**测试场景**:
- 导出文件脱离仓库后仍能搜索和阅读 Markdown;
- 导出中不含附件字节、绝对凭证路径、env 值或远程请求;`</script>`、事件属性、SVG、危险 URL scheme 和 Unicode 边界载荷不能逃逸数据上下文;
- 默认 tracked/untracked 与敏感模式策略、inclusion manifest 和覆盖清单符合契约;
- 采集部分失败时仍能导出并保留错误;
- 输出中 JSON/HTML snapshot identity 一致,权限符合预期;
- 大文档和总正文上限触发时明确标记截断。
**完成证据**:export tests、离线浏览器验收和治理文档回链完整。
---
## Verification Contract
### 自动验证
实施阶段至少运行:
```bash
go test ./internal/engineeringdashboard/...
go test ./cmd/engineering-dashboard/...
go vet ./...
go test -short ./...
git diff --check
```
涉及共享容器的只读验收也必须遵守 CURRENT 集成槽规则;中控台本身不得为测试启动、停止或重建共享容器。
### 契约验证矩阵
| 领域 | 必须证明 |
|---|---|
| 模型 | 计划、Git facets、验证、部署 facets 互不覆盖;Agent 声明和运行观测分离;所有派生结论可追溯到 facts。 |
| 文档 | taxonomy、全文检索、反链、broken/unindexed、路径安全与 assets 排除。 |
| Git | ahead/behind、worktree、dirty、local refs 新鲜度和无隐式 fetch。 |
| 部署 | container/app/service 三类信号分离,receipt/artifact 身份可核对。 |
| 降级 | 每个源超时、错误、stale、恢复都不会让整页不可用。 |
| 实时 | 变化在目标时间内形成完整新快照,不出现半新半旧卡片。 |
| 导出 | 单文件离线可读、默认 `0600`、不嵌 assets、不产生网络请求。 |
| 安全 | loopback、Host/Origin/startup token、read-only methods、命令 allowlist、路径边界、Docker 字段 allowlist、CSP 与输出脱敏。 |
### 浏览器验收
1. 从总览进入 rdev,确认“计划/实施/验证/实装”四轴与源文档链接均可见。
2. 在仓库外复制导出 HTML,断网打开并全文搜索、阅读至少一份设计与一份测试报告。
3. 制造 fixture 中的 CURRENT/Docker/readiness 冲突,确认页面保留多值且不出现综合绿灯。
4. 切换 fixture 快照,确认页面刷新后筛选条件和当前文档保持不变。
5. 尝试路径穿越、未知文档、POST、DNS rebinding、跨 Origin、readiness 重定向和含原始 HTML/脚本逃逸载荷的 Markdown,确认均不能越界、外联或执行。
### 性能与容量验证
- 记录当前 `.doc` 规模下的冷启动、增量刷新、JSON 大小和 HTML 导出大小。
- 建议一期门槛:UI shell 与来源状态在 2 秒内可交互,P95 完整快照重建不超过 5 秒,单源超时不超过 2 秒;基线不达标时必须记录实测并拆分后台正文索引,不能伪造 PASS。
- 导出达到配置上限时必须显式列出被截断文档,不允许静默丢失。
---
## Definition of Done
- [ ] `serve` 和 `export` 在显式仓库根下可重复运行,且没有产品后台依赖。
- [ ] 实时 HTML、离线 HTML 与 JSON 使用同一版本化快照契约。
- [ ] `generation_id` 标识采集实例,`revision_id` 标识内容版本并驱动 ETag;无内容变化不会触发重绘。
- [ ] 架构、模块、功能、任务、Git、部署、文档和证据链均可从页面访问。
- [ ] 计划、实施、验证、实装四轴独立,rdev、dev ahead、main events 分叉样本通过。
- [ ] Agent 认领与可观测活动分开,Herdr 工程 Agent 与产品 PI Agent Runner 不混称。
- [ ] 所有 drift、degraded、stale 都带来源和时间,不存在未经定义的综合绿灯。
- [ ] 默认 loopback、Host/Origin/startup token、只读命令、路径边界、脱敏、CSP 和 Markdown 安全测试通过。
- [ ] 首次加载、空数据、部分失败、无缓存失败、恢复、键盘、窄屏和 URL 深链验收通过。
- [ ] 导出 HTML 脱离仓库可读 Markdown,且不包含二进制 assets 或凭证数据。
- [ ] 单元、集成、全仓短测、浏览器验收和 `git diff --check` 均有真实输出。
- [ ] `.doc/test-reports` 报告回链任务文,FEATURE-MATRIX 与 CURRENT 按实际状态更新。
- [ ] 没有遗留调试入口、写操作按钮、未使用的替代模型或与产品后台重名的组件。
---
## Appendix
### 一期交付边界
一期交付:本地只读服务、版本化快照 JSON、架构/任务/Git/部署/文档视图、四轴状态、drift/degraded、全文搜索、安全文档阅读和单 HTML 导出。
后续评估:跨快照历史趋势、远端托管/CI 聚合、受限富文本与 Mermaid、跨仓库聚合、面向 Agent 的筛选查询 API。
永久排除:在页面中修改文档、切换或推送分支、控制 Agent、执行部署、读取密钥、成为产品后台模块。
### 方案依据
- `.doc/README.md` 定义的文档 taxonomy 与生命周期;
- `.doc/ops/CURRENT.md` 的焦点、认领、集成槽与环境声明;
- `.doc/status/FEATURE-MATRIX.md` 的模块完成度口径;
- `.doc/remediation/gap-matrix.md` 的发布门禁口径;
- `.doc/system-design/README.md` 与模块边界清单;
- Git/worktree、Docker/Compose、`/ready` 和 promotion receipts 的当前可观测能力。
@@ -0,0 +1,48 @@
---
title: "docgov 变更提案 HTTP + 前端接线"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/docgov-modification-proposal-http
worktree: .worktrees/feature-docgov-modification-proposal-http
mutex: docgov
---
# docgov 变更提案 HTTP + 前端接线
## 目标
暴露 `POST /api/v1/docgov/proposal`,前端「修改」快捷分支与 `ProposalConfirmCard` 走真实 propose/decide,不再本地假装成功。
## 范围
- API:`ProposeModification` 路由;decide 补 404/403 映射
- 前端:`docgov.ts` + `App.tsx` 接线
- 单测 + 真实 HTTP 证据
- 关闭 audit 缺口;dev 试点总开关证据归档
## 非目标
- 晋升 test/main
- 变更提案自动改写受控正文(批准后仍为 UI 演示增补)
## 步骤
1. [x] 实现 propose handler + 路由
2. [x] 前端 client + App 接线
3. [x] handler/client 单测
4. [x] 合入 dev + rebuild + 真实 HTTP
5. [x] push origin/dev;清理 author-only worktree
## 验收标准
- [x] `POST /api/v1/docgov/proposal` 可写库(单测)
- [x] 真实 HTTP claim → propose → decide PASS
- [x] audit 缺口 resolved;CURRENT 认领收敛
## 相关链接
- Audit: [../../audit/2026-09-17-docgov-modification-proposal-http-gap.md](../../audit/2026-09-17-docgov-modification-proposal-http-gap.md)
- Pilot: [../../test-reports/assets/2026-09-17-author-only-pilot/](../../test-reports/assets/2026-09-17-author-only-pilot/)
- Closeout: [../handoffs/2026-09-17-document-author-only-closeout.md](../handoffs/2026-09-17-document-author-only-closeout.md)
@@ -0,0 +1,47 @@
---
title: 文档编制人兼任审核批准方案
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Codex
branch: feature/document-author-only-plan
worktree: .worktrees/feature-document-author-only-plan
mutex: document-duty-policy-plan
---
# 文档编制人兼任审核批准方案
## 目标
基于当前源码形成管理员总授权、项目创建者逐文档选择的详细实施方案,交用户审核。
## 范围
权限、系统设置、工作流规划和冻结、文档三职、动作鉴权、状态机、前端、迁移与验收。
## 非目标
本次不修改业务代码、不变更数据库或共享容器、不推送。
## 步骤
1. [x] 阅读启动链并从本地 dev 建立隔离分支。
2. [x] 核查实现并记录证据。
3. [x] 编写方案、检查边界与验收覆盖。
## 验收标准
- [x] 方案覆盖用户两个权限层级及逐文档持久化。
- [x] 当前事实与拟议行为分开,列明实施单元与测试场景。
## 证据 / 备注
基线 dev adb48c8。已 fetch origin/dev,本地 dev 领先 44、落后 0,保留未推送集成成果;主工作区 feature/control-center-server 未切换。worktree 脚本默认从当前 HEAD 创建,故直接指定 dev 创建本 worktree,避免引入他人分支。
## 交付
- 方案:`.doc/remediation/2026-09-17-document-author-only-plan.md`
- 核查:`.doc/audit/2026-09-17-document-author-only-analysis.md`
- 本任务完成仅指方案交付,业务实现为 planned;R9/R10 待用户审核。
- 未合入 dev:方案保留在独立分支供审核;未推送、未修改业务代码或容器。
- 验证:源码与文档一致性检查、git diff --check;未执行业务测试。
@@ -0,0 +1,57 @@
---
title: "文档编制人兼任:U1 策略存储与总授权"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: sysadmin + document-duty-policy
---
# 文档编制人兼任:U1 策略存储与总授权
## 目标
落地 `workflow.allow_author_only_approval` 管理员总开关:默认关闭、严格 bool、revision CAS、事务内审计,并向 projectinstance 提供可参与激活事务的窄读取接口。
## 范围
- Goose 增量迁移(revision 列、种子行、策略审计表)
- `internal/sysadmin` 存储/服务/窄 Policy 接口
- `admin_system_handlers` 对本 key 的 `expected_revision` 协议
- 单元 / PG / HTTP 负例测试
## 非目标
- 逐文档 duty_policy(U2)
- 前端设置页文案(U5)
- 已激活实例紧急熔断
## 步骤
1. [x] 认领 CURRENT
2. [x] 迁移 00050
3. [x] sysadmin CAS + 审计 + PolicySource
4. [x] admin handler
5. [x] 测试与提交
## 验收标准
- [x] 管理员可开关;非管理员 403
- [x] null/字符串布尔拒绝
- [x] 并发 CAS 仅一版成功
- [x] 审计失败回滚设置
- [x] 窄接口可读 allowed+revision;缺行默认 false;DB 故障不伪装
## 相关链接
- Plan: `.doc/remediation/2026-09-17-document-author-only-plan.md` U1
- Checklist:
## 证据 / 备注
- `go test ./internal/sysadmin/ ./internal/server/ -run 'Settings|AuthorOnly|PGSettings|AdminSystem'` PASS
- `go test -short ./internal/sysadmin/ ./internal/server/` PASS
- Key: `workflow.allow_author_only_approval`
- 窄接口: `sysadmin.AuthorOnlyPolicySource`
@@ -0,0 +1,54 @@
---
title: "文档编制人兼任:U2 逐文档模式与激活"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: projectinstance + document-duty-policy
---
# 文档编制人兼任:U2 逐文档模式与激活
## 目标
落地逐文档 `duty_policy=author_only`:规划校验、预览摘要、激活 token 绑定策略 revision,激活事务内行锁串行化关闭总开关。
## 范围
- DocTaskPlan / PreviewSummary / ProjectSettings 扩展
- ResolveDocTaskDuty、Save/Preview/Activate 消费 U1 策略
- Goose 00051 token revision 列
- app 适配器装配、HTTP 错误码映射
- 单元测试
## 非目标
- Heal/文档投影(U3)
- 前端 UI(U5)
- 运行时动作多职责(U4/U6)
## 步骤
1. [x] 类型与解析器
2. [x] service/store/迁移
3. [x] app 装配与 handler
4. [x] 测试与提交
## 验收标准
- [x] 一位成员兼任可存/预览/激活(总开关开)
- [x] 总开关关时 Save 拒绝
- [x] 预览后 revision 变化旧 token 409
- [x] 未开模式只填作者仍 partial 拒绝
- [x] 旧快照缺 duty_policy 时 hash 稳定
## 相关链接
- Plan: `.doc/remediation/2026-09-17-document-author-only-plan.md` U2
## 证据 / 备注
- `go vet ./internal/projectinstance/ ./internal/app/ ./internal/server/`
- `go test -short ./internal/projectinstance/ ./internal/server/ ./internal/app/` PASS
@@ -0,0 +1,55 @@
---
title: "文档编制人兼任:U3 文档绑定与职责投影"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: docgov + docduty + bizdev + document-duty-policy
---
# 文档编制人兼任:U3 文档绑定与职责投影
## 目标
生成时写入实例治理职责并 `duty_locked`;heal/revoke 跳过锁定行;读侧投影 `duty_policy`。
## 范围
- Goose 00052:`document_records.duty_locked` / `duty_policy`
- `docgov.LockDocumentDuty` + 列表投影
- `docduty` heal/revoke `AND NOT duty_locked`
- `bizdev.InstanceDutySource` + `resolveTaskDocumentDuties` 治理分支;跳过 governed 内存 heal
- `app/instance_duty_adapter.go` 装配
## 非目标
- U4 动作鉴权 / allowed_actions
- U5/U6 前端
- 合入 `dev`
## 步骤
1. [x] 迁移
2. [x] docgov / docduty
3. [x] bizdev + app 适配器
4. [x] 测试与提交
## 验收标准
- [x] 受治理文档创建后 `duty_locked=true` 且三职来自实例
- [x] heal/revoke 不清锁定行(SQL 过滤 + 单测/PG 可选)
- [x] 生成后 governed 路径不再用项目默认覆盖内存态
- [x] 模块边界:bizdev/docduty/docgov 不导入 projectinstance
## 相关链接
- Plan: U3(文档绑定与职责投影一致性)
- 依赖:U1 `3b6def2`、U2 `c03d0a3`
## 证据 / 备注
- `go vet ./internal/docgov/ ./internal/docduty/ ./internal/bizdev/ ./internal/app/ ./internal/projectinstance/`
- `go test -short` 上述包 PASS
- PG:`TEST_DATABASE_URL` 未配置时 `Heal/Revoke SkipsDutyLocked` 自动跳过
@@ -0,0 +1,47 @@
---
title: "文档编制人兼任:U4 动作鉴权与审计"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: projectinstance + docgov + document-duty-policy
---
# 文档编制人兼任:U4 动作鉴权与审计
## 目标
ABAC 门禁识别 `duty_policy=author_only` 派生职责;审计 Details 携带 duty_policy。
## 范围
- `duty_action` / `stage_access` / `gate` 改用 `ResolveDocTaskDuty`
- `state_machine` Transition* Details 补 `duty_policy`
- author_only 动作矩阵与阶段可见性测试
## 非目标
- U5 UI / U6 浏览器闭环
## 步骤
1. [x] ABAC 三文件
2. [x] 审计详情
3. [x] 测试与提交
## 验收标准
- [x] author_only 规范存储(仅 Author ID)下 A 可 run/edit/submit/review/approve
- [x] 非 A 拒绝;阶段门禁将 author_only 视为 approvalManaged
- [x] 审计 Details 含 duty_policy
## 相关链接
- Plan: U4+U5 实施计划
- 依赖:U1–U3
## 证据 / 备注
- `go test -short ./internal/projectinstance/ ./internal/docgov/ ./internal/app/ ./internal/server/` PASS
@@ -0,0 +1,48 @@
---
title: "文档编制人兼任:U5 系统设置与逐文档 UI"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: web + document-duty-policy
---
# 文档编制人兼任:U5 系统设置与逐文档 UI
## 目标
前端识别 `duty_policy` / `author_only_policy`;项目设置可逐文档开启兼任。
## 范围
- `projectSettings.ts` 类型
- `projectSettingsDuties.ts` resolveClientDocTaskDuty + 校验
- `ProjectSettingsModal` 兼任勾选与预览
- SettingsSection 不改(白名单通用渲染)
## 非目标
- U6 多职责动作栏 / 浏览器 E2E
## 步骤
1. [x] 类型与 lib
2. [x] UI
3. [x] 测试与提交
## 验收标准
- [x] author_only 客户端校验通过且不计三人门槛
- [x] 总开关关闭时兼任勾选禁用并提示
- [x] 预览展示兼任文档计数
## 相关链接
- Plan: U4+U5 实施计划
## 证据 / 备注
- `npx tsc --noEmit` PASS
- `npm test` PASS(含 projectSettingsDuties author_only 用例)
@@ -0,0 +1,55 @@
---
title: "文档编制人兼任:U6 多职责动作与真实闭环"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/document-author-only-plan
worktree: ".worktrees/feature-document-author-only-plan"
mutex: web + document-duty-policy
---
# 文档编制人兼任:U6 多职责动作与真实闭环
## 目标
去掉 author-first 动作短路,把认领/送审/审核/批准接到真实 docgov HTTP,完成 author_only 端到端验收。
## 范围
- `web/src/api/docgov.ts` 四接口客户端
- `docGovActionVisibility` / `holdsDocDuty`
- `App.tsx` 真实 handler + 快捷指令
- `duty_policy` 透传与「编制人兼任」徽标
- 单测 + 真实闭环报告
## 非目标
- 变更提案 HTTP 路由(另记 audit)
- 合入 `dev` / 推送远端(未授权不推)
## 步骤
1. [x] API 客户端
2. [x] ID 直判可见性
3. [x] App 接线 + 驳回批准修正
4. [x] duty_policy 徽标透传
5. [x] 单测 / tsc
6. [x] 真实闭环与报告
## 验收标准
- [x] author_only 下 A 可见三动作;非 A 403
- [x] 真实 API 闭环写库与审计含 duty_policy
- [x] 浏览器可见「编制人兼任」徽标
- [x] 测试报告归档
## 相关链接
- Test report: [../../test-reports/2026-09-17-document-author-only-u6-test-report.md](../../test-reports/2026-09-17-document-author-only-u6-test-report.md)
- Remediation U6: [../../remediation/2026-09-17-document-author-only-plan.md](../../remediation/2026-09-17-document-author-only-plan.md)
## 证据 / 备注
- `npm test` 390 pass;`tsc --noEmit` clean
- assets: `test-reports/assets/2026-09-17-document-author-only-u6/`
@@ -0,0 +1,41 @@
---
title: "首次加载性能诊断与改进方案"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Codex
branch: feature/initial-load-performance-plan
worktree: .worktrees/feature-initial-load-performance-plan
mutex: loading-performance-audit
---
# 首次加载性能诊断与改进方案
## 目标
以源码、现有容器静态资源和只读浏览器测量定位首次加载瓶颈,输出可审核的分期改进方案。
## 范围
登录前首屏、登录后初始化、项目/文档首次打开、静态资源交付;区分事实与待验证假设。
## 非目标
不修改业务代码,不重启/重建共享服务,不触发真实对话或文档写任务,不提交或推送其他人的工作。
## 步骤
1. [x] 阅读仓库启动链;独立 dev 基线 worktree,主仓保留其他 Agent 分支。
2. [x] 采集数值基线和源码证据。
3. [x] 写 audit 和 remediation,同步 CURRENT,归档任务。
## 验收标准
- [x] 原因有文件位置或运行时测量支持,未覆盖环境明确标注。
- [x] 方案包含优先级、改动边界、性能预算、回归门禁和回滚。
## 证据 / 备注
仅诊断与方案,不代表优化已实施。fetch 后 origin/dev 落后本地 dev;不拉回或覆盖本地工作。worktree 从创建瞬间的 dev 建立。
## 交付
- 诊断:`.doc/audit/2026-09-17-initial-load-performance-audit.md`
- 方案:`.doc/remediation/2026-09-17-initial-load-performance-plan.md`
- 报告:`.doc/test-reports/2026-09-17-initial-load-performance-baseline.md`
- 本轮仅方案;没有业务代码、没有部署、未提交、未合dev、未推送。主仓仅同步本任务认领。
- 临时3199 Vite已停止;既有3100/8080/8081未重启。未占集成槽。
@@ -0,0 +1,57 @@
---
title: "rdev 模板深度补强 S1 续批(剩余 46 份)"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/rdev-template-depth-s1-continued
worktree: ".worktrees/feature-rdev-template-depth-s1-continued"
mutex: rdev-templates
---
# rdev 模板深度补强 S1 续批(剩余 46 份)
## 目标
将剩余 46 份 `rd_*` 模板按写作规范做同等深度补强,lint allowlist 扩至全 60 份,抽样真 PI 打样收口。
## 范围
- 批1:6 份评审记录
- 批2:阶段06 硬件/工艺 8 份
- 批3:阶段06 软件/检验/技术要求+清单 9 份
- 批4:阶段08 验证 12 份
- 批5:阶段10–13 转换/确认 11 份
- lint allowlist + 抽样真 PI + 文档同步
## 非目标
- S2/S3、P2 前端、P3 三样本全量 E2E、P4 键名空间化
- 晋升 test/main
## 步骤
1. [x] 批1 评审记录 6 份
2. [x] 批2 硬件/工艺 8 份
3. [x] 批3 软件/检验/清单 9 份
4. [x] 批4 验证 12 份
5. [x] 批5 转换/确认 11 份
6. [x] 抽样真 PI + 文档同步(合入 push 见 merge 步骤)
## 验收标准
- [x] 46 份无「按本阶段专业结构写」;lint allowlist 60/60
- [x] 抽样 1–2 份真 PI PASS(`rd_planning_review` + `rd_design_vv`,项目 6446)
- [x] FEATURE-MATRIX / 写作规范 / backlog 已更新
## 相关链接
- Backlog: [.doc/backlog/2026-09-17-rdev-phase2-backlog.md](../../backlog/2026-09-17-rdev-phase2-backlog.md)
- 写作规范: [.doc/system-design/project-workflow/08-rdev模板写作规范.md](../../system-design/project-workflow/08-rdev模板写作规范.md)
- 首批报告: [.doc/test-reports/2026-09-17-rdev-template-depth-test-report.md](../../test-reports/2026-09-17-rdev-template-depth-test-report.md)
- 续批报告: [.doc/test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md](../../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md)
## 证据 / 备注
- 资产:`.doc/test-reports/assets/2026-09-17-rdev-template-depth-s1-continued/`
- 附带:`fix(projectinstance): allocate next instance_no for planning drafts`
@@ -0,0 +1,54 @@
---
title: "rdev 模板深度补强 S0 + S1 首批"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/rdev-template-depth
worktree: ".worktrees/feature-rdev-template-depth"
mutex: rdev-templates
---
# rdev 模板深度补强 S0 + S1 首批
## 目标
修复 rdev leader prompt 错配,并为阶段 01–05 的 14 份 rdev 模板补齐 ISO 13485 专业章节与逐节写作指令,以 dev 真实 PI 打样验证收口。
## 范围
- S0.1 B1:`rdev_leader.md` + InstructionsFile 注入链
- S0.2:`rd_design_input_spec` 样例 + 写作规范 + lint
- S0.3:dev 真实 PI 打样
- S1 首批:阶段 01–05 共 14 份模板(分 3 批)
## 非目标
- overlay 机制本体、R1–R7 二期、per-stage 步骤定制、模型配置化、manifest 元数据、前端(P2)、键名空间化(P4)、阶段 06–13 模板
## 步骤
1. [x] S0.1 leader prompt 注入链(`6a09062`)
2. [x] S0.2 样例模板 + 规范 + lint(含于 `eb09b21`)
3. [x] S0.3 真实 PI 打样(项目 6424 intake + 6425 `rd_design_input_spec`)
4. [x] S1 批 1–3(`eb09b21`)
5. [x] 文档与门禁
## 验收标准
- [x] rdev leader AGENTS.md 含「设计控制」且不含「商务对接负责人」「CDO」
- [x] intake leader 回归仍含「商务对接负责人」
- [x] 14 份模板 lint 绿灯;真 PI 终稿五节实质论证
- [x] `go vet` + `go test -short` 全绿
## 相关链接
- Test report: [.doc/test-reports/2026-09-17-rdev-template-depth-test-report.md](../../test-reports/2026-09-17-rdev-template-depth-test-report.md)
- Assets: [.doc/test-reports/assets/2026-09-17-rdev-template-depth/](../../test-reports/assets/2026-09-17-rdev-template-depth/)
- Backlog: [.doc/backlog/2026-09-17-rdev-phase2-backlog.md](../../backlog/2026-09-17-rdev-phase2-backlog.md)
- 写作规范: [.doc/system-design/project-workflow/08-rdev模板写作规范.md](../../system-design/project-workflow/08-rdev模板写作规范.md)
## 证据 / 备注
- 依赖 `feature/rdev-core`(尚未合 dev);合入前需 rebase 丢弃已进 dev 的 engineering-dashboard 重复提交。
- 真 PI:`run_1789635054471569201`(intake ~220s);`run_1789635960880707641`(DI ~450s,`stage=RD03_design_input`)。
@@ -0,0 +1,70 @@
---
title: "研发工作流(rdev)接入:13 阶段 / 60 文档任务"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: fix/docgov-stage-dynamic → feature/rdev-core
worktree: "-"
mutex: workflow-def
---
# 研发工作流(rdev)接入:13 阶段 / 60 文档任务
## 目标
在现有 5 个正式工作流外新增医疗第 4 工作流「研发设计控制流程」(key: `rdev`),完整承载参考项目 13 phase / 60 文档任务的 ISO 13485 DHF 设计控制链,并通过真实 PI 验收;随后完成全工作流任务键命名空间化(P4)。
## 范围
- 方案:[07-研发工作流rdev接入-设计与实施计划](../../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md)(P0–P4 五期;§8 四项决策已确认)
- P0:docgov Stage 去硬编码 + stage key 透传
- P1:rdev.v2.json manifest(13×60 一次到位)+ 60 份 rd_ 前缀模板 + catalog/seed/registry + squad kind 编排 + main-completed precheck + 齐套测试 + stub PG 全链路
- P2:前端激活规划/切换/前置 Banner + intent 文档名匹配 + prior docs 注入与血缘
- P3:真实 PI Agent E2E(rd_proposal / rd_planning_review / rd_sw_plan 三样本)+ CI 门禁扩四
- P4:现有工作流(main/pm/tm + 软件两盘点)任务键 `bd_`/`pm_`/`tm_`(`sw_`)空间化,alias 兼容式改名(D12),独立分支独立验收
## 非目标
- 二期增强全部移入 backlog:[2026-09-17-rdev-phase2-backlog](../../backlog/2026-09-17-rdev-phase2-backlog.md)(N/A 不适用页生成、UR/RS 结构化门禁、kind 专用门禁、depends_on 精确血缘、DMR 归档、sw_ 键盘点、complexity regulatory 注入)
- 云盘 canonical DHF/DMR 归档(本仓库无云盘模块)
- 软件域(non_medical_software)开放 rdev
## 步骤
1. [x] 用户确认方案 §8 四项决策(2026-09-17:名称「研发设计控制流程」/ 60 任务一次到位 / N/A 规划期关闭 + backlog / rd_ 前缀并扩展到现有工作流键名空间化)
2. [x] P0 分支 `fix/docgov-stage-dynamic`(StageKey 透传;已叠入 `feature/rdev-core`)
3. [x] P1 分支 `feature/rdev-core`(manifest/模板/seed/编排/precheck/齐套测试)
4. [ ] P2 分支 `feature/rdev-web-governance`(前端 + intent + 血缘)— **骨架已定,待独立认领**
5. [ ] P3 真实 PI 验收 + 报告归档 + FEATURE-MATRIX 更新 — **骨架已定,待独立认领**
6. [ ] P4 分支 `feature/workflow-key-namespace`(D12 alias 兼容式改名 + 双路径回归)— **骨架已定,待独立认领**
## 验收标准
- [x] `go vet ./...` && `go test -short` 相关包 PASS(P0+P1)
- [x] 齐套断言:manifest 60 任务 ↔ `templates/docs/rd_*.md` 存在非空;rd_ 键与既有任务键不相交
- [x] precheck:main 未 completed 时 rd 任务启动被拒且文案含 CDO
- [ ] PG 集成:rdev 实例 planning→live→推进(`TestPG_RDevActivateWithNAClose`,需 `TEST_DATABASE_URL`)
- [ ] web `npm test && npm run build` PASS;Playwright 抽检激活/推进(P2)
- [ ] 真实 PI + MiniMax 三样本 E2E 报告归档 `.doc/test-reports/`(P3)
- [ ] P4:旧 live 实例(旧键)+ 新实例(新键)双路径回归 PASS;全工作流任务键集合无交集
## 相关链接
- 设计方案: [07-研发工作流rdev接入-设计与实施计划](../../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md)
- 参考调研: [2026-09-17-rdev-workflow-reference-analysis](../research/2026-09-17-rdev-workflow-reference-analysis.md)
- 二期 backlog: [2026-09-17-rdev-phase2-backlog](../../backlog/2026-09-17-rdev-phase2-backlog.md)
- Checklist: -
- Handoff: -
- Test report: -
## 证据 / 备注
- 参考项目:`.refs/weichen-agent-system`(configs/workflows/rdev.yaml 60 stage、templates/docs 60 模板、squads/overlays 配套)
- 关键约束:WF-DEF-06(无流程级依赖,precheck 先例 test_manager);doc_id `doc_proj{pid}_{taskKey}` 平铺命名 → rd_ 前缀
## 合入说明(2026-09-17)
- P0+P1 已 `--no-ff` 合入本地 `dev`(含 template-depth S0+S1)。
- P2/P3/P4 仍 planned,待独立认领。
@@ -0,0 +1,59 @@
---
title: "个人工程中控台:实时项目看板与离线 HTML 快照"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor-Auto
branch: feature/engineering-dashboard
worktree: .worktrees/feature-engineering-dashboard
mutex: engineering-dashboard
---
# 个人工程中控台:实时项目看板与离线 HTML 快照
## 目标
实现一个独立于产品后台的本地只读中控台,以同一不可变快照驱动实时页面、机器可读 JSON 与单文件 HTML 导出。
## 范围
- 聚合 `.doc`、Git/worktree、Docker/Compose、`/ready` 和晋升凭证。
- 展示架构、模块、功能、任务、分支、验证和环境实装证据。
- 提供 Markdown 搜索、阅读、正反向链接和证据链导航。
- 显示来源、新鲜度、degraded 与 drift,不把声明状态当作观测状态。
## 非目标
- 不接入产品后台、产品数据库或产品权限体系。
- 不写文档,不操作 Git、Docker、部署或 Herdr。
- 不隐式联网或执行 `git fetch`。
## 步骤
1. [x] U1:冻结快照、事实与四轴状态契约。
2. [x] U2:实现文档图谱与领域解析器。
3. [x] U3:实现 Git 与 worktree 采集。
4. [x] U4:实现运行态与部署证据采集。
5. [x] U5:实现对账、派生视图与新鲜度。
6. [x] U6:实现本地服务、总览与文档导航。
7. [x] U7:实现离线导出、脚本、浏览器验收和治理文档同步。
## 验收标准
- [x] 实时 HTML、离线 HTML 和 JSON 引用同一 `generation_id` 与 `revision_id`。
- [x] 计划、实施、验证、实装四轴独立展示。
- [x] rdev、dev ahead、main events 分叉三个真实样本按方案输出。
- [x] 单源失败时页面仍可用,且显示 stale/error/last-success。
- [x] 默认仅监听 loopback,无写操作、凭证暴露、路径越界和远程资源执行。
- [x] 导出 HTML 离开仓库后仍可阅读 Markdown,且不嵌入 assets。
## 相关链接
- 设计与实施方案:[../../archive/design/2026-09-17-personal-engineering-control-center-plan.md](../../archive/design/2026-09-17-personal-engineering-control-center-plan.md)
- Test report: [../../test-reports/2026-09-17-engineering-dashboard-test-report.md](../../test-reports/2026-09-17-engineering-dashboard-test-report.md)
## 证据 / 备注
- 实现提交序列见 `feature/engineering-dashboard`(U1→U7)。
- 启动:`./scripts/engineering-dashboard.sh serve --repo . --addr 127.0.0.1:8787`
- 导出:`./scripts/engineering-dashboard.sh export --repo . --output /tmp/engdash.html`
@@ -0,0 +1,45 @@
---
title: "临时验证脚本 Path 空字符串拼接导致跨任务取证串味"
status: done
created: 2026-09-17
updated: 2026-09-17
severity: low
---
# 临时验证脚本 Path 空字符串拼接导致跨任务取证串味
## 现象
S0.3 真 PI 打样归档时,`rd_design_input_spec-final.md` 一度被写成无关客户的商务对标报告(「掌上无线超声系统 × GE Vscan / Philips Lumify」),而非设计输入规格书终稿。
## 根因分析
产品侧小队/工作区创建正常:失败的 `rd_*` 请求因 main-completed 硬 precheck 拒绝,`task_runs.WorkspaceID` 如实为空。
缺陷在**本地临时取证脚本**(`.doc/test-reports/assets/2026-09-17-rdev-template-depth/run_s0_*.py`)的兜底逻辑:
1. `ws_id = pi_result.get("workspace_id") or ""` 在响应无该字段时得到空串;
2. Python `pathlib`:`Path(bizdev_root) / ""` **坍缩为父目录本身**(无报错);
3. 随后 `root.rglob("output.md")` 扫遍共享 `data/dev/workspaces/bizdev/` 全树;
4. 「取最长文本」启发式选中历史商务任务终稿并误归档。
证据:会话内 `task_runs` 失败记录 `WorkspaceID=""`;`Path('/a/b') / '' == Path('/a/b')` 可复现;误归档文件内含 `adhoc_GEVsca_...` 工作区路径。
## 严重度
`low` — 仅本地取证脚本;未污染产品库、未改小队/黑板创建逻辑;同轮已用精确工作区路径重归档并随测试报告提交干净终稿。
## 关联整改
- 无需产品代码改动。
- 经验红线:临时验证脚本禁止「空路径拼接 + 全树 `rglob` + 取最大值」组合;`work_dir`/`WorkspaceID` 为空时必须失败退出,不得扩大搜索范围。
## 证据
- 正确终稿:`.doc/test-reports/assets/2026-09-17-rdev-template-depth/rd_design_input_spec-final.md`
- 测试报告:`.doc/test-reports/2026-09-17-rdev-template-depth-test-report.md`
- 工作区 ID 生成:`internal/squad/workspace.go`(`ws_%s_%d` + UnixNano)
## 开放问题
- 无。
@@ -0,0 +1,32 @@
---
title: "docgov 变更提案缺少 HTTP 路由"
status: resolved
created: 2026-09-17
updated: 2026-09-17
severity: medium
---
# docgov 变更提案缺少 HTTP 路由
## 现象
引擎侧存在 `docgov.ProposeModification` / `DecideModificationProposal`,但服务端此前仅注册 `POST /api/v1/docgov/proposal/decide`;前端 `App.tsx`「变更方案提议」(`pendingProposal`)为本地模拟。
## 根因分析
生命周期三接口与 claim 已注册;变更提案 **propose** 路径从未暴露为 HTTP。
## 严重度
`medium` — 不阻塞编制→审核→批准主链;阻塞「认领后小队修改须提案确认」的真实治理。
## 处置(resolved)
- 新增 `POST /api/v1/docgov/proposal` → `ProposeModification`
- 前端 `proposeModification` / `decideModificationProposal` + App 接线
- 单测:`TestServer_DocGovProposeAndDecideHTTP`、`web/src/api/docgov.test.ts`
- 任务:`.doc/ops/short-term/2026-09-17-docgov-modification-proposal-http.md`
## 证据
- 合入后真实 HTTP 证据见 `.doc/test-reports/assets/2026-09-17-docgov-modification-proposal-http/`
@@ -0,0 +1,45 @@
---
title: 文档编制人兼任模式源码核查
status: done
created: 2026-09-17
updated: 2026-09-17
severity: medium
---
# 文档编制人兼任模式源码核查
## 结论
当前 dev 基线 adb48c8 不支持本需求。已有标准三人审批、可选免审批、系统设置白名单可复用,但必须补齐逐文档模式、职责来源和前端多职责。
## 根因与证据
1. `internal/projectinstance/duty_mode.go`:partial 拒绝,full 要求三人分离。
2. `internal/projectinstance/service.go`:创建者规划权限与激活后冻结已存在。新需求需在这条链上增加总授权,不能只改 UI。
3. `internal/docduty/store.go`:HealProjectDocuments 按项目默认职责回填受控文档。`internal/docgov/project_docs.go` 在列表读取时调用;`internal/bizdev/service.go` 在生成后调用。新增逐文档策略必须阻止该链覆盖实例职责。
4. `web/src/lib/currentDocRole.ts` 优先返回 author;`docGovActionVisibility.ts` 按单角色显示动作。同人三职会缺审核和批准入口。
5. `internal/server/handlers.go` 三个动作端点固定使用相应 action role,并以登录身份调用引擎;`internal/docgov/state_machine.go` 可复用逐步流转。
6. `internal/sysadmin/settings.go` 有白名单 bool 设置,但没有本需求 key;存储只保留最后修改人时间,新策略需独立版本与审计。
以上为静态源码核查,未查询真实用户数据,未执行功能测试,未声称线上已复现或已修复。完整源码映射与实施单元见方案。
## 关联方案
[文档编制人兼任审核批准](../remediation/2026-09-17-document-author-only-plan.md)
## 文档检查
已检查两级权限、逐文档独立性、full/none 兼容、前后端职责来源、状态与锁、并发授权撤销、成员退出、迁移及回滚。修正一处 docflow 路径为 internal/app/docflow。方案明确区分已知事实与建议口径。
ce-doc-review 未运行:当前工具目录未提供可调用的 skill invocation 入口;按 ce-plan 的 skill_unreachable 分支记录,不能把本地自检当作独立文档审查通过。
```yaml
fixes_applied: 0
proposed_fixes_count: 0
decisions_count: 0
fyi_count: 0
skipped_reason: skill_unreachable
skipped_detail: No callable skill invocation interface in this session; local source and consistency checks only.
```
上方计数仅为未运行技能的占位,不代表产品决策已解决。开放问题仍为 R9、R10;用户未答复时保持方案建议,业务实现不得自行视为授权。
@@ -0,0 +1,117 @@
---
title: "首次加载慢:静态资源、字体与初始化请求诊断"
status: done
created: 2026-09-17
updated: 2026-09-17
severity: high
---
# 首次加载性能诊断
## 结论与适用范围
当前已复现的主要问题在浏览器加载入口:登录页也下载约 2.82 MB 未压缩 JavaScript;外部 Google Fonts CSS 阻塞页面加载;若用户访问 Vite 3100,首访进一步扩大为 207 个资源请求、12.24 MB。冷缓存与热缓存差异很大,与“尤其第一次慢”一致。
登录后还有已确认的请求放大和后端重复工作,但没有登录态浏览器瀑布图或 SQL 耗时,不能声称已量化其贡献。用户已确认 3100/8080/8081,系统重启后第一次访问约十数秒;设备、网络与“系统重启”包含宿主机还是仅应用尚未确认;本次未复现用户原始环境的完整等待时间。
- 主仓读取时 `feature/rdev-core@52f0fbc`;其他 Agent 正在工作,未切换其分支。
- 文档独立 worktree 基线为 `dev@d0ef696`。创建前已 fetch;本地 dev 有未推送提交,未 reset/覆盖。
- 实测现有 8080/8081/8000 构建入口与 3100 Vite;以资源 hash 为运行产物标识,**没有证据证明容器恰好等于上述源码 commit**。
- “首次”定义为新浏览器 context、空 HTTP 缓存;没有重启服务、清空 DB 缓存或重启 Vite,故不是服务/依赖预构建冷启动。
- 未登录、没有调用对话/文档写接口;浏览器探针未使用真实用户会话。
## 实测基线
工具:隔离 Playwright v1.63.0 Docker 浏览器,host 网络访问既有服务。宿主浏览器缺 libatk,改用本机已有浏览器镜像;未修改应用容器。每个场景一个样本,仅诊断,不是 p95 或交付验收。
| 场景 | 登录输入框可见 | FCP | 资源数 | transferSize 合计 |
|---|---:|---:|---:|---:|
| 8080 本机冷缓存 | 662 ms | 664 ms | 4 | 2,857,761 B |
| 同 context 再次导航 | 62 ms | 60 ms | 5 | 353 B |
| 8080 CDP 10 Mbps / 80 ms 冷缓存 | 2,636 ms | 2,636 ms | 4 | 2,857,761 B |
| 同 context 再次导航 | 60 ms | 60 ms | 5 | 353 B |
| 8080 CDP 2 Mbps / 80 ms 冷缓存 | 11,776 ms | 11,776 ms | 4 | 2,857,761 B |
| 3100 本机冷缓存 | 659 ms | 652 ms | 207 | 12,238,086 B |
| 3100 同 context 再次导航 | 162 ms | 160 ms | 208 | 52,253 B |
transferSize 是浏览器 Resource Timing 可观测资源求和,不含顶层 HTML,不等于全链路抓包流量。输入框可见按导航命令开始至 selector 可见计时,FCP 来自页面 Performance API,两者采样时钟和帧提交不同。CDP 限速为模拟设置,不能代替真实公网 RTT;本机 document TTFB 仍约 1–3 ms。首次/再次均保持已有服务运行,未运行 Vite 冷预构建基准。
### F1. 入口包过大且未按需加载(高置信)
- `web/src/main.tsx:2` 静态导入 App;`web/src/App.tsx:98,103,108,145-146` 静态导入导出、系统管理、文件预览等模块;未登录判断直到 `App.tsx:3461`,无法避免入口依赖下载和求值。
- `web/src/features/replyExport/download.ts:1` → docx;`web/src/engine/docxRenderer.ts:19-22` → docx、KaTeX、Mermaid;`web/src/engine/xlsxRenderer.ts:1` → XLSX。
- `web/src/components/doc/preview/FilePreviewPanel.tsx:19-24` 全部静态导入预览器;DocxViewer、ExcelViewer 各自静态导入重依赖。
- 浏览器访问登录页即可观测大 JS。3100 瀑布中含 katex.js 485,944 B、xlsx.js 870,702 B(decodedBodySize)。并非仅仅源码中出现依赖但构建已经排除。
- 8080 主 JS `/assets/index-BLnmtk_3.js` = **2,820,055 B**;8081 = 2,805,141 B;8000 = 2,798,137 B。
因果链:空缓存 → 登录视图与全部工具共入口 → 下载/解析无关依赖 → 网络较慢时登录表单迟迟出现。10 Mbps 下主 JS 下载约 2,373 ms;2 Mbps 首屏约 11.78 秒。没有采集 CPU trace,不能进一步把时间分解成具体库的执行成本。
### F2. 静态响应无压缩、无明确长缓存策略(高置信)
- 三个构建入口均携带 `Accept-Encoding: gzip, br` 请求主 JS,响应没有 `Content-Encoding`,`Content-Length` 为原始字节数。
- `internal/server/server.go:344-384` 使用 `http.ServeFile`,没有静态压缩协商或显式 Cache-Control。
- 同一 8080 JS 离线 gzip 后 **796,146 B**,相对原始包减少约 **71.8%**。这是体积估算,不是已部署优化结果,也不是端到端提速承诺。
- 资源有 Last-Modified,没有显式 Cache-Control/ETag。本次再次导航已命中浏览器缓存;**不能写成“完全没有缓存”**。问题是版本化资源缺少可预测的长期缓存契约。
源站是上述行为,未知用户实际入口是否另有反向代理压缩。优先在真正提供构建资源的层验证和修复。
### F3. 外部字体 CSS 可放大首次白屏(高置信机制,用户网络贡献待测)
- `web/index.html:9-15` 的 Google Fonts 是 head 中普通 stylesheet。`display=swap` 控制字体显示,不会让外链 CSS 本身变为非阻塞。
- 本机自然请求字体 CSS 耗时 **508 ms**,DOMContentLoaded 609 ms,登录可见 662 ms。
- 浏览器拦截并立即失败字体 CSS:登录可见 **210 ms**。Playwright route 会禁用 HTTP cache,因此这个场景不能用于热缓存收益对比,也不能据单样本得出精确净收益。
- 控制实验仅让字体 CSS 等待 5 秒再失败,其余请求正常:DOMContentLoaded **5,111 ms**、登录可见 **5,161 ms**。证明该依赖可以把外部等待传到登录首屏,**不表示自然字体请求真的用了 5 秒**。
### F4. 登录后项目成员扇出并放大会话同步(源码已证实,耗时待测)
`web/src/App.tsx:524-540` 获取项目后,对每个项目调用成员接口;`:383-387` 每次成员结果用 map 生成新的 projects 数组;`:560-590` 的会话列表 effect 依赖 projects,因此成员返回可重复触发会话列表请求。取消标志仅忽略部分返回,没有 AbortController 终止已发请求。React 批处理可能合并更新,**不能写成固定 N 次会话请求**。
项目数 N 增大时,初始成员请求为 N,叠加会话重取、setProjects 及本地持久化。`web/src/data/storage.ts:63` JSON.stringify + localStorage.setItem,`App.tsx:343` 随 projects 更新保存。持久化是否成为长任务还须 profile,不能预设为主要根因。
### F5. 认证有重复查询和同 session 写放大(源码已证实,耗时待测)
`internal/server/auth_middleware.go:48,62` 已认证并保存 principal;`internal/server/auth_handlers.go:126-139` 的 me 再认证。每次经 `internal/auth/service.go:197-203`、`internal/auth/pg_store.go:335-367` 执行 SELECT session、SELECT status、UPDATE session、GetUserByID。正常 PG me 路径共 8 次认证 DB 操作,加一次权限查询。
其他鉴权请求也无条件 UPDATE 同一 auth_sessions 行;首屏并发可能放大行锁/连接等待。未采集 pg_stat_activity/锁等待或接口 p95,锁竞争是待验证风险。
### F6. 文档列表的隐含写修复与轮询叠加(源码已证实,耗时待测)
`internal/docgov/project_docs.go:59-74` 列表先调用 `HealProjectDocuments`;`internal/docduty/store.go:173-205` 开事务并取得项目 advisory lock(`internal/docduty/revoke.go:111-126`),重复读取创建者/成员,扫描文档,按需逐条 UPDATE,commit 后才正式 SELECT。
前端 `App.tsx:1507-1545` 每 5 秒为租约同步调用这个完整列表。请求时长超过间隔时可能重叠;相同项目多个标签放大成本。**不能直接删除 heal**:须先补齐创建/成员变更/转交/撤销写路径与历史数据修复闭环。本轮没有用该 GET 做只读探针。
### F7. 会话列表先聚合消息再分页(源码已证实,耗时待测)
`internal/ctxmgr/chat_history.go:110-125` 候选会话 JOIN 消息、COUNT、GROUP BY/ORDER BY 后 LIMIT,另取最新消息内容。仅返回少量会话不代表少量消息扫描。`internal/projectworkflow/store.go:171-240` 项目列表也无分页。
已有 `chat_messages(session_id, created_at)` 索引(`deploy/postgres/goose/00001_baseline.sql:119`);不笼统认定缺索引。先 EXPLAIN/数据量和可见性分析,再决定先分页后统计、索引或摘要。
### F8. 重启场景补查(用户补充后)
用户明确 3100、8080、8081 在系统重启后首次进入约十数秒。三种冷态须分开:浏览器 HTTP 缓存、Vite 转换/依赖缓存、Go/DB/代理启动就绪。重启若不改变构建 hash,并不会自动清掉浏览器持久 HTTP 缓存;不能直接用新 context 测量解释全部重启现象。
现存容器启动记录:dev StartedAt `2026-09-17T07:00:38.127811581Z`,打印“监听地址”于 `07:00:38.293728694Z`(约 **166 ms**);test StartedAt `06:20:05.243037366Z`,打印监听于 `06:20:05.384607542Z`(约 **142 ms**)。这是已有 DB 就绪条件下的一次启动、且日志先于真正 ListenAndServe,**不是 host reboot→ready 时间**;但未支持“Go 每次初始化必然十几秒”。
`cmd/server/main.go:41-50` 的初始化在监听前,`internal/bizdev/service.go:69-114` 包括 DB Ping/迁移/成员补齐/seed;DB连接段 timeout 5 秒,后续 seed 使用 Background,缺少分阶段耗时。`internal/app/app.go:355` 的 Runtime.Start 幂等,入口重复调用不会重复启动 worker,不能据此误判双倍启动。
Compose app healthcheck 每 10 秒、start_period 20 秒;start_period 是失败宽限窗口,**不代表强制等待20秒**。若代理/运维脚本等健康状态才放流,则探测周期可能影响可见就绪,需要对齐宿主启动、DB healthy、app listen、ready、首次请求时间。3100 的无缓存 Vite 预构建/按请求转换为独立候选,8080/8081 构建产物不存在 Vite 首次编译。
隔离 Vite 在 3199 使用独立空 cacheDir,同源码、未重启宿主/DB:监听准备 43 ms,首访登录可见 **1,580 ms**、207 资源/14,445,631 B,再次 171 ms。服务先启动、浏览器随后连接,部分预构建可能已在导航前完成;该值不是“启动到首屏”总时间。支持开发冷态有额外成本,但本机未复现自然网络十数秒;不得仅靠 warmup 宣称已解决 8080/8081。证据见 `../test-reports/assets/2026-09-17-initial-load-performance/vite-cold.json`。
本轮不重启正在使用的共享服务;U1/U7 纳入计划中的隔离重启矩阵和阶段计时。没有把服务冷启动排除在用户需求之外。
## 已排除与未证明
- 本机静态 HTML TTFB 约 1–3 ms;这组未登录测试并非后端生成首页耗时数秒。
- 没有请求产品 PI Runner,因此本次首屏慢不能归因于大模型冷启动。
- 服务监听前迁移/种子初始化(`cmd/server/main.go:41-50,84-85`;`internal/bizdev/service.go:69-114`)只解释重启就绪,不等于每个新浏览器首访。
- 没有用户重启时的 FRP/公网瀑布、登录后基线、慢 CPU profile、数据库 EXPLAIN;不对这些项宣称已复现。
- 基线现有测试以功能为主;本轮未发现首屏资源预算/冷缓存性能门禁。未运行业务测试,因为没有业务代码变更。
## 关联整改与证据
- [改进方案](../remediation/2026-09-17-initial-load-performance-plan.md)
- [诊断测量报告](../test-reports/2026-09-17-initial-load-performance-baseline.md)
- [完整浏览器数据](../test-reports/assets/2026-09-17-initial-load-performance/browser.json)
- [受控实验](../test-reports/assets/2026-09-17-initial-load-performance/controlled.json)
- [静态响应摘要](../test-reports/assets/2026-09-17-initial-load-performance/assets.json)
@@ -0,0 +1,180 @@
---
title: "系统全面体检:任务收口、缺陷与未启用功能审计"
status: done
created: 2026-09-17
updated: 2026-09-17
severity: high
---
# 系统全面体检(2026-09-17)
> 范围:① 规划未实现 / 需变更 / 实施中任务;② 现存与潜在 bug;③ 已实现但未启用或未测试的功能。
> 方法:文档 SSOT 盘点(CURRENT / FEATURE-MATRIX / gap-matrix / short-term / long-term / backlog / ADR / handoff)+ Go 全量 vet/build/test + 前端 test/build + 特性开关与环境配置交叉核对。只读审计,未实施任何修改。
> 基线验证:`go vet ./...` 与 `go build ./...` 全绿;`go test -short -count=1 ./...` 62 包全 ok;`web` npm test(380+32)与 build 通过。
---
## 一、任务状态盘点
### 1.1 实施中(in_progress)
| # | 任务 | 位置 | 剩余工作 |
|---|------|------|----------|
| T1 | partial/deferred 全量收口总控 | `.doc/ops/short-term/2026-09-16-partial-deferred-completion.md`(owner Cline) | W5(SWBOOT-10 真实现 + 真实 PI + UI 二次验收)、W6(FAV shadow→live 放量)、W7(D7 按 ADR 整改,待合规签字)、逐行升 done |
| T2 | Control Center 个人中控台 | 2026-09-19 已移出本仓库 | 进度管理改由独立项目承担;本仓库不再保留该模块 |
| T3 | 纯软件项目自举 W5b | `.doc/ops/long-term/2026-09-14-software-project-bootstrap-implementation.md` | SWBOOT-10 受控执行器(真 patch/merge)未启动,需独立安全评审,当前 fail-closed stub |
### 1.2 已规划未开始
| # | 任务 | 位置 |
|---|------|------|
| T4 | 首次加载性能 U1/U3–U7 | `.doc/remediation/2026-09-17-initial-load-performance-plan.md`(仅 U2 done:主 JS 传输 2.82 MB→~624 KB) |
| T5 | 选择性模块解耦 M4–M6 | `.doc/ops/long-term/2026-09-14-selective-module-decoupling.md`(planned,owner=TBD) |
| T6 | 产品 backlog:B5 报价复核、A5/A6 小队降级与 trace、A7 中文注释迁移、D5 KB 按环境隔离评估 | `.doc/backlog/chat-agent-p6-backlog.md`(均无任务文件) |
| T7 | `TestReconcile_LegacyRepair_PG` 工程测试债 | gap-matrix DOC-CONTENT-CANONICAL-HASH-DRIFT 行(需隔离 PG,本机无) |
| T8 | IAM 收尾开放项:410 退役产品拍板、R13 全量清单勾选 | handoff `2026-09-16-phase3-leftover-closeout.md` |
### 1.3 部分完成(partial,剩余关闭条件)
| 行 | 剩余关闭条件 |
|----|--------------|
| 纯软件项目自举 | SWBOOT-10 非 stub(W5b)+ 真实 PI 全链路 + UI 二次验收 |
| FAV | W6 shadow 已合;live 未放量(staging→artifact→publication 各 ≥7 天观察窗) |
| Control Center | 2026-09-19 已移出本仓库,不再作为本仓库关闭条件 |
| 首次加载性能 | U1/U3–U7 |
| 文档可靠性试点 | M1 结论「停止扩面」;M2(U5–U12)明确禁止开工,真实 PI/浏览器验收未勾 |
### 1.4 deferred 待决策
- **D7 对话数据治理**:ADR `2026-09-17-d7-chat-data-retention.md` 仍 `pending-compliance-signoff`;W7 盘点未发现违规;签字前禁止物理删除。
- **`SEMANTIC_SUMMARY_REPLACE`**:决策默认不启用;启用须另开授权 + fail-closed 灰度。
- **`MULTI_INTENT_PLAN_TIER` 升 confirm**:W4 证据闭环,升级需独立授权;永不默认 full。
### 1.5 文档漂移 / 矛盾(文档债)
| # | 漂移 | 涉及文件 |
|---|------|----------|
| D-1 | PU8 四份契约文件仍 `status: in_progress`,但 U9–U12 已升 done、报告已归档 | `.doc/ops/long-term/2026-09-16-pu8-u9/u10/u11/u12-*.md` |
| D-2 | ADR modular-monolith-decoupling 仍「提议,等待用户确认」,但 Phase 1/2 已落地并被当作已确认结论引用 | `.doc/adr/2026-09-14-modular-monolith-decoupling.md` |
| D-3 | audit/INDEX.md 与 remediation/INDEX.md 末行称首次加载性能「方案未实施」,与 U2 已验收矛盾 | 两个 INDEX.md(**本审计已顺手修正为准确表述**) |
| D-4 | handoff `2026-09-15-conversation-intent-dual-tab.md` 的「未完成」已被后续 PASS 覆盖但未回标 | 该 handoff |
| D-5 | backlog D3/D7 条目与 W2 done、W7/ADR 草案并存,backlog 未同步 | `.doc/backlog/chat-agent-p6-backlog.md` |
| D-6 | PROJECT.md §9「剩余 blocker」表述与 gap-matrix「门禁已签、production_ready=yes」口径冲突 | `PROJECT.md` |
---
## 二、Bug 清单
### 2.1 确认 bug(有明确证据)
**后端**
| ID | 描述 | 证据 | 严重度 |
|----|------|------|--------|
| B-1 | **SSE 聊天流被全局 WriteTimeout=120s 强杀**:`server.go:350` 的 WriteTimeout 是绝对期限;`handleChatStream`(`sse.go:129`)从不调用 `extendSSEWriteDeadline`、无心跳,该机制只接到了 run-events 订阅端点。任何 >120s 的聊天回合(长 PI 推演常见)必断流 | `internal/server/server.go:350`、`internal/server/sse.go:46-64,129` | high |
| B-2 | **`POST /tasks/run/stream` 同样无 deadline 延长/心跳**,且断线后无法续订:`sse.go:390` 写死 `Subscribe(created.RunID, 0)`,不接受 `after_seq` | `internal/server/sse.go:305-424,390` | high |
| B-3 | `handleRunTaskStream` **静默吞 JSON 解析错误**:`_ = json.NewDecoder(r.Body).Decode(&req)`,畸形 body 以空请求走默认 `TaskKey="intake"`,可能误启动 intake 任务 | `internal/server/sse.go:315,362-364` | medium |
| B-4 | `handleRunTaskStream` **Flush 200 SSE 头之后才做会失败的操作**(CreateAndStart/Subscribe),失败时往 SSE 流里写 JSON 错误体;同文件 chat 路径明确「授权必须在 Flush 前」,task 路径未对齐 | `internal/server/sse.go:355-360,383-393` | medium |
**前端**
| ID | 描述 | 证据 | 严重度 |
|----|------|------|--------|
| B-5 | **会话窗口缓存 key 不一致**:读/初次写带 `userId` 前缀,但 `loadOlder`/`loadFullDay`/`jumpToDate`/`loadDayForAnchor`/`appendLiveMessage` 等 7 处后续写入不带前缀 → 刷新/切会话恢复到旧窗口;且 LRU 驱逐只用无前缀 key,带前缀缓存永不驱逐,localStorage 只增不减 | `web/src/hooks/useChatWindow.ts:84,100,136,235,271,315,365,416,439,471`、`web/src/data/storage.ts:164-176` | high |
| B-6 | **mount 时 IndexedDB 恢复用陈旧快照整体覆盖 deliverables**:捕获 mount 闭包、非函数式 set,resolve 前新增的 deliverable 被静默丢弃(旁边已有 `deliverablesRef` 未用) | `web/src/App.tsx:326-336` | medium |
| B-7 | `useTaskRunStream` 返回**伪 ref**(每渲染新建对象、快照值非 live),且全仓库无消费方——误导性 API | `web/src/hooks/useTaskRunStream.ts:96` | low |
### 2.2 高风险隐患
| ID | 描述 | 证据 |
|----|------|------|
| R-1 | **聊天会话无归属校验**:`getOrCreateSession` 仅凭客户端传入 `session_id` 返回既有内存会话,随后直接覆盖 `sess.UserID`;非项目会话(ProjectID==0)无任何授权关卡,内存 Messages/Facts 可进入他人 Prompt 与 SSE。缓解:session ID 为纳秒时间戳不易猜 | `internal/server/server.go:394-415`、`handlers.go:181`、`sse.go:187`、`stage_access_helpers.go:251-253` |
| R-2 | **18 个非测试文件 `rows.Next()` 循环后未查 `rows.Err()`**,中途断连静默截断结果集(ctxmgr 历史/窗口/搜索、docgov engine、freedoc、storage/cas、`cmd/document-content-reconcile` 漏检会让 reconcile 漏报文档) | 如 `internal/ctxmgr/chat_history.go`、`internal/docgov/engine.go`、`cmd/document-content-reconcile/main.go:82` |
| R-3 | 事件 dispatcher `Handlers` map **写持锁、读不持锁**(当前仅启动期注册则良性,动态注册即 race) | `internal/events/worker.go:87,154,234` |
| R-4 | `memTurns` 全局幂等表只增不删且跨实例共享,长期运行内存缓增、测试间可能串扰 | `internal/ctxmgr/chat_turns.go:169` |
| R-5 | `internal/docrevision/pg_store.go:68-208` 十余处 `_ = json.Unmarshal(...)`,账本 JSONB 损坏时静默零值化 | 同左 |
| R-6 | 后台 ticker goroutine 无关停通道(通知提醒、vault Drain 错误被丢弃、bizdev 心跳用 `context.Background()`),`Shutdown` 未覆盖 | `notification_reminder_loop.go:15`、`vault.go:63`、`bizdev/service.go:682` |
| R-7 | SSE 重连对 401/404 无 fail-fast:任何错误一律退避重连 40 次(~3 分钟)期间 UI 一直 thinking;`streamChat` 对畸形 data 帧直接抛错中断整条流 | `web/src/api/taskRuns.ts:108-140`、`api/chatStream.ts:122` |
| R-8 | 组件卸载/登出不 abort 任务流,在途 SSE 继续写 localStorage | `web/src/App.tsx:595,2804` |
### 2.3 环境 / 配置缺陷
| ID | 描述 | 证据 | 严重度 |
|----|------|------|--------|
| E-1 | **main 环境 app `ENV=prod` 与 events `ENV=main` 不一致**:事件信封以 `Environment="prod"` 写入,而 `event_consumer_modes` 只种子 dev/test/main 三行 → app 侧 `WriterLive("prod")` 恒 false(in-process 直连不退出),events worker 按 'main' 判定 → **main 存在双写或 durable 管道空转风险**(取决于 main 行 mode)。dev/test 两服务 ENV 一致,无此问题 | `docker-compose.main.yml:90,160`、`internal/app/docflow/commands.go:276`、`goose/00040:55-59`、`internal/events/dispatcher.go:308-313` | **critical(main 专属)** |
| E-2 | **main schema 落后两版(47 vs dev 49)**:00048 给 projects 加 13 列,当前 HEAD 代码直接 SELECT/INSERT 这些列;00049 建 system_settings。若把 dev HEAD 镜像升 main 而不先跑迁移,项目工作流查询/系统设置 API 直接 SQL 报错。**main 晋升顺序必须 events(跑迁移)先于 app** | `goose/00048`、`goose/00049`、`internal/projectworkflow/store.go:76,113` | high(晋升窗口) |
| E-3 | `MULTI_INTENT_PLAN_TIER` 未在任何 compose environment 声明(configs/.env 设了也传不进容器);test/main 连 U9–U12 flag 都未声明 → 容器内锁死 legacy,授权升级时需先改 compose | `docker-compose.*.yml` | medium |
| E-4 | `CURSOR_RUNNER_URL` 三环境 compose 都注入但代码零读取;cursor-agent 容器是 alpine 占位,cursor-cli 后端容器部署不可达 | `docker-compose.*.yml` | low |
| E-5 | `ENABLE_DEV_IMPORT` 不在任何 compose/.env.example;且判断把 `cfg.Env==""` 也算 dev——配置缺失时导入门禁自动放开 | `internal/server/chat_window_api.go:171` | medium |
| E-6 | `SEED_DEMO_USERS` 仅 test compose 显式 false;dev 依赖默认播种(demo 密码 123456),main 靠代码 `Env!="dev/test"` 兜底,主 compose 未显式关闭 | `docker-compose.test.yml:91`、`internal/auth/bootstrap.go:67-116` | low |
| E-7 | `INTENT_V2_DECISION_TIER` 非法值回退 `query`(激进),与 `MULTI_INTENT_PLAN_TIER` 回退 `legacy`(保守)策略不一致 | `internal/intent/flags.go:47-64` | low |
| E-8 | `publisher_gate_test.go:16` 读 `FAV_PUBLISHER_ENABLE`(少 D),与正式变量名不符,该测试门永远走默认分支 | `internal/artifactvault/publisher_gate_test.go:16` | low |
| E-9 | main compose 的 system-db initdb 只挂 00001_baseline.sql,与 dev/test 不一致;新建卷时初始脚本漂移(依赖 events 启动迁移补齐) | `docker-compose.main.yml:23` | low |
---
## 三、已实现但未启用 / 未测试的功能
### 3.1 特性开关封存(实现完整,全环境 off)
| 功能 | 实现位置 | 状态与门禁 |
|------|----------|-----------|
| FAV 事件订阅者 | `internal/app/fav/subscriber.go` | 三重硬门禁:cmd/events 刻意不注册、registry fail-closed、SetMode 拒绝非 off;仅 ObserveShadow 可达 |
| FAV 发布器 | `internal/server/vault.go:18-67` | `FAV_PUBLISHER_ENABLED=false` 三环境显式;且 VAULT_* 三变量 compose 全未声明,容器内即使开 flag 也会静默 return(E-类:实际不可误开,属设计内封存) |
| FAV 降级读 | `internal/docquery/service.go:70` | `FAV_DEGRADED_READ=false` 红线保持 |
| 多意图 PlanTier shadow/auto_read/confirm | `internal/app/intentflow/turn.go` | 容器内锁死 legacy(见 E-3) |
| U9–U12 扩面 | `intentflow/expansion.go`、`mux.go` | 全 false;dev compose 已声明可调,test/main 未声明 |
| 意图 V2 shadow/decision | `internal/intent/shadow_v2.go`、`v2_decision.go` | 三环境显式 false |
| 语义摘要 shadow | `internal/ctxmgr/semantic_summary.go:216` | 默认 off,且仅 AGENT_BACKEND=pi-agent 时挂载 |
| PI change-report 叙事 | `internal/docrevision/narrative.go:68` | 默认 off,仅确定性 fallback(不得冒充完整 PI) |
| artifact-vault CLI | `cmd/artifact-vault/main.go` | 未部署 stub |
| eventmode cutover CLI | `cmd/eventmode/main.go` | 硬门禁仅 dev 可用(`internal/events/cutover.go:13`) |
### 3.2 死代码 / 机制先行无消费方
| # | 项 | 位置 |
|---|----|------|
| X-1 | `SEMANTIC_FALLBACK_ENABLED` 死 flag:无任何业务消费方,仅 sysadmin 展示;三环境 compose 都在设一个没用的变量 | `internal/intent/flags.go:43`、`internal/app/app.go:285` |
| X-2 | `SEMANTIC_SUMMARY_REPLACE` 读取后 `_=` 显式丢弃,刻意永久未接线 | `internal/ctxmgr/semantic_summary.go:257` |
| X-3 | goose 00048 三张新表 `project_source_bindings`/`repo_path_allowlist`/`project_type_workflows` 无代码消费方(swboot 目录硬编码内存版,RepoAllowlist 为 stub) | `internal/swboot/catalog.go:92,118`、`repo_allowlist.go` |
| X-4 | `system_settings` 白名单 6 键全部无业务消费方——可写不生效,纯机制先行 | `internal/sysadmin/settings.go:57-66` |
| X-5 | 前端死组件:`DocumentNotificationList.tsx`(含已读回写,功能完整无挂载点)、`WorkflowPrerequisiteBanner.tsx`、`user/SettingsModal.tsx`(已被 UserSettingsModal 取代);死 API:`api/projectWorkflow.ts:71 activateWorkflow`;`data/storage.ts:141 saveMessages` deprecated no-op | web/src 各文件 |
| X-6 | `useTaskRunStream` 伪 ref(同 B-7) | — |
### 3.3 测试盲区
| # | 盲区 | 说明 |
|---|------|------|
| S-1 | `TestReconcile_LegacyRepair_PG` 从未执行 | 要求隔离 PG 且硬拒绝 5433/5434/5435;canonical-hash 修复链路零自动化验证(gap-matrix 已记测试债) |
| S-2 | 两个「永久跳过」 | `taskstream_test.go:189`(功能已删,测试成死代码应删除);`plan_owner_test.go:125`(重定向跳过) |
| S-3 | 无测试的 cmd 入口 | `cmd/server`、`cmd/events`、`cmd/artifact-vault`、`cmd/dataset`、`cmd/eventmode`、`cmd/recategorize`、`cmd/document-revision-backfill`(仅 bizdev-cli、document-content-reconcile 有);`internal/observability`、`internal/workflow` 无测试文件 |
| S-4 | **E2E 默认全不跑**:web/e2e 9 个 spec 全部被环境门禁(`RUN_UI_ACCEPTANCE=1`/`DOCREV_E2E_BASE_URL`/`INTENT_DUAL_TAB=1`),默认 `playwright test` 实跑 0 用例;`test:ui-acceptance` script 只覆盖 1 个 spec,其余 8 个无 script 入口 | web/e2e/、web/package.json:11 |
| S-5 | 409 信封处理只覆盖部分消费方:projectMembers、freeformDoc、createTaskRun、chatSessions upsert 等 409 只能裸报错(与 FEATURE-MATRIX hardening backlog 一致) | `web/src/api/projectMembers.ts`、`freeformDoc.ts:177`、`taskRuns.ts`、`chatSessions.ts` |
| S-6 | 前端 bundle 大 chunk 未分割(mermaid/katex/xlsx/docx 各成 >500 kB chunk,已有 precompress 缓解) | vite build 警告 |
---
## 四、结论与优先级
**总体判断**:发布门禁与 FEATURE-MATRIX 的 `done/partial/deferred` 口径与代码实况基本一致,未发现「stub 冒充验收」类违规;质量门禁(vet/test/build)全绿。主要风险集中在三处:
1. **E-1(main ENV 不一致 → 双写/空转)是唯一 critical 级发现**,且只在 main 环境存在, dev/test 的「healthy」不能证明 main 事件链路正确。
2. **SSE 120s 断流(B-1/B-2)直接影响长任务可用性**,是用户可感知的现存 bug。
3. **封存面(FAV/多意图 tier/U9–U12/语义摘要/PI 叙事)实现完整但容器内不可调或硬门禁封存**,红线达标,但授权放量时会发现 compose 层缺失(E-3)与若干死接线(X-1/X-2)。
详细整改顺序见 [remediation 方案](../remediation/2026-09-17-system-health-remediation-plan.md)。
## 关联整改
- Remediation: [2026-09-17-system-health-remediation-plan.md](../remediation/2026-09-17-system-health-remediation-plan.md)
## 证据
- `go vet ./...` / `go build ./...` / `go test -short -count=1 ./...`(62 包 ok)/ `cd web && npm test && npm run build`:2026-09-17 全绿。
- 文中所有 `文件:行号` 引用均为 2026-09-17 dev 分支工作区实测。
## 开放问题
- E-1 的修复取向(app 改 `ENV=main` vs 事件信封/consumer mode 键改用部署名)需架构决策。
- D7 合规签字、`MULTI_INTENT_PLAN_TIER` 升 confirm、FAV live 放量均需用户显式授权,不在本整改自动范围内。
- configs/.env.dev/.env.test/.env.main 实际文件未读取(含密钥);若偏离 example 模板,E-3/E-4/E-6 结论需复核。
+130
View File
@@ -0,0 +1,130 @@
---
title: "系统深度体检审计(2026-09-19,dev@e8ed33b)"
status: done
created: 2026-09-19
updated: 2026-09-19
severity: high
---
# 系统深度体检审计(2026-09-19)
> 只读审计,未修改业务代码。分支 `docs/system-deep-audit-2026-09-19`,基点 dev@e8ed33b。
> 方法:go vet / go test -short 静态基线 + 五路并行深潜(后端 server/chat、docgov/events/工作流/迁移、前端 web、配置 flag/死代码、安全鉴权)。
## 一、总体结论
- **静态基线健康**:`go vet ./...` 零告警;`go test -short ./...` 55 包全 PASS;全仓 TODO/FIXME 仅 2 处非实质。
- **四条已声明红线全部核实一致**:`MULTI_INTENT_PLAN_TIER=legacy`、`SEMANTIC_SUMMARY_REPLACE` 未接线、`FAV_DEGRADED_READ=false`、SWBOOT-10 fail-closed stub——代码与三环境 compose 均对齐,无漂移。
- **IAM 主链路复核成立**:路由统一挂鉴权中间件、SQL 全参数化、token 哈希存储、错误出参有内部信息过滤。但存在 dev/test 兜底与端点级鉴权缺口(见 S1/S2)。
- **本次新发现**:2 项 critical(后端数据竞态 + docgov 吞错)、10 项 high、若干 medium/low。其中 3 项被两路独立审查交叉命中(见 ★ 标记),可信度最高。
- FEATURE-MATRIX 已声明的 partial/deferred(rdev、SWBOOT、FAV、D7、首载性能)不在本次重复申报范围;本次发现均为**新增**缺口。
## 二、Critical(发布前必须评估)
### C1 ★ docgov 持久化全链路 fire-and-forget 吞错;fencing token 未读回
`internal/docgov/lease.go:460-467, 485-490`;`internal/docgov/engine.go:318, 392, 405, 470, 477, 650, 743, 750, 1081-1134`
租约获取/续约/回收、正文哈希、认领状态、提案决定及**全部审计日志**均为 `_, _ = e.pool.Exec(...)` 静默吞错:
- 审计 INSERT 失败 → 合规事件永久丢失,无重试无告警;
- 租约 UPDATE 失败 → 内存与 DB 分叉,重启后可并行编辑同一文档;
- `lease.go:485` 用 `context.Background()` 脱离请求生命周期;
- `loadDocumentFromDBLocked` 的 SELECT 列表**不含 `lease_fencing_token` 列**(00034 迁移已建列)→ 进程重启后 fencing 语义完全失效(合法持锁者被误判 stale,或 stale 写者被放行——两个方向都有缺口)。
**建议**:持久化失败必须返回 error 或 slog.Error+指标;审计写入失败进重试队列;lease SELECT 补 fencing 列;persistLeaseLocked 失败回滚内存状态。
### C2 ★ Session 全字段数据竞态 + 跨项目污染
`internal/chat/session.go:275-277`;`internal/server/server.go:432-435`;`internal/server/handlers.go:196-198`
- `Messages`/`UserCtx`/`LastAccessedAt` 的读写锁粒度碎片化:SSE 路径持 `execMu`,而 `hydrateVisibleHistory`、`handleGetProject`、`cleanStaleSessionsLocked`、`server.go:435` 均不持锁。并发 SSE+REST 同会话时 `go test -race` 可复现 data race。
- `handleChat` 无锁写 `sess.ProjectID = req.ProjectID`,同一 sessionID 被不同项目请求交错时跨项目串扰。
**建议**:Session 加 `sync.RWMutex` 统一保护;ProjectID 改为请求级参数不写回共享 sess。
### C3 SSE WriteTimeout=120s 硬杀长任务 + 心跳 goroutine 生命周期不一致
`internal/server/server.go:352-355`;`internal/server/sse.go:252-271`
全局 `WriteTimeout: 120s`;SSE 靠 45s 续期+15s 心跳兜底,心跳被中间代理吞掉时长 LLM 回合(dialogueTimeout=3min)被强杀。非流式 `handleRunTask` 同步执行数十分钟任务,120s 必然截断响应(业务已执行、客户端收不到结果 → 幂等重试造成重复执行观感)。心跳 goroutine 模式与 `handleTaskRunEvents`(主循环 select,无此问题)不一致。
**建议**:长任务端点异步化(提交+轮询/SSE);心跳并入主 select 或 WaitGroup 收敛。
### C4 工作流计划保存跨语句竞态 + completed_by 错填
`internal/projectinstance/service.go:185-190`;`internal/projectinstance/stage_store.go:132-138`
- `SaveWorkflowPlan`:upsert 与 bump revision 两条独立事务,并发下同版本号先互相覆盖 plan 再一方 bump 失败 → **版本号与 plan 内容错位落库**。`Activate` 的 token 前置校验与激活事务间存在 TOCTOU。
- `completed_by = (SELECT activated_by ...)`:最终阶段完成的归属人被错填为激活人,审计归属错误。
**建议**:upsert+bump 同事务 + `FOR UPDATE` 锁 project 行;completed_by 显式传当前操作者。
## 三、High(建议进入 short-term 整改)
| # | 发现 | 位置 | 要点 |
|---|------|------|------|
| H1 ★ | dev/test 未认证静默兜底为 user id=1 | `internal/server/auth_middleware.go:48-51` | `Env=dev|test` + `AllowInMemory` + 无 ContextDB 时,无 token 请求静默识别为 id=1(管理员)。main 已被 `validateProductionSecrets` 兜住。建议:兜底路径加审计日志+启动告警;中期删除 legacy 兜底 |
| H2 ★ | docgov 批注/审计端点无资源级鉴权且信任请求体身份 | `internal/server/handlers.go:858-940, 534-552` | 任意登录用户读任意文档批注/审计;`AddComment` 直接用 `req.UserID/UserName/UserRole` 可伪造他人身份;`Claim` 角色由客户端自选。两路审查交叉命中。建议:actor 一律取 principal;读类端点加项目成员校验 |
| H3 ★ | 会话查询类端点水平越权 | `chat_turn_api.go:12-45`;`handlers.go:947-981, 429-451` | `handleGetChatTurn`/`handleListChatSessions`/`handleGetUserContext` 的 session_id/user_id 来自 query 不校验归属;userID<=0 时默认 1(种子 admin)。建议:改用 principal 或比对不一致 403 |
| H4 | 登录/注册无速率限制 | `server.go:295-296` | 全仓无限流;bcrypt 高成本反而便于 CPU 耗尽 DoS。建议:IP+用户名滑动窗口限流 |
| H5 | SSE 任务流缺幂等前置检查 | `internal/server/sse.go:398-424` | REST 路径有 `FindByIdempotencyKey`,SSE 路径没有;EventSource 断线重连产生重复任务执行 |
| H6 | 事件 dispatcher stale-fencing 无限重放 | `internal/events/worker.go:206-275` | ErrStaleFencing 直接 cancel+return 不计 Failed;handler 半成功被回滚后事件无限重放,永不可达 dead,无告警 |
| H7 | 迁移 00001–00009 缺 down;00012 seed 迁移破坏性 DELETE | `deploy/postgres/goose/` | 前 9 个迁移无 down;00012 无条件 DELETE 30 个 session 的真实消息再插种子;多个迁移事务内 CREATE INDEX(非 CONCURRENTLY)大表会锁表 |
| H8 | compose 弱口令兜底 + main 注册默认开放 | `docker-compose.{dev,test}.yml:17,86,101`;`main.yml:101` | dev/test 的 DB/ADMIN 口令有弱默认值;main 已用 `:?required` 强制但 `AUTH_REGISTRATION_ENABLED` 默认 true。建议 test 对齐 main 必填,main 注册默认 false |
| H9 | 前端 KaTeX 占位符 XSS | `web/src/engine/renderMarkdown.ts:44-64, 106-108` | 数学公式 catch 分支把未转义原文放入占位符数组,还原发生在 escapeHtml 之后 → XSS。建议:catch 分支 escapeHtml(math) + 占位符随机化 |
| H10 | `context.Background()` 脱离请求生命周期 | `internal/chat/session.go:131-134`;`server.go:423,458,566` | LLM 摘要/DB 调用用 Background,客户端断开无法取消,慢库时 handler 挂死。建议:透传请求 ctx + WithTimeout |
## 四、Medium(选录,详见各专项)
| # | 发现 | 位置 |
|---|------|------|
| M1 | 全局缺安全响应头(CSP/nosniff/X-Frame-Options/Referrer-Policy) | `internal/server/server.go:624-636` |
| M2 | 租约 TTL 无上限(可锁文档 1000 天)+ AcquireLease 无编辑权校验 | `handlers.go:1196-1203`;`docgov/lease.go:62-70` |
| M3 | coordinator 关键词命中强制改写意图 + 模板硬编码"张工您好" | `internal/coordinator/engine.go:409-416, 485` |
| M4 | `fmt.Sscanf` 解析 `u_sess_xxx` 必然失败 → UserID=0 审计落空 | `coordinator/engine.go:930-934, 1067-1071` |
| M5 | `Runtime.Start` 被 main 与 Server.Start 双重调用且错误被吞 | `server.go:343-345`;`cmd/server/main.go:47` |
| M6 | sessions map 无硬上限,惰性清理可被随机 session_id 放大 | `server.go:451-453` |
| M7 | 修订三阶段写(账本→DocGov→freeform)无事务,靠客户端重试补偿 | `document_revision_handlers.go:274-318` |
| M8 | 测试 flag 名笔误 `FAV_PUBLISHER_ENABLE`(少 D)门闩失效 | `internal/artifactvault/publisher_gate_test.go:16` |
| M9 | dev compose 声明永不消费的 `SEMANTIC_SUMMARY_REPLACE`(诱导性配置);dev 与 test/main 默认模型不一致(M2.7-highspeed vs M3) | `docker-compose.dev.yml:119,44` |
| M10 | OpsCutover 硬编码 `"dev"`,test/main 无合规 cutover 路径 | `internal/events/cutover.go:12-19` |
| M11 | 前端乐观已读无失败回滚;MessageStream prevMsgCount 跨会话不重置;SSE 无 online 感知重连 | `web/src/hooks/useUnreadMarks.ts:176-233`;`MessageStream.tsx:148-154` |
| M12 | ExcelViewer 无行数上限内存爆炸;React 19 下 30+ 处裸 setTimeout 无清理 | `ExcelViewer.tsx:42-55` |
| M13 | `deploy/postgres/migrations/` 疑似死目录(14 个旧 SQL 无引用,与 goose 重复) | `deploy/postgres/migrations/` |
| M14 | `Orchestrator.ResolveDocTask` 静默返回 0 值三权掩盖数据不一致 | `internal/workflow/runtime/orchestrator.go:69-83` |
| M15 | PG 事件投递允许乱序而 MemoryBus 有 gap 语义——测试替身与生产行为分叉 | `internal/events/dispatcher.go:56-63` vs `bus.go:99-103` |
## 五、Low(选录)
- `handleHealth` 每请求同步两次 DB 往返无缓存无超时(`handlers.go:97-110`)
- `writeStoredEvents` json.Marshal 错误被吞(`task_run_handlers.go:437`)
- `ReplayPlan.Digest()` 不含 DryRun 字段(纵深防御,`internal/events/replay.go:24-38`)
- 前端 localStorage 缓存无版本字段;`lucide-react@^1.16.0` 版本异常需确认来源;App.tsx 4600 行/30 个 useEffect 巨石组件
- `handleRunTaskStream` 死参数 `includeDetails/requestID`(`sse.go:417-418`)
## 六、复核确认无问题的面(证据性记录)
- SQL 注入:全部 pgx 参数化;仅 4 处 fmt.Sprintf 涉 SQL 均为常量
- CORS:白名单制、无 `*`+凭证;SSE 鉴权失败返回 JSON 而非污染流
- 日志:密码 bcrypt、token SHA-256 摘要存储;`httpx.LooksInternal` 过滤内部错误串
- os/exec:bridge 路径来自服务端配置,用户输入只进 stdin payload;无 text/template 引用
- 事件系统:claim 幂等(SKIP LOCKED + fencing 复合判断)、ack+inbox+checkpoint 单事务、envelope 完整性校验、replay 审批人≠操作人——设计正确
- 前端:Mermaid strict 模式、链接 noopener、ErrorBoundary 覆盖根组件、EventSource 卸载清理正确
## 七、优先级建议
1. **进 main 前必须处理**:C1–C4、H1–H5、H8、H9(H8 的 main 注册默认开放一项)
2. **short-term 整改批**:H6、H7、H10、M1、M2、M8(一行修复恢复门闩)
3. **backlog**:其余 medium/low
## 关联整改
- Remediation: 待立项(建议按第七节优先级拆 short-term 任务)
## 证据
- `go vet ./...` 零输出;`go test -short ./...` 55 包 ok(2026-09-19,dev@e8ed33b)
- 五路只读深潜:后端 server/chat、docgov/events/工作流/迁移、前端 web、配置/flag/死代码、安全鉴权
- 任务条目:[ops/short-term/2026-09-19-system-deep-audit.md](../ops/short-term/2026-09-19-system-deep-audit.md)
## 开放问题
- dev 与 test/main 默认模型不一致(M2.7-highspeed vs M3)是否刻意?未见 `.doc/ops` 对齐记录
- `deploy/postgres/migrations/` 是否还有外部工具依赖?无则建议归档
- H1 legacy 兜底是否有仍在使用的内部工具依赖?删除前需盘点
@@ -0,0 +1,48 @@
---
title: "系统权限设置与项目协作多项缺陷排查"
status: done
created: 2026-09-20
updated: 2026-09-20
severity: high
---
# 系统权限设置与项目协作多项缺陷排查
## 现象
用户报告:成员管理勾选无效、系统设置「允许编制人兼任审核批准」400、PDF 预览被拦截、任务 runs 403 刷屏、发起编制被标 NETWORK_ERROR、注册/建号 rollback、改密后刷新再强制改密、退出重登出现同名重复项目、无项目仍可对话、右侧工具栏默认展开且不记忆。
## 根因分析
| # | 根因 | 关键路径 |
|---|------|----------|
| 1 | CSP 缺 `frame-src`,blob iframe fallback 到 `default-src 'self'` | `internal/server/cors.go` |
| 2 | PdfViewer 同源 iframe 直连,触发 `X-Frame-Options: DENY` 原生拦截页 | `web/src/components/doc/preview/renderers/PdfViewer.tsx` |
| 3 | 前端未传 `expected_revision`(该 key 后端强制 CAS) | `web/src/api/systemAdmin.ts` / SettingsSection |
| 4 | `ProjectSettingsApiError` 字段名与消费方 `httpStatus`/`errorCode` 不一致 | `web/src/api/projectSettingsError.ts` |
| 5 | task-run view 仅放行创建者/owner;前端 403 无停止轮询 | `task_run_auth.go` / `App.tsx` |
| 6 | `CanManageProjectMembers` 未读细粒度权限位 | `internal/authz/service.go` |
| 7 | memStore `ListProjectsForUser` 忽略成员表 | `internal/projectworkflow/store.go` |
| 8 | `user_role_bindings` 插入吞错 → commit rollback;handler 一律 400 | `internal/auth/pg_store.go` |
| 9 | 嵌套 `user.mustChangePassword` OR 合并复活 + fetchMe 未回写 session | `authUserMap.ts` / WorkbenchView / useAuthenticatedWorkspaceSync |
| 10 | `projects.name` 无唯一约束 + Create 无幂等键;logout 不清 projects 缓存 | `service.go` / migration 00056 / App logout |
| 11 | `Project()<=0` 时跳过项目访问校验 | `handlers.go` / `sse.go` / `stage_access_helpers.go` |
| 12 | `rightCollapsed` 默认 false 且无持久化 | `AppShell.tsx` / `storage.ts` |
## 严重度
`high`
## 关联整改
- Short-term: `.doc/ops/short-term/2026-09-20-bug-hunt-permissions-uploads.md`
- 分支: `fix/bug-hunt-2026-09-20-permissions-and-uploads`
## 证据
- 产品决策:新增 `project:manage_members`;无项目禁止对话并置灰发送按钮;同创建人内项目名唯一 + `client_key` 幂等。
- 迁移:`00055_...project-manage-members-permission.sql`、`00056_...project-create-idempotency.sql`
## 开放问题
- 无(本批范围内)
+3
View File
@@ -472,3 +472,6 @@ Day 4-5: Phase C 完善与发布准备(20h)
---
*本索引最后更新于 2026-09-12 15:05 UTC*
- 2026-09-17:[系统全面体检](2026-09-17-system-health-check.md)(任务收口 / 缺陷 / 未启用功能;配套 [整改方案](../remediation/2026-09-17-system-health-remediation-plan.md) Wave0–7)。
- 2026-09-17:[首次加载性能诊断与改进](2026-09-17-initial-load-performance-audit.md)(三入口重启首访;U2 已验收,主 JS ~624 KB;U1/U3–U7 待实施)。
+7 -7
View File
@@ -43,7 +43,7 @@ AuthN column is **heuristic**; negative-test pointers filled where known.
| POST | `/api/v1/auth/register` | `s.handleAuthRegister` | `server.go` | handler | see suite |
| GET | `/api/v1/auth/sessions` | `s.handleAuthSessions` | `server.go` | handler | see suite |
| DELETE | `/api/v1/auth/sessions/{id}` | `s.handleAuthSessionByID` | `server.go` | handler | see suite |
| POST | `/api/v1/chat` | `s.handleChat` | `server.go` | session+project | see suite |
| POST | `/api/v1/chat` | `s.handleChat` | `server.go` | session+project (ERR_NO_PROJECT if unbound + zero memberships) | see suite |
| GET | `/api/v1/chat/categories` | `s.handleListChatCategories` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/dates` | `s.handleListChatDates` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/digests` | `s.handleListDailyDigests` | `server.go` | session+project | see suite |
@@ -60,8 +60,8 @@ AuthN column is **heuristic**; negative-test pointers filled where known.
| GET | `/api/v1/chat/search` | `s.handleChatSearch` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/sessions` | `s.handleListChatSessions` | `server.go` | session+project | see suite |
| POST | `/api/v1/chat/sessions` | `s.handleUpsertChatSession` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/stream` | `s.handleChatStream` | `server.go` | session+project | see suite |
| POST | `/api/v1/chat/stream` | `s.handleChatStream` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/stream` | `s.handleChatStream` | `server.go` | session+project (ERR_NO_PROJECT if unbound + zero memberships) | see suite |
| POST | `/api/v1/chat/stream` | `s.handleChatStream` | `server.go` | session+project (ERR_NO_PROJECT if unbound + zero memberships) | see suite |
| GET | `/api/v1/chat/turns/{client_turn_id}` | `s.handleGetChatTurn` | `server.go` | session+project | see suite |
| GET | `/api/v1/chat/unread` | `s.handleChatUnread` | `server.go` | session+project | see suite |
| GET | `/api/v1/context/cases/recommend` | `s.handleRecommendCases` | `server.go` | handler | see suite |
@@ -131,10 +131,10 @@ AuthN column is **heuristic**; negative-test pointers filled where known.
| GET | `/api/v1/tasks/run/stream` | `s.handleRunTaskStream` | `server.go` | session+project | see suite |
| POST | `/api/v1/tasks/run/stream` | `s.handleRunTaskStream` | `server.go` | session+project | see suite |
| POST | `/api/v1/tasks/runs` | `s.handleCreateTaskRun` | `server.go` | session+project | see suite |
| GET | `/api/v1/tasks/runs/{run_id}` | `s.handleGetTaskRun` | `server.go` | session+project | see suite |
| POST | `/api/v1/tasks/runs/{run_id}/cancel` | `s.handleCancelTaskRun` | `server.go` | session+project | see suite |
| GET | `/api/v1/tasks/runs/{run_id}/events` | `s.handleTaskRunEvents` | `server.go` | session+project | see suite |
| POST | `/api/v1/tasks/runs/{run_id}/resume` | `s.handleResumeTaskRun` | `server.go` | session+project | see suite |
| GET | `/api/v1/tasks/runs/{run_id}` | `s.handleGetTaskRun` | `server.go` | session+project member (view) | see suite |
| POST | `/api/v1/tasks/runs/{run_id}/cancel` | `s.handleCancelTaskRun` | `server.go` | session+run owner or project owner | see suite |
| GET | `/api/v1/tasks/runs/{run_id}/events` | `s.handleTaskRunEvents` | `server.go` | session+project member (view) | see suite |
| POST | `/api/v1/tasks/runs/{run_id}/resume` | `s.handleResumeTaskRun` | `server.go` | session+run owner or project owner | see suite |
| GET | `/api/v1/workflow-instances/{id}` | `s.handleGetWorkflowInstance` | `server.go` | session+project | see suite |
| POST | `/api/v1/workflow-instances/{id}/stages/{stage}/advance` | `s.handleAdvanceStage` | `server.go` | session+project | see suite |
| GET | `/api/v1/workflow-instances/{id}/stages/{stage}/readiness` | `s.handleGetStageReadiness` | `server.go` | session+project | see suite |
@@ -0,0 +1,75 @@
# rdev 研发工作流二期增强 Backlog
> 来源:[07-研发工作流rdev接入-设计与实施计划](../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md) §8 决策 3——首期 N/A 采用「激活规划期关闭」,以下增强项不阻塞首期交付,**用户要求记录以便随时续推进**。
> 创建:2026-09-17。每项建议独立 short-term 任务认领。
## 优先级排序(建议)
### R1 N/A 不适用页生成模式(对齐参考项目行为)
- 现状:skippable 任务在激活规划期由创建者关闭 = 不适用;
- 目标:保留任务但可生成「不适用说明页」(完整论述理由而非一句话),仍走审核/批准,再进入下一阶段(参考项目 rdev_software overlay 语义);
- 涉及:manifest 不适用模式标记、bizdev 执行 N/A 生成路径、squad N/A 编排、前端规划 UI「保留但声明不适用」选项;
- 验收:软件类任务声明不适用 → 生成完整不适用页 → 审批通过 → 阶段可推进。
### R2 UR/RS 结构化质量门禁(复用 PM requirements.json 模式)
- **状态**:✅ **done**(2026-09-19)— `rd_user_needs` / `rd_system_reqs` 在 `QualityGate.Validate` 中检查连续编号、禁止随机抽取、验证准则与正文/JSON 一致。`pm` 的 `system_reqs` 仍走原有检查。
- 范围:`rd_user_needs`、`rd_system_reqs`(及 `pm_system_reqs`)输出结构化需求集合;确定性门禁:ID 唯一连续、不随机抽取、缺验证准则拒绝、正文/JSON 不一致拒绝;
- 参考先例:`quality.system_reqs.v2`。
### R3 review_minutes / upload_index 专用确定性门禁
- **状态**:✅ **done**(2026-09-19)— 评审记录拒绝空洞「同意通过」;附件清单要求索引表与影响分析。`TestRDevQualityGates`。
- review_minutes(6 个评审记录):问题-决议-行动项闭环检查(拒绝空洞「同意通过」、行动项无责任人/期限);
- upload_index(7 个附件清单):附件索引表存在性、缺失影响分析存在性检查;禁止伪造附件内容靠 Accept 纪律 + 门禁抽查「待上传后更新」结论。
### R4 depends_on 精确血缘与 stale 传播
- 现状:rd 任务 prior docs 全量注入 + 摘要级血缘;
- 目标:per-task upstream 声明表(对齐参考项目 rdev.yaml depends_on:rd_planning_review ← rd_proposal+rd_design_plan、rd_verification_review ← rd_design_vv+rd_risk_report_v 等),上游新版本批准 → 下游 stale 且不能完成;
- 参考先例:test_manager 对 approved SR 的 stale 传播(projectworkflow/service.go)。
### R5 DMR 双记录归档
- 参考项目 `records: [dhf, dmr]` 的设计输出/转换文档在本仓库无对应物;需评估文档「记录归属」字段扩展 + 归档/导出按 DHF/DMR 分类(本仓库无云盘,先落 docgov 元数据与导出分类)。
### R6 软件工作流任务键 `sw_` 前缀盘点(并入 P4 或其后)
- `software_bootstrap`/`software_delivery`(executor `software.doc.v1`)任务键盘点并纳入统一命名空间规约(D12 的遗留尾巴)。
### R7 高复杂度 regulatory 步注入策略
- 现状:D7 中 regulatory 按任务清单静态注入;目标:接 `complexity_tier`(complexity_high/medium 分层)动态注入,对齐参考项目 `when: complexity_tier=high`。
## 依赖关系
- R2/R3 可并行;R4 依赖 manifest 落地后的 upstream 声明表;R1 独立;R5/R6/R7 低优先级。
---
## 模板深度与运行时续批(S1 续批 / S2 / S3)
> 来源:Kimi 分析方案 + [2026-09-17-rdev-template-depth](../archive/ops/2026-09-17-rdev-template-depth.md) 收口。S0 + S1 首批(14 份)已交付;以下不阻塞本轮合并候选。
### S1 续批 — 剩余模板专业章节
- **状态**:✅ **done**(2026-09-17)— 46 份全部同等深度补强;allowlist 60/60;真 PI `rd_planning_review` + `rd_design_vv` PASS
- **证据**:[测试报告](../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md);[short-term](../ops/short-term/2026-09-17-rdev-template-depth-s1-continued.md)
### S2 — 运行时编排与配置化
- **状态**:✅ **done**(2026-09-19,`fix/audit-remainder-closeout`)
- per-stage 步骤覆盖(相对默认 organize→engineer→draft→review 的阶段差异)
- regulatory 步接 `complexity_tier`(与 R7 可合并认领)
- 模型去硬编码(配置/环境驱动)
- manifest hint + aliases 元数据补齐
- **证据**:`TestRDevRegulatoryFollowsComplexityTier`、`TestRDevModelFromEnv`、`TestRDevStageOverrideAndAliases`
### S3 — overlay 与质量门禁扩面
- **状态**:部分(2026-09-19)。overlay 与 R2/R3 已落地;P3 真 PI 未做
- 轻量 overlay 机制(模板管结构;overlay/运行时管纪律与粒度下限)— done,`configs/overlays/`,`TestRDevWorkspaceWritesOverlay`
- R2/R3 专用确定性门禁落地 — done,`TestRDevQualityGates`
- P3:三样本真 PI E2E 报告 + CI 四工作流门禁挂钩 — 未做
+2 -2
View File
@@ -5,6 +5,6 @@
- **B5** 报价模块接入轻量复核与输入范围校验(`internal/quote/`)
- **A5/A6** 小队工作流支持非关键步骤降级;并行 trace 序号改单次加锁读-算-写(`internal/squad/`)
- **A7** 将中文注释中的已知限制迁移为正式 issue
- **D3** 摘要引擎替换为语义摘要(依赖模型接入,需单独评估)(`internal/ctxmgr/summarizer.go`)
- **D3**(已实现,shadow)摘要引擎语义摘要能力已落地:`SEMANTIC_SUMMARY_SHADOW` 默认 off,见 [FEATURE-MATRIX「语义摘要(D3)」行](../status/FEATURE-MATRIX.md)、[PU6 契约](../ops/long-term/2026-09-16-pu6-semantic-summary-contract.md)(`status: done`)、[W2 真 PI 报告](../test-reports/2026-09-17-w2-semantic-summary-shadow-test-report.md)。`SEMANTIC_SUMMARY_REPLACE` 仍未接线(红线,需独立授权)。本行状态转入 FEATURE-MATRIX 常态跟踪,不再作为独立 backlog 开放项
- **D5** 知识库按环境隔离方案评估(当前三环境共享 KB 为 intentional 架构)
- **D7** 对话数据留存期限与敏感字段加密(先对齐合规再定技术方案)
- **D7** 对话数据留存期限与敏感字段加密——草案 ADR [2026-09-17-d7-chat-data-retention.md](../adr/2026-09-17-d7-chat-data-retention.md)(`compliance: pending-compliance-signoff`);[W7 只读盘点](../audit/2026-09-17-d7-data-inventory.md) 未发现基线违规,见 [报告](../test-reports/2026-09-17-w7-d7-inventory-test-report.md)。签字前禁止按 365/180/30 物理删除;本行继续跟踪合规签字进度
@@ -0,0 +1,22 @@
---
title: "dev 试点:开放编制人兼任总开关"
status: done
created: 2026-09-17
updated: 2026-09-17
---
# dev 试点:开放编制人兼任总开关
## 结论
在运行中的 `agent-dev`(`:8080`,schema 52)经 admin CAS 将 `workflow.allow_author_only_approval` 设为 `true`(revision `0 → 1`)。**未**改默认迁移值;**未**晋升 test/main;test/main 仍保持默认 off。
## 证据(脱敏)
- [before-enable.json](../../test-reports/assets/2026-09-17-author-only-pilot/before-enable.json)
- [put-enable.txt](../../test-reports/assets/2026-09-17-author-only-pilot/put-enable.txt)
- [after-enable.json](../../test-reports/assets/2026-09-17-author-only-pilot/after-enable.json)
## 关联
- author-only 收口:[../handoffs/2026-09-17-document-author-only-closeout.md](../handoffs/2026-09-17-document-author-only-closeout.md)
+43 -10
View File
@@ -1,19 +1,50 @@
# 当前焦点
**更新**: 2026-09-17
**production_ready**: yes(门禁 B1–B4 已签;dev/test `schema_version=48`;main `schema_version=47`;goose 00048 已在 test 迁移。不把 fallback change report 写成完整 PI)
**更新**: 2026-09-20
**production_ready**: yes(门禁 B1–B4 已签;dev/test schema 53,main schema 52。不把 fallback change report 写成完整 PI)
## 焦点
1. **promote null-fk → test**:`rc-v1.0.0-beta.4`(docgov optional-duty FK 修复)
2. **partial/deferred 全量收口**:W1–W4 **done**;W5a **done**(矩阵自举行仍 partial);W6 **shadow done**(矩阵 FAV 仍 partial);W7 **盘点 done**(矩阵 D7 仍 deferred)。已晋升:`rc-v1.0.0-beta.3` → 本轮 `beta.4`
3. **红线**:禁止整支 merge FAV;不默认升 `MULTI_INTENT_PLAN_TIER=full`(升 `confirm` 须 W4 闭环后独立授权);`SEMANTIC_SUMMARY_REPLACE` 不随 W2 开启;FAV live 顺序 staging→artifact→publication、每级观察窗证据驱动(下限 ≥7 天)、`FAV_DEGRADED_READ=false`;flag 默认 off;项目 143 只读
1. **2026-09-20 dev→test 晋升完成 (rc-v1.0.0-beta.5)**:已合入 fix/audit-remainder-closeout,完成全量深度测试(Go 短测 46 包全绿、Vite 前端构建/测试通过、治理 PG 集成通过、运行时端点/安全响应头通过)。已合入 test 分支并重建测试环境服务(端口 :8081,schema 53 healthy)。
2. **2026-09-19 审计整改批 1–4 done**(合入 `844f757` / `08f4e0b` / `a2a49a6` / `d73bc79`)。dev 已 rebuild 到 schema 53。余项见 [long-term](./long-term/2026-09-19-audit-remainder.md)。
3. **Control Center 已移出本仓库**:项目进度由独立统一管理系统承担;本仓库恢复为智能体系统。见 [任务](./short-term/2026-09-19-remove-control-center.md)
4. **rdev 模板深度 / document-author-only**:已合入 `origin/dev` 及 `test`
5. **红线**:禁止整支 merge FAV;不默认升 `MULTI_INTENT_PLAN_TIER=full`;`SEMANTIC_SUMMARY_REPLACE` 不随 W2 开启;FAV live 观察窗证据驱动;`FAV_DEGRADED_READ=false`;项目 143 只读;SWBOOT-10 保持 fail-closed stub;D7 待合规签字
## 并行认领
| owner | task | branch | worktree | mutex | status |
|-------|------|--------|----------|-------|--------|
| Cursor | 2026-09-17-promote-null-fk-to-test | feature/promote-null-fk-to-test | - | infra | in_progress |
| Cursor-Auto | 2026-09-20-bug-hunt-permissions-uploads | fix/bug-hunt-2026-09-20-permissions-and-uploads | - | authz+web+projectworkflow | done |
| Cursor | audit-b1-data-consistency | fix/audit-b1-data-consistency | - | docgov+workflow+chat | done |
| Cursor | audit-b2-authz-hardening | fix/audit-b2-authz-hardening | - | authz | done |
| Cursor | audit-b3-sse-events | fix/audit-b3-sse-events | - | chat+events | done |
| Cursor | audit-b4-frontend | fix/audit-b4-frontend | - | web | done |
| Cursor-Auto | 2026-09-19-audit-remainder-closeout | fix/audit-remainder-closeout | - | audit-remainder | done |
| Antigravity | 2026-09-20-dev-deep-test-and-promotion | feature/dev-deep-test-and-promotion | - | integration | done |
| Cursor-Auto | 2026-09-19-remove-control-center | fix/remove-control-center | - | controlcenter | done |
| Cursor-Auto | 2026-09-17-control-center-server | feature/control-center-server | - | controlcenter | cancelled |
| Kimi | 2026-09-18-user-manual | feature/user-manual | .worktrees/feature-user-manual | docs | done |
| Cursor-Auto | 2026-09-18-wave7-roadmap-orchestration | docs/wave7-roadmap-orchestration | - | roadmap-orchestration | done |
| Cursor-Auto | 2026-09-18-wave6-doc-drift | docs/wave6-doc-drift | - | doc-drift | done |
| Cursor-Auto | 2026-09-18-wave5-deadcode-decisions | fix/wave5-deadcode-decisions | - | deadcode-cleanup | done |
| Cursor-Auto | 2026-09-18-wave4-hardening-r1-r8 | fix/wave4-hardening-r1-r8 | - | hardening | done |
| Cursor-Auto | 2026-09-18-wave3-test-debt-blindspots | fix/wave3-test-debt-blindspots | - | test-debt | done |
| Cursor-Auto | 2026-09-18-wave2-config-flag-align | fix/wave2-config-flag-align | - | infra | done |
| Cursor | 2026-09-18-wave1-main-env-fix | fix/wave1-main-env-fix | - | infra | done |
| Cursor | 2026-09-18-wave0-p0-bug-fixes | fix/wave0-p0-sse-chat-cache-bugs | - | chat + web | done |
| Kimi | 2026-09-17-system-health-check(只读审计,未实施) | - | - | audit | done |
| Cursor | 2026-09-17-docgov-modification-proposal-http | feature/docgov-modification-proposal-http | - | docgov | done |
| Cursor | 2026-09-17-document-author-only-closeout | feature/document-author-only-plan | - | document-duty-policy | done |
| Cursor | 2026-09-17-rdev-template-depth-s1-continued | feature/rdev-template-depth-s1-continued | .worktrees/feature-rdev-template-depth-s1-continued | rdev-templates | done |
| Cursor | 2026-09-17-rdev-workflow-integration | feature/rdev-core | - | workflow-def | done |
| Cursor | 2026-09-17-rdev-template-depth | feature/rdev-template-depth | .worktrees/feature-rdev-template-depth | rdev-templates | done |
| Codex | 2026-09-17-document-author-only-plan | feature/document-author-only-plan | - | document-duty-policy-plan | done |
| Cursor | 2026-09-17-initial-load-perf-u2 | feature/initial-load-perf-u2 | - | web + static-delivery | done |
| Codex | 2026-09-17-initial-load-performance-plan | feature/initial-load-performance-plan | .worktrees/feature-initial-load-performance-plan | loading-performance-audit | done |
| Kimi | 2026-09-17-system-admin-console | feature/system-admin-console | - | web + sysadmin | done |
| Cursor-Auto | 2026-09-17-engineering-dashboard | feature/engineering-dashboard | .worktrees/feature-engineering-dashboard | engineering-dashboard | done |
| Cursor | 2026-09-17-promote-null-fk-to-test | feature/promote-null-fk-to-test | - | infra | done |
| Cursor | 2026-09-17-docgov-optional-duty-null-fk | fix/docgov-optional-duty-null-fk | - | docgov | done |
| Cursor | 2026-09-17-leftover-hygiene | chore/leftover-hygiene-2026-09-17 | - | ops | done |
| Cursor | 2026-09-17-w2-semantic-summary-shadow | feature/w2-semantic-summary-shadow-live | - | chat | done |
@@ -121,7 +152,7 @@
| holder | phase | since | scope | queue |
|--------|-------|-------|-------|-------|
| Cursor | merging | 2026-09-17 | promote null-fk → test (rc-v1.0.0-beta.4) | - |
| - | idle | 2026-09-20 | dev 深度测试全绿;已晋升 test (rc-v1.0.0-beta.5) 并重建测试环境;test 与 dev 均为 schema 53 healthy | - |
**phase**: `idle` | `merging` | `smoke` | `e2e`
@@ -131,9 +162,9 @@
| 环境 | 端口 | schema | 状态 |
|------|------|--------|------|
| dev | 8080 | **48** | healthy(`pi-agent` typed-result-v1;events worker `:8088`;notify/advance/projection live、fav off;health+ready PASS;demo 6001–6010 retired) |
| test | 8081 | **48** | healthy(`rc-v1.0.0-beta.3`;pi-agent `:18866`;events `:8089`;notify/advance/projection live、fav off;health+ready PASS;goose 00048 已迁移) |
| main | 8000 | **47** | healthy(app + events + runner + DB;与 dev/test 对齐) |
| dev | 8080 | **53** | healthy(2026-09-19 `fix/audit-remainder-closeout` rebuild;goose `00053` `document_content_projections`;入口 `index-DOO0-Yh7.js`;`pi-agent`;events `:8088`) |
| test | 8081 | **53** | healthy(2026-09-20 `rc-v1.0.0-beta.5` rebuild;goose `00053`;入口 `index-C5YTF8ik.js`;pi-agent `:18866`;events `:8089`) |
| main | 8000 | **52** | healthy(`env=main` app+events 对齐;events 先 healthy 后启 app;consumer modes 全 off;Wave 1 已验证) |
## SSOT
@@ -144,7 +175,9 @@
| 发布缺口 | [gap-matrix](../remediation/gap-matrix.md)(`production_ready=yes`;Wave 0 IAM 只读未发现旁路) |
| 连续性审计/计划 | [audit](../audit/2026-09-16-feature-matrix-production-readiness-audit.md) · [remediation](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md) · [Wave 0 任务](./short-term/2026-09-16-feature-matrix-wave0-calibration.md) |
| 测试报告 | [test-reports/](../test-reports/) |
| dev→test 晋升前复核 | [research](./research/2026-09-19-pre-test-promotion-review.md)(2026-09-19 只读;静态门禁过,容器未 rebuild,暂不合并) |
| D7 盘点(W7) | [audit](../audit/2026-09-17-d7-data-inventory.md) · [报告](../test-reports/2026-09-17-w7-d7-inventory-test-report.md) · ADR 仍 `pending-compliance-signoff` |
| Wave 7 编排确认 | [决策记录](./short-term/2026-09-18-wave7-roadmap-orchestration.md) |
| Agent 手册 | [AGENTS.md](../../AGENTS.md) |
| 意图双标签 busy 交接 | [./handoffs/2026-09-15-conversation-intent-dual-tab.md](./handoffs/2026-09-15-conversation-intent-dual-tab.md) |
| 受控正文 hash 漂移 W1–W6 | [../ops/handoffs/2026-09-14-controlled-content-canonical-hash.md](../ops/handoffs/2026-09-14-controlled-content-canonical-hash.md) |
@@ -65,3 +65,13 @@ curl -sf http://127.0.0.1:8080/ready
- CURRENT: [CURRENT.md](../CURRENT.md)
- Task: [../short-term/2026-09-13-conversation-intent-runtime-state.md](../short-term/2026-09-13-conversation-intent-runtime-state.md)
- Test report: [../../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md](../../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)
## 回标(2026-09-18,Wave 6 文档漂移修复)
上方「未完成」与「认领 / 槽位状态」两节是 2026-09-15 交接时刻的快照,**已在同一提交(`8a8f64a`)内被后续证据覆盖**:
- 浏览器双标签刷新恢复 / busy 租约可见性:项目 6275、`sess-p6275-u10` 真实 PI + Docker 截图(`dual-tab-live.py`、`live.json`、`window-before-refresh.json`、`window-after-refresh.json`、`screenshots/tab-b-after-reload.png` 等,均在同一提交归档)。
- `CHAT-INTENT-STATE` 已在 [gap-matrix](../../remediation/gap-matrix.md) 标记 **PASS**(「双标签活验项目 6275 / `sess-p6275-u10`」)。
- mutex 已释放:CURRENT.md 当前无该任务 `in_progress` 行;集成槽位 holder 为 `idle`。
**结论**:本 handoff 无待办事项,`status: closed` 生效,仅为历史记录保留原文,不删除。
@@ -0,0 +1,40 @@
---
title: "document-author-only U1–U6 收口交接"
status: done
created: 2026-09-17
updated: 2026-09-17
from: Cursor
to: integrator
---
# document-author-only U1–U6 收口交接
## 结论
实现与验收任务已全部收口:U1–U6 short-term 已迁入 `archive/ops/`;FEATURE-MATRIX / remediation DoD(除发布末条)已更新;U6 报告已归档。
**远端**:已 `git-push-dev.sh` 推送 `origin/dev`(含 author-only merge);**未**晋升 test/main。
**dev 试点**:`workflow.allow_author_only_approval=true`(revision 1);证据见 [pilot assets](../../test-reports/assets/2026-09-17-author-only-pilot/) 与 [ops 笔记](../2026-09-17-author-only-pilot-toggle.md)。
## 分支
- `feature/document-author-only-plan` — 已合入并清理 worktree/本地分支
- 续作:`feature/docgov-modification-proposal-http`(变更提案 HTTP)
## 合入 `dev`(已完成)
- `merge --no-ff feature/document-author-only-plan` → 后续推送至 `origin/dev@ba92a8b` 一带
- 冒烟:`go vet` / `go test -short` 相关包 PASS;`./scripts/env-service.sh dev rebuild`;`GET /health` → `schema_version=52`、`status=ok`
- 总开关默认迁移值仍为 off;**dev 运行态**已 CAS 试点开启;**未**晋升 test/main
## 明确不在本期(已转入续作)
- ~~变更提案 HTTP 路由~~ → [short-term](../short-term/2026-09-17-docgov-modification-proposal-http.md) / [audit resolved](../../audit/2026-09-17-docgov-modification-proposal-http-gap.md)
- test/main 晋升仍另授
## 证据
- [U6 报告](../../test-reports/2026-09-17-document-author-only-u6-test-report.md)
- [方案 DoD](../../remediation/2026-09-17-document-author-only-plan.md)
- [pilot](../../test-reports/assets/2026-09-17-author-only-pilot/)
@@ -63,6 +63,8 @@ L1(SWBOOT-00…09 契约/迁移/目录钩子 + SWBOOT-10 stub)**已合入 `d
L1 已合 `dev`。W5a 从 `dev` 开 `feature/w5a-software-bootstrap-ui-pi`(mutex `workflow-design`)。W5b 受控执行器未启动,SWBOOT-10 保持 fail-closed stub。
**Wave 5 X-3(2026-09-18)**:goose 00048 三表(`project_types` / `compliance_profiles` / `project_type_workflows`;另含零读者的 `project_source_bindings` / `repo_path_allowlist`)消费方接线评估结论 = **deferred → SWBOOT-10/W5b**。不改 schema;API 继续硬编码目录。决策落点:[wave5-deadcode-decisions.md#x-3](../short-term/2026-09-18-wave5-deadcode-decisions.md#x-3)。不阻塞 W5b 立项。
## 相关链接
- [详细设计](../../system-design/2026-09-14-software-project-bootstrap-workflow.md)
@@ -1,8 +1,8 @@
---
title: "PU8-U10 mutate — 获批后任务契约"
status: in_progress
status: done
created: 2026-09-16
updated: 2026-09-17
updated: 2026-09-18
owner: Cursor
branch: feature/w4-u9-segment-live
mutex: intent-plan
@@ -1,8 +1,8 @@
---
title: "PU8-U11 docgov action — 获批后任务契约"
status: in_progress
status: done
created: 2026-09-16
updated: 2026-09-17
updated: 2026-09-18
owner: Cursor
branch: feature/w4-u9-segment-live
mutex: intent-plan
@@ -1,8 +1,8 @@
---
title: "PU8-U12 workflow/run-control — 获批后任务契约"
status: in_progress
status: done
created: 2026-09-16
updated: 2026-09-17
updated: 2026-09-18
owner: Cursor
branch: feature/w4-u9-segment-live
mutex: intent-plan
@@ -1,8 +1,8 @@
---
title: "PU8-U9 segment proposal — 获批后任务契约"
status: in_progress
status: done
created: 2026-09-16
updated: 2026-09-17
updated: 2026-09-18
owner: Cursor
branch: feature/w4-u9-segment-live
mutex: intent-plan
@@ -0,0 +1,85 @@
---
title: "2026-09-19 审计剩余项(medium/low,不挡已合入批 1–4)"
status: planned
created: 2026-09-19
updated: 2026-09-19
---
# 2026-09-19 审计剩余项
## 动机
[系统深度体检](../../audit/2026-09-19-system-deep-audit.md) 的 C1–C4 与 H1–H10 已按四批合入 `dev`。下列 medium/low 仍真实存在,但不进入本轮发布回退。
## 成功标准
- 每条有独立 short-term、负例测试或明确关闭理由后再标 done
- 不把本清单自动写成 gap-matrix blocker
## 依赖
- 批 1–4 已在 `dev`:`844f757`、`08f4e0b`、`a2a49a6`、`d73bc79`
## 暂不启动原因
本轮范围只到 critical + high。下列项要么是加固、要么需要产品/合规决策,要么改动面大于收益。
## 进展(2026-09-19,`fix/audit-remainder-closeout`)
| ID | 结果 |
|----|------|
| M1 | done。`nosniff` / `DENY` / `Referrer-Policy` / 本站 CSP。`TestP0_SecurityHeaders` |
| M2 | done。TTL 钳到人工 15 分钟、小队 30 分钟;人工租约前 `CheckHumanCanEdit`。`TestAcquireLeaseClampsHumanTTL` |
| M3 | done(本项可落地部分)。低置信度才做关键词改道;称呼取用户名。高置信度意图层改造不在本项把模板整段搬走 |
| M4 | done。`parseDecimalID` 拒绝 `u_sess_*`。`TestParseDecimalIDRejectsSessionTokens` |
| M5 | done。`Server.Start` 不再二次启动并吞错。`main` 仍调用 `Runtime.Start`,该方法本身已幂等 |
| M6 | done(上限)。硬上限 4096,淘汰最久未访问。会话 id 仍由客户端提供,因为历史恢复按该 id 查找;改成只接受服务端签发会打断现有对话协议 |
| M9 | done。dev compose 不再声明 `SEMANTIC_SUMMARY_REPLACE`。dev=`MiniMax-M2.7-highspeed`、test/main=`MiniMax-M3` 确认为有意分叉,已写在 compose 注释 |
| M10 | done(写明路径,不放开门闩)。`OpsCutoverPromotionPath`:dev 观察后用晋升回执写 test,再写 main。`ValidateOpsCutover` 仍拒绝 test/main |
| M13 | done。SQL 迁到 `deploy/postgres/archive/pre-goose/`。代码与脚本无引用 |
| M14 | done。冻结计划找不到职责行则报错;显式空三权仍为 0。`TestResolveDocTask_NoneDutiesStayZero` |
| L1 | done。健康检查 2 秒缓存 + 2 秒 DB 超时 |
| L2 | done。SSE marshal 失败写 `event: error` 帧 |
| L3 | done。`ReplayPlan.Digest` 含 `DryRun`;dry-run 摘要不能授权 apply |
| M15 | done。生产 `claimSQL` 与 `MemoryBus` 共用 `VersionClaimable`:版本 0 可领,版本化事件不能跳过 checkpoint。checkpoint 只前进。`TestVersionClaimableMatchesMemoryBusGap`、`TestGapDoesNotSkipVersion` |
| H3 负例 | done。`TestListChatSessions_CrossUserIs403` |
| FE 缓存 | done(版本字段)。窗口缓存写入 `{schema,data}`,无 schema 的旧载荷丢弃。`window cache: 无 schema` |
| FE lucide | 关闭理由:`package-lock.json` 锁定 `lucide-react@1.42.0`,来源 `registry.npmjs.org`,带 integrity。`^1.16.0` 是合法的 1.x 范围,不是来源不明的包 |
| M7 | done(出站意图 + 同键重放)。`document_content_projections` 与账本同一事务写入;投影成功才销账。`TestDocRevision_PatchOrder_RetryProjectsWithoutSecondLedgerCommit`。账本库与正文库仍不是一个 SQL 事务,进程退出后靠未投影行重放,不靠客户端记忆 |
| FE App.tsx | 部分收口。登录壳不再静态引用重模块。本地缓存、登录同步、文档补水、服务端文档同步、生命周期、发送消息、块编辑、对话流/任务流重试、卡片动作、立项和成员写操作已分别抽出。文档栏在 `DocumentPane`,聊天栏在 `ChatColumn`,`AppShell` 与工作台弹窗在 `WorkbenchView`。`App.tsx` 仍持有会话状态,不再挂 `<AppShell` |
| H1-del | 关闭理由:`allowLegacyTestPrincipal` 仍被 `AllowInMemory && ContextDbHost==""` 的 dev/test 内存测试使用。删除会把这批测试变成未登录 401。保留告警,删除另开、先改测试夹具 |
仍开放:`rd_proposal` 终稿未对齐模板标题(没有新的真 PI)。U7 登录表单可见未测(本机无头 Chromium 缺 `libatk`),也不把 1.4 秒模块图写成「较十几秒基线下降 50%」。见 [U7 报告](../test-reports/2026-09-19-initial-load-u7-restart-test-report.md)。工作台壳已挪到 `WorkbenchView`。dev schema 53。U6 仍不加索引。`TestArchitectureBoundaries` 仍有 6 条新 import(intent/squad/template → workflowdef),不是本轮容器改动。test/main 仍是 schema 52。评审门禁的法规表误伤已修,保存的 P3 终稿不再报「问题行缺少」。
红线关闭(不是实现):
- SWBOOT-10:保持 fail-closed stub。未获独立授权前不接真实仓库写入。
- FAV live:禁止整支 merge;`FAV_DEGRADED_READ=false`;live 需要各阶段至少 7 天观察窗,本轮不放量。
- D7:合规签字前禁止按留存口径物理删除。盘点已完成,口径仍 `pending-compliance-signoff`。
## 清单
| ID | 项 | 位置 | 说明 |
|----|----|------|------|
| M1 | 安全响应头 | `internal/server/server.go` CORS 中间件 | 补 `nosniff` / `X-Frame-Options` / `Referrer-Policy` / 收敛 CSP |
| M2 | 租约 TTL 无上限 | `handlers.go` AcquireLease | clamp 到 `DefaultHumanLeaseTTL`,Acquire 前校验编辑权 |
| M3 | 关键词改写意图 + 硬编码「张工」 | `internal/coordinator/engine.go` | 移到意图层并加置信度;称呼取用户名 |
| M4 | `fmt.Sscanf` 解析 `u_sess_*` 得到 UserID=0 | 同上 | 统一数字 ID |
| M5 | `Runtime.Start` 双调用且吞错 | `cmd/server/main.go` 与 `server.go` | `sync.Once` 或删 Server.Start 内调用 |
| M6 | sessions 无硬上限 | `server.go` cleanStaleSessionsLocked | LRU + 服务端发 session id |
| M7 | 修订三阶段写无事务 | `document_revision_handlers.go` | 已落地:`00053` 投影意图与账本同事务;成功后销账。见进展表 |
| M9 | `SEMANTIC_SUMMARY_REPLACE` 只在 dev compose 声明;dev/test 默认模型不一致 | compose | 删未接线 flag 并钉死测试;确认 M3 是否刻意 |
| M10 | cutover 只允许 `dev` | `internal/events/cutover.go` | 写明 test/main 切换路径 |
| M13 | `deploy/postgres/migrations/` 死目录 | 与 goose 重复 | 确认无外部依赖后归档 |
| M14 | ResolveDocTask 静默 0 值三权 | `orchestrator.go` | 找不到 duties 应报错 |
| M15 | PG 投递允许乱序,MemoryBus 有 gap | `dispatcher.go` vs `bus.go` | 对齐测试替身与生产顺序语义 |
| L1 | health 每次打两次 DB | `handlers.go` | 短缓存 + 超时 |
| L2 | SSE marshal 错误被吞 | `task_run_handlers.go` | 失败写 error 帧 |
| L3 | ReplayPlan digest 不含 DryRun | `replay.go` | 纳入 digest |
| H1-del | 删除 legacy user-id=1 兜底 | `auth_middleware.go` | 已加日志;删除前盘点调用方 |
| FE | App.tsx 巨石、localStorage 无版本、lucide 版本确认 | `web/` | 拆 hook;缓存加 version;确认包来源 |
## 相关链接
- 审计:[../../audit/2026-09-19-system-deep-audit.md](../../audit/2026-09-19-system-deep-audit.md)
- 批 1–3 报告:`.doc/test-reports/2026-09-19-audit-b*.md`
@@ -0,0 +1,93 @@
---
title: "参考项目 weichen-agent-system 研发工作流(rdev)文档关系与阶段组成梳理"
created: 2026-09-17
status: done
confidence: high
---
# 调研:参考项目 weichen-agent-system 研发工作流(rdev)文档关系与阶段组成梳理
## 结论
参考项目 `.refs/weichen-agent-system` 中的「研发流程」(`key: rdev`)是与商务对接(bizdev)、测试经理(test_manager)、产品经理(product_manager)并列的第 4 个工作流,`kind: followon`、`after: bizdev`:商务对接末阶段 CDO 报价批准后才可启动。rdev 共 **60 个阶段(文档任务)**,按 **13 个 phase(01–13)** 组织成 ISO 13485 设计控制链(策划 → 输入 → 输出 → 验证 → 转换 → 确认),每阶段恰好对应 `templates/docs/<stage_key>.md` 一份自描述模板,并有 overlays(工作流级 `rdev.md` + 阶段簇 `rdev_phNN.md` + 文档类型 `kind_*.md`)与 `configs/squads/rdev.yaml` 五步小队编排三层配套。
## 证据
| 项 | 路径/命令 | 结果 |
|----|-----------|------|
| 工作流定义 | `.refs/weichen-agent-system/configs/workflows/rdev.yaml` | 1473 行;`key: rdev` `kind: followon` `after: bizdev`;60 个 stage |
| 阶段齐套校验 | `.refs/weichen-agent-system/scripts/e2e-rdev.sh` | 脚本内置断言 `want 60 rdev stages`,逐 stage 校验 `templates/docs/<key>.md` 存在且非空,末模板须含「签署」 |
| 小队编排 | `.refs/weichen-agent-system/configs/squads/rdev.yaml` | `default_steps`:organizer → engineer(+regulatory 可选并行)→ writer → leader;关键 stage 覆盖专属 steps |
| 任务叠加 | `.refs/weichen-agent-system/configs/overlays/rdev.md`、`rdev_ph01…ph13.md`、`rdev_software.md`、`kind_review_minutes.md`、`kind_upload_index.md`、`kind_design_record.md` | 工作流级 / 阶段簇 / 文档类型三层叠加,`### role:` 按专员过滤 |
| 研发负责人人设 | `.refs/weichen-agent-system/configs/agents/rdev_leader.md` | 「研发/设计控制小队负责人…按 ISO 13485 把本阶段做成可追溯的 DHF 记录」 |
| 插件 | `.refs/weichen-agent-system/plugins/rdev/plugin.go` | 不注册生成意图,启动走生命周期 `start_workflow`(说法「启动研发流程」) |
| 官方说明 | `.refs/weichen-agent-system/docs/workflows.md` §研发流程、`docs/handoff.md` §研发流程(followon) | 约 60 阶段、每阶段一份 Word(RD-…)、不适用须完整理由并仍走审核/批准 |
| Canonical 归档 | `docs/cloud-drive.md` | `archive/dhf/{NN-阶段名}/{nn-产出}`;`records` 含 `dmr` 且已批准再拷 `archive/dmr/` |
## 研发工作流的文档关系(五层结构)
```text
configs/workflows/rdev.yaml ← 阶段 SSOT:key/标题/phase/records/artifact_kind/docx 元数据/fields/depends_on/skippable
│ 一一对应(stage key = 模板文件名)
▼
templates/docs/<stage_key>.md ← 自描述模板:文件编号 RD-…、记录归属 DHF(/DMR)、阶段 NN、
│ 结论/适用性/正文/追溯表/材料摘要/待确认清单/签署 固定骨架
▼
configs/squads/rdev.yaml ← 小队编排:default_steps + 个别 stage 覆盖(五步编制流水线)
▼
configs/overlays/*.md ← 任务叠加(注入 TASK 的阶段级撰写指导,多层):
① rdev.md(工作流级全员质量红线)
② rdev_phNN.md(阶段簇,ph01–ph13)
③ kind_review_minutes / kind_upload_index / kind_design_record(文档类型)
④ rdev_software.md(软件类阶段专项)+ 个别 stage 特例 overlay
▼
plugins/rdev/plugin.go ← 运行时入口:启动走生命周期 start_workflow(followon 门禁),
不注册生成意图;启动时从 bizdev 拷贝已填字段(产品类型/预期用途/目标市场等)
```
- **模板即文档**:每份模板头部自带「文件编号 / 记录归属 / 版本 / 阶段」元数据,与 rdev.yaml 中 stage 的 `docx.code`(RD-…)和 `phase` 一致;`scripts/e2e-rdev.sh` 强制校验 60 个 key 与模板一一对应。
- **记录归属双轨**:`records: [dhf]`(设计历史文件)为主;设计输出/转换类文档 `records: [dhf, dmr]`(同时属器械主记录),批准后额外拷贝到 `archive/dmr/`。
- **追溯链**:每份模板含固定「追溯」表(本文件 ID ↔ 上游输入 ↔ 下游验证/确认),需求类要求 UR→RS 追溯主表(见 `kind_design_record.md`)。
- **评审依赖**:评审记录类 stage 用 `depends_on` 显式声明上游(如 `verification_review` depends_on `design_vv`、`risk_report_v`)。
- **不适用机制**:每 stage 都有 `applicability` / `na_rationale` 字段;软件类/动物试验/临床等 15 个 stage 标 `skippable: true` + `skip_hint`,不适用仍须生成完整不适用页并走审核/批准。
## 工作流阶段组成(13 个 phase / 60 个 stage)
| Phase | 阶段簇 overlay | Stage(key → 文档) | 数量 |
|-------|--------|--------------------|------|
| 01 策划 | rdev_ph01 | `proposal` 项目建议书、`design_plan` 设计开发计划任务书 | 2 |
| 02 策划评审 | rdev_ph02 | `planning_review` 策划评审记录(depends: proposal, design_plan) | 1 |
| 03 设计输入 | rdev_ph03 | `user_needs` 用户需求规格书(UN)、`regs_stds` 法规和标准清单、`adverse_events` 同类产品不良事件、`system_reqs` 系统需求规格书(SR)、`risk_plan` 风险管理计划、`hazard_analysis` 危险分析、`sw_plan`*/`sw_reqs`*/`sw_config`* 软件三件套、`design_input_spec` 设计输入规格书、`design_input_list` 设计输入清单、`system_design` 系统设计方案 | 12 |
| 04 需求评审 | — | `req_review` 需求评审记录(depends: user_needs, system_reqs) | 1 |
| 05 输入阶段评审 | — | `input_phase_review` 阶段3和4评审记录(depends: design_input_spec/list, req_review) | 1 |
| 06 设计输出 | rdev_ph06 | `drawings_3d` 图纸3D、`product_bom` BOM、`ee_bom`*/`pcba`*/`electrical_sys`* 电气三件套、`sw_arch`*/`sw_ui`* 软件、`purchase_spec` 采购规范、`process_flow` 工艺流程、`packaging` 包装、`ifu` 说明书、`incoming_iqc`/`ipqc`/`fqc` 三级检验、`tech_req` 产品技术要求、`risk_report` 风险管理报告、`design_output_list` 设计输出清单 | 17 |
| 07 输出评审 | — | `output_review` 阶段6评审(depends: design_output_list) | 1 |
| 08 验证 | rdev_ph08 | `prototype_photos` 样机照片、`design_vv` 设计验证方案、`shelf_life` 货架寿命、`lifetime` 使用期限、`biocompatibility` 生物学、`cleaning` 清洁消毒、`emc_safety`* EMC安规、`risk_report_v` 验证风险报告、`sw_release`*/`sw_unit_test`*/`sw_sys_test`* 软件三件套、`qualified_suppliers` 合格供方 | 12 |
| 09 验证评审 | — | `verification_review`(depends: design_vv, risk_report_v) | 1 |
| 10 转换 | — | `dmr_list` DMR文件清单、`pack_ship` 包装运输、`risk_report_t` 转换风险报告 | 3 |
| 11 转换评审 | — | `transfer_review`(depends: dmr_list, pack_ship, risk_report_t) | 1 |
| 12 确认 | — | `validation_plan` 设计确认方案、`use_error` 使用错误、`animal_study`* 动物试验、`sw_quality`* 软件质量、`clinical`* 临床试验报告、`risk_report_val` 确认风险报告、`user_test` 用户测试 | 7 |
| 13 设计确认报告 | — | `design_validation_report` 设计确认报告(末阶段,批准后项目 done) | 1 |
合计 60,与 `e2e-rdev.sh` 的 `want 60 rdev stages` 断言一致。(`*` = `skippable: true`,实测 grep 共 15 个:软件 9 个(sw_plan/sw_reqs/sw_config/sw_arch/sw_ui/sw_release/sw_unit_test/sw_sys_test/sw_quality)+ 电气 3 个(ee_bom/pcba/electrical_sys)+ emc_safety + animal_study + clinical)
**artifact_kind 三类**(grep 实测):`document`(常规成文,47 个)、`review_minutes`(评审记录,6 个)、`upload_index`(附件清单/上传索引,7 个,只建索引不伪造内容)。各 kind 有独立 overlay 质量要求。
## 小队与治理机制
- **小队编制**:复用整理(organizer)/技术(engineer)/撰写(writer)/法规(regulatory)/检索(searcher)专员,种子化「研发流程负责人」(rdev_leader);市场与财务不进研发小队。
- **默认五步**:organizer(抽材料事实+回填字段+blackboard facts/gaps/implications)→ engineer(技术内容与追溯,可并行)→ regulatory(仅 complexity_tier=high,可选并行)→ writer(按模板成稿)→ leader(二审完整性/粒度/不适用理由/有无编造,不达标退回)。
- **门禁**:启动前必须 bizdev CDO 已批准(e2e 脚本专门验证「CDO 前启动应被拒绝」);启动时从商务对接拷贝产品类型/预期用途/目标市场等字段。
- **状态机**:与 bizdev 同一套编制/审核/批准 FSM;末阶段批准后项目标 `done`。
## 开放问题
- 本仓库(Agent-System)当前尚无 rdev 工作流模块;若要移植,需评估 60 stage × 模板 × overlay × 小队步骤的落地范围与分期(bizdev 已有移植先例)。
- 参考项目 `records: [dhf, dmr]` 双归属与云盘 canonical 归档机制在本仓库尚无对应物,移植时需决策是否引入。
- `complexity_tier=high` 才注入 regulatory 步;本仓库复杂度分层(complexity_high/medium overlay)如何对齐需另调研。
## 建议动作
- 若立项移植 rdev:在 `ops/short-term/` 新建任务,按「工作流定义 → 模板 → 小队 → overlays → 生命周期门禁」顺序分批实施,先做 phase 01–03(策划/输入)切片。
- 移植时保留「stage key = 模板文件名」一一对应约束,并复刻 e2e 齐套校验(60 stage、模板非空、末模板含签署)。
@@ -0,0 +1,151 @@
---
title: "dev→test 晋升前复核:功能权限、合并可行性、已知缺陷"
created: 2026-09-19
updated: 2026-09-19
status: done
confidence: high
---
# 调研:dev→test 晋升前复核
只读复核。不改业务代码、不 rebuild 容器、不合入 `test`/`main`、不修复 [medium/low backlog](../long-term/2026-09-19-audit-remainder.md)。
## 结论
1. **规划内的功能、权限与流程已按声明范围接入。** [FEATURE-MATRIX](../../status/FEATURE-MATRIX.md) 主表里,除明确标成 `partial` / `deferred` 的行以外,其余能力均为 `done`,并有测试报告或 commit 证据。没有发现「规划了但完全未实现」的模块。未完成项是主动延后,且 [gap-matrix](../../remediation/gap-matrix.md) 已判定不挡首发。
2. **`dev` 的静态质量达标,但现在不建议直接合并入 `test`。** `go vet` 与 `go test -short` 全绿,2026-09-19 深度审计的 critical/high 已合入 `dev`。合并前仍缺三件事:dev 容器 rebuild 冒烟、治理 PG 集成与前端构建、批 2 越权负例的自动化覆盖。
3. **critical/high 已关闭;medium/low 仍在,且本轮不修。** 新发现的观察项是文档漂移和 `test` 分支上 9 个晋升提交,不是新的代码缺陷。
## 一、功能、权限、流程
对照 [FEATURE-MATRIX](../../status/FEATURE-MATRIX.md)(更新 2026-09-19)与 [gap-matrix](../../remediation/gap-matrix.md)(`production_ready=yes`,门禁 B1–B4 已签)。
### 已关闭(声明范围内 `done`)
| 能力 | 接入情况 |
|------|----------|
| 意图识别 L1、多意图 U1–U8、多意图扩面 U9–U12 | 代码与报告齐全;`MULTI_INTENT_PLAN_TIER` 仍为 `legacy`,未默认升 `confirm`/`full` |
| 对话 / ctxmgr、语义摘要 D3、PI change-report 叙事 | 刷新恢复门禁已签;摘要与叙事 flag 默认 off,REPLACE 未启用 |
| 工作流治理 | 三正式工作流、动作级鉴权、真实 PI E2E |
| 文档治理、文档版本 baseline | 法定生命周期、租约、受控正文、运行时 UI |
| IAM / 鉴权 | 项目级 API + RBAC;路由清单见 [authorization-matrix-v3](../../audit/authorization-matrix-v3-full.md) |
| 前端工作台、PI Runner、三环境运维、CI/E2E、Artifact 同 digest、可靠事件核心、系统管理台 | 各自行有报告;系统管理台二期(Playwright、细粒度 `system:*`、设置审计)不在本行关闭条件内 |
| 文档编制人兼任(U1–U6) | 已合入 `dev`;总开关默认 off |
2026-09-19 审计批 2 已把鉴权缺口接到主链:H1 给 dev/test legacy 兜底加了告警(未删除兜底)、H2 批注/认领 actor 取 principal 且读类端点校验项目成员、H3 会话查询跨用户 403、H4 登录限流、H8 compose 口令改为必填。证据:[批 2 报告](../../test-reports/2026-09-19-audit-b2-authz-hardening-test-report.md)。
### 明确未完成(不是遗漏)
| 行 | 状态 | 剩余 | 是否挡首发 |
|----|------|------|------------|
| 研发设计控制(rdev) | partial | S2/S3、P2 前端、P3 三样本 E2E、P4 键名空间化 | 否 |
| 纯软件项目自举 | partial | SWBOOT-10 仍 fail-closed stub | 否 |
| Final Artifact Vault | partial | live 未放量;禁止整支 merge;`FAV_DEGRADED_READ=false` | 否 |
| 对话数据治理(D7) | deferred | `pending-compliance-signoff`;禁止按口径物理删除 | 否(违规则才升 blocker) |
| 首次加载性能 | partial(矩阵外专项) | U2 已验收;U1/U3–U7 未做 | 否 |
红线与代码/compose 对齐(深度审计已核实,本轮未再改 flag):`MULTI_INTENT_PLAN_TIER=legacy`、`SEMANTIC_SUMMARY_REPLACE` 未接线、`FAV_DEGRADED_READ=false`、SWBOOT-10 fail-closed stub、项目 143 只读。
## 二、`dev` 能否合入 `test`
**判断:静态门禁通过,运行态与回归门禁未补齐,暂不合并。**
### 已满足
- `dev` 工作树在复核时干净;`dev` HEAD 为 `66421b1`(含审计批 1–4:`844f757`、`08f4e0b`、`a2a49a6`、`d73bc79`)。
- `go vet ./...` 零告警。
- `go test -short ./...` 全包 PASS(`internal/server` 本轮实测约 14s,非缓存)。
- 三环境 `GET /api/v1/health` 均为 `status=ok`、`schema_version=52`、`schema_ready=true`。goose 最新文件为 `00052`。迁移版本本身不阻塞晋升。
- `internal/`、`cmd/` 生产代码中无 `TODO`/`FIXME`/`XXX`。
### 合并前必须处理
1. **dev 容器仍是旧二进制。** 批 1–3 报告写明未执行 `./scripts/env-service.sh dev rebuild`。`:8080` 健康只证明旧镜像在跑,不能证明审计修复已部署。按 [AGENTS.md](../../../AGENTS.md) §6.3,合入共享环境前要占集成槽位并冒烟。
2. **`dev` 领先 `test` 225 个 commit。** 差异覆盖 rdev 模板、系统管理台、docgov 加固、Control Center 移除等。`-short` 不够。晋升前至少再跑:`TEST_DATABASE_URL` 下治理 PG 集成,以及 `cd web && npm test && npm run build`。
3. **批 2 的越权负例仍是人工兜底。** [批 2 报告](../../test-reports/2026-09-19-audit-b2-authz-hardening-test-report.md) 写明:非项目成员访问 docgov 应 403 的 HTTP/Playwright 负例未补,目前靠既有鉴权测试不回退加 code review。
### `test` 上多出来的 9 个提交
`git rev-list --count dev..test` = 9。这些提交是历次 `release-candidate` / 晋升文档同步(含 `rc-v1.0.0-beta.2` 至 `beta.4`),不是 `dev` 上缺失的产品代码。下次晋升应把 `dev` **merge 进** `test`,不要把 `test` reset 到 `dev`,否则这 9 个提交的晋升记录会丢。
`CURRENT.md` 文首仍写 test `schema_version=48`,同文「环境快照」表与本次 health 实测已是 52。这是文档漂移,不是运行时缺陷。更正留给下次晋升文档,本笔记不改那一行。
## 三、缺陷
### 已修复(2026-09-19 深度审计 critical/high)
来源:[系统深度体检](../../audit/2026-09-19-system-deep-audit.md)。四批均已合入 `dev`。
| 批 | 项 | merge |
|----|----|-------|
| 1 数据一致性 | C1 docgov 吞错与 fencing 读回;C2 Session 竞态与跨项目污染;C4 计划保存事务与 `completed_by`;H10 请求 ctx | `844f757` |
| 2 鉴权 | H1–H4、H8、M8 | `08f4e0b` |
| 3 SSE/事件 | C3 心跳与写超时;H5 任务 SSE 幂等;H6 stale fencing 日志;H7 迁移注释(历史 SQL 不能补 down) | `a2a49a6` |
| 4 前端 | H9 占位符 XSS;未读回滚;Excel 预览上限 | `d73bc79` |
H1 的 legacy user-id=1 兜底只加了日志,删除仍在 backlog(`H1-del`)。H7 的 00001–00009 无 down 不能改已应用文件,只加了注释。
### 已知未修(维持 backlog,本轮不启动)
清单 SSOT:[2026-09-19-audit-remainder.md](../long-term/2026-09-19-audit-remainder.md)。均为 medium/low,不回写 gap-matrix。
| ID | 项 |
|----|----|
| M1 | 缺 `nosniff` / `X-Frame-Options` / `Referrer-Policy`,CSP 未收敛 |
| M2 | 租约 TTL 无上限;Acquire 前未校验编辑权 |
| M3 | 关键词改写意图;硬编码「张工」 |
| M4 | `u_sess_*` 解析失败得到 UserID=0 |
| M5 | `Runtime.Start` 双调用且吞错 |
| M6 | sessions 无硬上限 |
| M7 | 修订三阶段写无事务 |
| M9 | `SEMANTIC_SUMMARY_REPLACE` 只在 dev compose 声明;dev/test 默认模型不一致 |
| M10 | cutover 只允许 `dev` |
| M13 | `deploy/postgres/migrations/` 与 goose 重复 |
| M14 | ResolveDocTask 静默 0 值三权 |
| M15 | PG 投递允许乱序,MemoryBus 有 gap |
| L1 | health 每次两次 DB |
| L2 | SSE marshal 错误被吞 |
| L3 | ReplayPlan digest 不含 DryRun |
| H1-del | 删除 legacy user-id=1 兜底前须盘点调用方 |
| FE | `App.tsx` 巨石、localStorage 无版本、lucide 来源待确认 |
M8(测试 flag 名 `FAV_PUBLISHER_ENABLE` 少一个 D)已在批 2 修复,不在上表。M11/M12 的未读回滚与 Excel 行数上限已在批 4 处理;批 4 报告写明浏览器端到端未覆盖这两条,单测已钉住 XSS 主路径。
### 本轮新观察(不单独立项)
- 文首 schema 数字与实测不一致,见第二节。
- `test` 独有 9 个晋升提交,合并时用 merge,不要 reset。
## 证据
复核时间:2026-09-19。工作区当时在 `docs/audit-remediation-backlog`(树与 `dev@66421b1` 一致),随后本笔记落在 `docs/pre-test-promotion-review`。
| 项 | 路径/命令 | 结果 |
|----|-----------|------|
| 工作树 | `git status` | clean |
| dev 领先 test | `git rev-list --count test..dev` | 225 |
| test 领先 dev | `git rev-list --count dev..test` | 9(晋升/文档提交) |
| 静态检查 | `go vet ./...` | 零告警,exit 0 |
| 短测 | `go test -short ./...` | 全包 PASS;`internal/server` 14.044s |
| dev health | `curl -s http://127.0.0.1:8080/api/v1/health` | `env=dev` `schema_version=52` `status=ok` |
| test health | `curl -s http://127.0.0.1:8081/api/v1/health` | `env=test` `schema_version=52` `status=ok` |
| main health | `curl -s http://127.0.0.1:8000/api/v1/health` | `env=main` `schema_version=52` `status=ok` |
| 迁移文件 | `deploy/postgres/goose/` | 52 个 SQL,最新 `00052_2026-09-17-document-duty-locked.sql` |
| worktree | `git worktree list` | 主仓 + `dev-rdev-merge` + `feature-initial-load-performance-plan` + `fix-dev-runtime-data-root-guard`(检出 `feature/final-artifact-vault`) |
| 待办标记 | `grep TODO\|FIXME\|XXX` 于 `internal/` `cmd/`(排除 `_test.go`) | 0 |
| 容器 | `docker ps` | dev/test/main app+events+pi-agent 均为 healthy;dev app 已运行约 5 小时,早于批 1–4 合入后的 rebuild(未做) |
## 开放问题
- dev 与 test/main 默认模型不一致(M2.7-highspeed vs M3)是否刻意?深度审计已记,本轮无新证据。
- `deploy/postgres/migrations/` 是否仍有外部工具依赖?无则再归档(M13)。
- H2/H3 越权负例补到哪一层才算晋升门禁:HTTP 集成即可,还是必须 Playwright?
## 建议动作
按顺序,全部另开任务,不在本笔记内执行:
1. 占集成槽位,`./scripts/env-service.sh dev rebuild`,`curl -sf http://127.0.0.1:8080/health`(或 `/api/v1/health`)确认 schema 52 且二进制含批 1–4。
2. `TEST_DATABASE_URL` 下跑治理 PG 集成;`cd web && npm test && npm run build`。
3. 为 H2/H3 补至少一条跨用户/非成员 403 负例。
4. 通过后再把 `dev` merge 入 `test`(保留 test 上 9 个晋升提交),打 rc tag,并顺手更正 `CURRENT.md` 文首的 test schema 表述。
@@ -0,0 +1,53 @@
---
title: "首次加载 U2:字体自托管与静态资源交付"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Cursor
branch: feature/initial-load-perf-u2
worktree: "-"
mutex: web + static-delivery
---
# 首次加载 U2:字体自托管与静态资源交付
## 目标
登录页不再依赖 Google Fonts 阻塞 CSS;8080/8081 静态资源支持 gzip/br 协商与分层缓存;缺失 `/assets`/`/fonts` 返回 404 而非 HTML。
## 范围
- 自托管 Inter / JetBrains Mono(latin + latin-ext 可变 WOFF2)
- 构建期预压缩 `.br` / `.gz`
- Go `serveSPA` 压缩协商、Cache-Control、Vary、assets 404
- 单元测试与 rebuild 后 curl/浏览器验收
## 非目标
- U1 完整 Playwright 性能套件
- U3 拆包懒加载 / katex 入口 CSS
- U4–U6 初始化扇出、认证、SQL
- U7 完整重启归因(本轮仅借 rebuild 采集起点证据)
## 步骤
1. [x] 诊断/方案文档落盘并合入 `dev`
2. [x] 自托管字体 + 移除外链
3. [x] 预压缩脚本接入 build
4. [x] Go 静态交付修复
5. [x] 测试与 rebuild 验收
6. [x] 测试报告与文档同步
## 验收标准
- [x] 登录页无 `fonts.googleapis.com` / `fonts.gstatic.com` 请求
- [x] 主 JS 响应带 `Content-Encoding: br` 或 `gzip`,体积显著下降
- [x] `/assets/missing.js` → 404 且非 HTML
- [x] HTML `Cache-Control: no-cache`;哈希资源 `immutable`
- [x] SSE / API 缓存行为未回归
## 相关链接
- 方案: [../../remediation/2026-09-17-initial-load-performance-plan.md](../../remediation/2026-09-17-initial-load-performance-plan.md)
- 审计: [../../audit/2026-09-17-initial-load-performance-audit.md](../../audit/2026-09-17-initial-load-performance-audit.md)
- Test report: [../../test-reports/2026-09-17-initial-load-perf-u2-test-report.md](../../test-reports/2026-09-17-initial-load-perf-u2-test-report.md)
@@ -0,0 +1,58 @@
---
title: "系统管理台(System Admin Console)一期"
status: done
created: 2026-09-17
updated: 2026-09-17
owner: Kimi
branch: feature/system-admin-console
worktree: "-"
mutex: web + sysadmin
---
# 系统管理台(System Admin Console)一期
## 目标
为管理员提供独立的系统级管理界面(全屏视图,`workbench | admin` 顶层切换),覆盖总览状态、知识库、功能与特性开关、角色权限、工作流、用户审批、文档治理;吸收下线 AdminSettingsModal;系统设置只读为主 + SettingSpec 白名单少量可写。
## 范围
- 后端:新包 `internal/sysadmin`(薄聚合层,ports/settings/overview);迁移 `deploy/postgres/goose/00049`(`system_settings` 表);路由 `/api/v1/admin/system/{overview,kb,features,settings}`;`internal/server/admin_system_handlers.go`;`internal/app/app.go` 装配。
- 前端:`web/src/api/systemAdmin.ts` + `web/src/types/systemAdmin.ts`;`web/src/components/admin/console/AdminConsoleView.tsx` + `sections/`;`App.tsx` 顶层视图切换;LeftRail 入口语义改为进入管理台;吸收 `AdminSettingsModal` 六 tab 并删除旧模态。
## 非目标
- 不做全量 DB feature-flag 层(env 开关保留,标注「需重启」)。
- 不改项目级设置(`projectinstance.ProjectSettings` 与项目设置模态保持原样)。
- 不引入 react-router / 新前端依赖;不改 `tokens.css` 之外的全局样式。
- 不做 KB 重建/索引管理等运维动作(一期只读)。
## 步骤
1. [x] 后端 sysadmin 包 + goose 00049(commit `f1404d5`)
2. [x] 后端路由/handler/装配 + 单测(commit `f1404d5`)
3. [x] 前端 API 模块与类型(commit `0eaca61`)
4. [x] AdminConsoleView 骨架与 8 个分组 sections(commit `0eaca61`)
5. [x] 吸收 AdminSettingsModal 并下线(commit `0eaca61`)
6. [x] go vet / go test -short / web npm test + build(全绿)
7. [x] 占集成槽位:dev rebuild + /health + admin overview 冒烟(merge commit `dc7c31e`;schema 48→49;PASS)
## 验收标准
- [x] admin 从 LeftRail 入口进入全屏管理台,八个分组可渲染(UI 人工抽检由 Playwright spec 兜底,见报告后续项 1)
- [x] 非管理员无入口且 `/api/v1/admin/system/*` 返回 403(server 单测真实 mux + 内存 IAM)
- [x] 白名单可写设置 PUT 后 GET 生效;env 项只读并标注需重启(写读回环 PASS)
- [x] `go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build` 全绿
- [x] dev 容器冒烟 PASS
## 相关链接
- 方案:会话计划(全屏独立视图 / 吸收旧模态 / 只读+少量可写,用户已批准)
- Test report: [2026-09-17-system-admin-console-test-report.md](../../test-reports/2026-09-17-system-admin-console-test-report.md)
- FEATURE-MATRIX 行:系统管理台
## 证据 / 备注
- commit:`f1404d5`(后端)、`0eaca61`(前端)、`dc7c31e`(merge dev)
- 冒烟:health `schema_version=49`;overview/kb/features(22)/settings(6) 200;PUT 写读回环 PASS;匿名 401、未知 key 400、非 admin 403(单测)
- 遗留(二期):Playwright 实跑、`system:*` 细粒度权限、设置审计日志、KB 运维动作、白名单项接消费方、403 自动退回
@@ -0,0 +1,58 @@
---
title: "系统使用说明书(含真实截图,md/word/pdf/html 四格式)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Kimi
branch: feature/user-manual
worktree: .worktrees/feature-user-manual
mutex: docs
---
# 系统使用说明书(含真实截图,md/word/pdf/html 四格式)
## 目标
产出覆盖「从 0 进入系统 → 登录/注册 → 管理员角色权限配置 → 日常使用 → 审批全流程」的终端用户说明书,配 dev 环境真实操作截图(含真实 PI 对话),交付 Markdown / HTML / PDF / Word 四种格式于 `docs/user-manual/`。
## 范围
- dev 环境(127.0.0.1:8080)Playwright 实操截图约 30 张(登录、工作台、立项、对话、文档、审批链、管理台 8 分组)
- `docs/user-manual/manual.md` 十章中文说明书(内容以代码为准)
- `docs/user-manual/scripts/`(截图与格式生成脚本,可重跑)
- `docs/user-manual/dist/`(html/pdf/docx 产物)
## 非目标
- 不合入 dev、不 push(用户未要求)
- 不改动任何产品代码
- 不覆盖产品手册范围外的工程内部工具(`engineering-dashboard` 当时为工程内部,其后已移出本仓库)
## 步骤
1. [x] 分支 + 登记
2. [x] 环境预检(健康、登录凭证、中文字体、chromium)
3. [x] 截图脚本 `capture-screenshots.mjs` 并采集
4. [x] 真实 PI 对话截图
5. [x] 三责审批链 + 阶段门禁截图(zhanggong/lizhuguan/wangzong)
6. [x] 撰写 manual.md
7. [x] build-formats.mjs 生成 html/pdf/docx(pandoc 缺失时 .doc 兜底)
8. [x] 校验(图片引用、PDF 渲染抽查、docx 媒体嵌入)
9. [x] 提交 + 更新 CURRENT
## 验收标准
- [x] 四种格式文件齐备且可打开
- [x] manual.md 图片引用全部存在,无孤图
- [x] PDF 中文无乱码、图片正常嵌入
- [x] 说明书章节覆盖:进入系统/登录/注册/管理员配置角色权限/项目使用/对话/文档/审批/FAQ
## 相关链接
- Checklist: -
- Handoff: -
- Test report: -
## 证据 / 备注
- 演示账号(dev 种子,密码 123456):zhanggong / lizhuguan / wangzong / guest;管理员 admin(密码取 configs/.env.dev)
@@ -0,0 +1,55 @@
---
title: "Wave 0:P0 确认 bug 修复(SSE/缓存/run-stream)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor
branch: fix/wave0-p0-sse-chat-cache-bugs
worktree: "-"
mutex: chat + web
---
# Wave 0:P0 确认 bug 修复(SSE/缓存/run-stream)
## 目标
修复体检确认的 P0 bug:SSE 120s 断流(B-1/B-2)、run/stream 解析与时序(B-3/B-4)、前端会话窗口缓存 key 不一致(B-5)、IndexedDB 恢复覆盖(B-6)。
## 范围
- `internal/server/sse.go`:chat/run stream 心跳 + WriteDeadline;Decode 400;CreateAndStart/Subscribe 前置 Flush
- `web/src/hooks/useChatWindow.ts` + `web/src/data/storage.ts`:缓存 key / LRU 一致
- `web/src/App.tsx` + `web/src/data/fileStore.ts`:恢复合并
- 对应单测与测试报告
## 非目标
- E-1(main ENV 不一致)及 Wave 1–7 其余项
- FAV / MULTI_INTENT_PLAN_TIER / SEMANTIC_SUMMARY_REPLACE 放量
## 步骤
1. [x] 从 dev 开 `fix/wave0-p0-sse-chat-cache-bugs`,CURRENT 认领
2. [x] B-1/B-2 心跳与 deadline
3. [x] B-3/B-4 run/stream
4. [x] B-5 缓存 key
5. [x] B-6 恢复合并
6. [x] 单测 + 全量回归 + 合入 dev 冒烟
## 验收标准
- [x] `go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build` 全绿
- [x] 畸形 body → 400;Flush 前失败非 200 SSE
- [x] 缓存 key / LRU 单测 PASS;恢复合并不丢新增 deliverable
- [x] dev rebuild + health/ready;真 PI 聊天心跳证据(见测试报告)
## 相关链接
- Audit: [../../audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- Remediation: [../../remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Test report: [../../test-reports/2026-09-18-wave0-p0-bug-fixes-test-report.md](../../test-reports/2026-09-18-wave0-p0-bug-fixes-test-report.md)
## 证据 / 备注
- Commits:`64efaa3` docs · `54244ed` server · `2620d80` web;合入 `dev` merge `810fb96`
- Assets:`.doc/test-reports/assets/2026-09-18-wave0-p0-bug-fixes/chat-stream-long.sse.txt`
@@ -0,0 +1,53 @@
---
title: "Wave 1:main 环境 ENV/schema 修正(E-1/E-2/E-5)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor
branch: fix/wave1-main-env-fix
worktree: "-"
mutex: infra
---
# Wave 1:main 环境 ENV/schema 修正(E-1/E-2/E-5)
## 目标
统一 main 环境 app/events 的 `ENV=main` 语义,用 compose 依赖强制 events 先迁移再启 app,并关闭 `Env==""` 视同 dev 的导入门禁漏洞。
## 范围
- `docker-compose.main.yml`:app `ENV: main`;`depends_on.events` healthy;events 补生产校验所需口令
- `configs/.env.main`(本机)/ `.env.main.example`:`ENV=main`
- `internal/server/chat_window_api.go`:去掉空 Env 视同 dev
- 回归测试 + 真实 main rebuild 验证
## 非目标
- Wave 2+;不改 `event_consumer_modes` 的 mode 值;不触碰 FAV / MULTI_INTENT / SEMANTIC_SUMMARY_REPLACE
## 步骤
1. [x] 从本地 `dev` 开分支并 CURRENT 认领
2. [x] E-1 ENV 对齐
3. [x] E-2 depends_on events
4. [x] E-5 空 Env fail-closed
5. [x] 单测 + 合入 + main rebuild 冒烟
## 验收标准
- [x] app/events health 均报 `env=main`
- [x] main schema 已升(health `schema_version=52`,goose `version_id=52`)
- [x] `event_consumer_modes` 中 main 四行仍为 `off`
- [x] 导入端点空 Env → 403;compose ENV 对齐单测 PASS
## 相关链接
- Audit: [../../audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- Remediation: [../../remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Test report: [../../test-reports/2026-09-18-wave1-main-env-fix-test-report.md](../../test-reports/2026-09-18-wave1-main-env-fix-test-report.md)
## 证据 / 备注
- 合入本地 `dev`:`merge: fix/wave1-main-env-fix` + events secrets unblock
- Assets:`.doc/test-reports/assets/2026-09-18-wave1-main-env-fix/`
@@ -0,0 +1,57 @@
---
title: "Wave 2:配置与灰度入口对齐(E-3/E-4/E-6/E-7/E-9)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: fix/wave2-config-flag-align
worktree: "-"
mutex: infra
---
# Wave 2:配置与灰度入口对齐
## 目标
三环境 compose 显式声明封存 flag(值保持 legacy/false);移除死 `CURSOR_RUNNER`;main 显式 `SEED_DEMO_USERS=false`;`INTENT_V2_DECISION_TIER` 非法值 fail-closed 到 `none`;E-9 仅记录评估结论。
## 范围
- E-3 / A-4:三环境补 `MULTI_INTENT_PLAN_TIER` + U9–U12 + SHADOW/NARRATIVE 声明
- E-4:删除 `CURSOR_RUNNER_URL` 与 `cursor-agent` 占位服务
- E-6:main `SEED_DEMO_USERS: "false"`
- E-7:`parseV2DecisionTier` default → `none`
- E-9:评估记录,不改 initdb
## 非目标
- 不升 `MULTI_INTENT_PLAN_TIER`;不接线 `SEMANTIC_SUMMARY_REPLACE`
- 不改 FAV modes;不改 E-9 initdb 挂载
- Wave 3+ 范围项
## 步骤
1. [x] Sonnet 5 产出实施计划(默认决策:删 cursor-agent;不补 REPLACE;E-9 不改代码)
2. [x] E-7 代码 + 单测
3. [x] E-3 / E-4 / E-6 compose
4. [x] compose flag 声明回归测试
5. [x] go vet/test;三环境 rebuild + env 抽检 + 冒烟
6. [x] 合入本地 dev;文档闭环
## 验收标准
- [x] 三环境 `docker compose config` 可见目标 flag;`CURSOR_RUNNER` 零匹配
- [x] 容器内 env 抽检 PASS;health/ready PASS
- [x] `go test -short ./...` 全绿
- [x] test-report 归档;remediation Wave 2 done
## 相关链接
- Remediation: [.doc/remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Audit: [.doc/audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- Test report: [.doc/test-reports/2026-09-18-wave2-config-flag-align-test-report.md](../../test-reports/2026-09-18-wave2-config-flag-align-test-report.md)
## 证据 / 备注
计划作者:[Wave 2 Sonnet 计划](5b8c8c73-c3e4-4947-b0c4-91822859ff4a)
commits:`07fc0ec` `e0aabec` `55a539c` `8d97dd6` + docs closeout
@@ -0,0 +1,46 @@
---
title: "Wave 3:测试债与盲区(S-1/S-2/S-4/S-5)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: fix/wave3-test-debt-blindspots
worktree: "-"
mutex: test-debt
---
# Wave 3:测试债与盲区
## 目标
关闭 `TestReconcile_LegacyRepair_PG` 工程测试债;清理永久跳过死代码;统一 E2E 脚本入口;推广 409/结构化错误信封复用。
## 范围
- S-1 / S-2 / S-4 / S-5(按 Sonnet 计划默认决策)
## 非目标
- 不升 MULTI_INTENT_PLAN_TIER;不接线 REPLACE;不改 FAV;项目 143 只读
- 不改后端 httpx 信封整体迁移;不统一 INTENT_DUAL_TAB
## 步骤
1. [x] Sonnet 5 计划
2. [x] S-1 隔离 PG 5436 跑一次并归档
3. [x] S-2 删死跳过 + plan_owner 说明
4. [x] S-4 e2e scripts + 退役 document-revision.spec
5. [x] S-5 信封复用 + 单测
6. [x] 文档闭环 + 合入本地 dev
## 验收标准
- [x] reconcile PG PASS 证据
- [x] playwright --list = 29 tests / 8 files
- [x] npm test / go test -short 全绿
- [x] gap-matrix 测试债关闭;remediation Wave 3 done
## 相关链接
- Plan agent: [Wave 3 Sonnet 计划](51987049-b338-41a7-84f4-2c97e3655d85)
- Test report: [.doc/test-reports/2026-09-18-wave3-test-debt-blindspots-test-report.md](../../test-reports/2026-09-18-wave3-test-debt-blindspots-test-report.md)
@@ -0,0 +1,49 @@
---
title: "Wave 4:隐患加固(R-1~R-8)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: fix/wave4-hardening-r1-r8
worktree: "-"
mutex: hardening
---
# Wave 4:隐患加固(R-1~R-8)
## 目标
按 Wave 4 Sonnet 计划默认决策关闭体检高风险隐患 R-1~R-8。
## 范围
- R-1~R-8 全项(含 D-1 扩大范围:upsert + COALESCE)
## 非目标
- D-4/D-5;不升 tier;不接线 REPLACE;不改 FAV;项目 143 只读;不 push
## 步骤
1. [x] R-1c/R-1a/R-1b + Memory/PG 负例
2. [x] R-2 rows.Err()
3. [x] R-3 RWMutex / R-4 memTurns / R-5 hydrate / R-6 Shutdown
4. [x] R-7/R-8 前端 + 单测
5. [x] 全量验收 + test-report + 合入本地 `.worktrees/dev-rdev-merge` dev
## 验收标准
- [x] R-1~R-8 按计划验收项 PASS
- [x] `go vet` / `go build` / `go test -short ./...` / `npm test` / `npm run build`
- [x] 相关 `-race` 绿
- [x] 文档闭环
## 相关链接
- Remediation: [.doc/remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Test report: [.doc/test-reports/2026-09-18-wave4-hardening-r1-r8-test-report.md](../../test-reports/2026-09-18-wave4-hardening-r1-r8-test-report.md)
- Assets: [.doc/test-reports/assets/2026-09-18-wave4-hardening-r1-r8/](../../test-reports/assets/2026-09-18-wave4-hardening-r1-r8/)
## 证据 / 备注
基线 tip:`32932e4`。合入本地 `dev` 见 merge commit。
@@ -0,0 +1,98 @@
---
title: "Wave 5:死代码与机制收口(X-1~X-5)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: fix/wave5-deadcode-decisions
worktree: "-"
mutex: deadcode-cleanup
---
# Wave 5:死代码与机制收口(X-1~X-5)
## 目标
按系统体检整改方案 Wave 5,对 X-1~X-5 逐项决策并收口:删除真死 flag/组件、封存 REPLACE、标记 00048 deferred、保留 system_settings 二期键。
## 范围
- X-1~X-5 全项(含级联删除 `patchNotification`)
## 非目标
- X-6(`useTaskRunStream` 伪 ref);不接线 REPLACE;不升 MULTI_INTENT_PLAN_TIER;不改 FAV;项目 143 只读;不改 goose 00048/00049 schema;不 push
## 步骤
1. [x] 决策记录落盘(本文件「决策记录」段)
2. [x] X-1 删除 `SEMANTIC_FALLBACK_ENABLED` + 回归测试
3. [x] X-2 封存注释回链
4. [x] X-3 00048 deferred 注释 + long-term
5. [x] X-4 system_settings 6 键注释
6. [x] X-5 删除死组件/死 API
7. [x] 全量验收 + test-report + 合入本地 `.worktrees/dev-rdev-merge` `dev`
## 验收标准
- [x] X-1~X-5 每项有决策记录(本文件)
- [x] `go vet ./...` / `go test -short ./...` / `cd web && npm test && npm run build`
- [x] remediation Wave 5 行改 done;勾选「X-1~X-5 每项有决策记录」
- [x] 文档闭环 + merge `--no-ff`
## 相关链接
- Remediation: [.doc/remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Audit: [.doc/audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- Test report: [.doc/test-reports/2026-09-18-wave5-deadcode-decisions-test-report.md](../../test-reports/2026-09-18-wave5-deadcode-decisions-test-report.md)
- Assets: [.doc/test-reports/assets/2026-09-18-wave5-deadcode-decisions/](../../test-reports/assets/2026-09-18-wave5-deadcode-decisions/)
## 决策记录
### X-1:`SEMANTIC_FALLBACK_ENABLED` — 删除
- **现状证据**:字段仅在 `internal/intent/flags.go` 解析、`internal/app/app.go` 注入 sysadmin 视图、`internal/sysadmin/features.go` 目录展示;全仓无业务消费方。三环境 compose + `.env.example` 均声明该死变量。
- **决策**:删除(不接线)。
- **理由**:零读者、无设计文档描述预期语义;接线需独立产品设计,保留只会继续污染配置面。
- **影响范围**:`flags.go` / `app.go` / `features.go` / 三 compose / `.env.example`;新增 `TestComposeNoDeadSemanticFallbackConfig` 防复活。
- **验收**:`go vet ./...`;`go test ./internal/intent/... ./internal/app/... ./internal/sysadmin/... ./internal/config/...`;`rg SEMANTIC_FALLBACK_ENABLED` 除 `.doc/` 历史外无匹配。
### X-2:`SEMANTIC_SUMMARY_REPLACE` — 维持封存
- **现状证据**:env 可读但 `semantic_summary.go` 明确 `_ = SemanticSummaryReplaceEnabled()` 且不替换 `sum.Narrative`;负例 `TestSemanticSummary_ShadowOKKeepsDeterministic` 已覆盖 `Replace: true`。
- **决策**:维持不接线;补强注释回链本决策记录。
- **理由**:与 CURRENT 红线及 remediation Wave 5 一致;启用需独立授权 + fail-closed 灰度设计。
- **影响范围**:仅 `summary_flags.go` / `semantic_summary.go` 注释。
- **验收**:`go test ./internal/ctxmgr/... -run Semantic`;diff 仅注释。
### X-3:goose 00048 三表 — deferred → SWBOOT-10/W5b
- **现状证据**:`project_types` / `compliance_profiles` / `project_type_workflows` 已建表有种子,但 API 走硬编码 `swboot.ProjectTypesCatalog()` / `ComplianceProfilesCatalog()`;`project_source_bindings` / `repo_path_allowlist` 零运行时读写;`RepoAllowlist` 仅 stub + 单测。
- **决策**:标记 deferred,归 W5b/SWBOOT-10;**不改 schema**。
- **理由**:FEATURE-MATRIX 明确 SWBOOT-10 仍 stub;DB 化消费方与受控执行器需独立安全评审。
- **影响范围**:`catalog.go` / `repo_allowlist.go` 注释;long-term 软件自举文档追加一行。
- **验收**:`go test ./internal/swboot/...`;diff 仅注释与 long-term 文档。
### X-4:`system_settings` 6 未接线键 — 保留待二期
- **现状证据**:白名单 7 键中仅 `workflow.allow_author_only_approval` 有消费方;其余 6 键(`ui.maintenance_notice`、`ui.read_only_mode`、`chat.default_session_role`、`tasks.default_auto_repair`、`kb.default_search_limit`、`notifications.stage_advance_reminder`)零业务读取。FEATURE-MATRIX 系统管理台「白名单项接消费方」列为二期。
- **决策**:保留白名单 + 逐键注释说明预期消费方;不删。
- **理由**:删除需改写多处白盒测试且收益低;机制先行符合一期设计,二期再接线。
- **影响范围**:仅 `internal/sysadmin/settings.go` 注释。
- **验收**:`go test ./internal/sysadmin/...`;diff 仅注释。
### X-5:前端死组件/死 API — 删除
- **现状证据**(`web/` 全目录扫描,排除自身):
- `DocumentNotificationList` / `WorkflowPrerequisiteBanner` / `SettingsModal`:仅自身文件命中;`App` 使用 `UserSettingsModal`。
- `activateWorkflow`(`api/projectWorkflow.ts`):仅定义处;实际用 `activateWorkflowInstance`。
- `saveMessages`:已 `@deprecated` no-op,仅定义处。
- 级联:`patchNotification` 唯一调用方为 `DocumentNotificationList`。
- **决策**:删除上述 3 组件 + `activateWorkflow`(及类型)+ `saveMessages` + `patchNotification`;同步 import。后端 `PATCH /api/v1/notifications/{id}` 保留。
- **理由**:真死代码;删除降低误挂载与维护噪音;后端路由未经本波审计故不删。
- **影响范围**:见删除清单;无 barrel / 无专用单测。
- **验收**:`cd web && npm test && npm run build`;`rg` 无残留(`activateWorkflowInstance` 除外)。
## 证据 / 备注
基线 tip:`a12c947`(Wave 4 已合入本地 `.worktrees/dev-rdev-merge` `dev`)。
@@ -0,0 +1,51 @@
---
title: "Wave 6:文档漂移修复(D-1~D-6)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: docs/wave6-doc-drift
worktree: "-"
mutex: doc-drift
---
# Wave 6:文档漂移修复(D-1~D-6)
## 目标
按系统体检整改方案 Wave 6,逐项关闭文档漂移 D-1~D-6,使 SSOT(audit/INDEX、remediation/INDEX、FEATURE-MATRIX、PROJECT.md、backlog、ADR、handoff、PU8 契约)口径一致。
## 范围
- D-1(含附带的 short-term 归档)、D-2、D-3(复核)、D-4、D-5、D-6
## 非目标
- Wave 5(X-1~X-5)及其涉及的任何代码;不升 tier;不接线 REPLACE;不改 FAV;项目 143 只读;不删除 D7 对话数据
## 步骤
1. [x] D-1 契约状态回标 + 归档两份 short-term 任务文件
2. [x] D-2 ADR 状态改 accepted
3. [x] D-3 复核 INDEX 末行(无改动)
4. [x] D-4 handoff 回标闭环
5. [x] D-5 backlog D3/D7 同步
6. [x] D-6 PROJECT.md §9 对齐
7. [x] remediation/CURRENT 收口 + test-report + 合入本地 `dev`
## 验收标准
- [x] D-1~D-6 每项均有落盘证据或复核记录
- [x] `go build ./...` / `go vet ./...` / `npm run build` 全绿(无代码改动,防误伤)
- [x] remediation Wave 6 行改 done;勾选「D-1~D-6 全部回链关闭」
- [x] CURRENT 焦点/认领表/集成槽位三处一致
## 相关链接
- Remediation: [../../remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Audit: [../../audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- Test report: [../../test-reports/2026-09-18-wave6-doc-drift-test-report.md](../../test-reports/2026-09-18-wave6-doc-drift-test-report.md)
## 证据 / 备注
基线 tip:`2ce2625`(`merge: fix/wave5-deadcode-decisions`)。mutex=`doc-drift`,未复用 `architecture-docs`。FEATURE-MATRIX 交叉检查无改动(D3 done/shadow、D7 deferred、U9–U12 done、`production_ready=yes` 与本次回标一致)。
@@ -0,0 +1,101 @@
---
title: "Wave 7:既有 roadmap 收口(编排确认)"
status: done
created: 2026-09-18
updated: 2026-09-18
owner: Cursor-Auto
branch: docs/wave7-roadmap-orchestration
worktree: "-"
mutex: roadmap-orchestration
---
# Wave 7:既有 roadmap 收口(编排确认)
## 目标
对照 FEATURE-MATRIX 剩余工作列,为 T1/W5、T1/W6、T1/W7、T2、T4、T5/T6/T8 各写一条编排确认;不改变任何能力实现状态。
## 范围
- 六条编排确认文案落盘(见「确认记录」)
- remediation Wave 7 行改 done 并回链本记录
- CURRENT 焦点改为 Wave 0–7 done,并记录 Control Center 双实现发现
## 非目标
- 不实施 SWBOOT-10;不升 FAV live / 不改 `FAV_DEGRADED_READ`;不按 D7 物理删除数据;不升 `MULTI_INTENT_PLAN_TIER`;不接线 `SEMANTIC_SUMMARY_REPLACE`;项目 143 只读
- 不改 FEATURE-MATRIX 状态列;不改 gap-matrix 发布门禁
- **不补 Wave 6 D-5**:D-1~D-6 已在 `a88ed85` PASS,backlog D3/D7 已同步;本波不改 `.doc/backlog/chat-agent-p6-backlog.md`,不把 Wave 6 再标一遍
- 不决定 Control Center 两套实现的取舍:不合并、不删除 `feature/control-center-server`
## 步骤
1. [x] 跳过步骤 0(Wave 6 D-5 已完成)
2. [x] 六条编排确认落盘(本文件)
3. [x] remediation Wave 7 行改 done + 回链本记录
4. [x] CURRENT 焦点改为「Wave 0–7 done」+ 记录 Control Center 分支冲突发现
## 验收标准
- [x] 六项编排确认均含:当前状态、关闭条件、是否需用户授权、建议下一触发点
- [x] 无一项被伪装为已实现;FAV/D7/tier 升级仍标注「需用户显式授权」
- [x] Wave 6 保持已关闭,未重复改写
## 相关链接
- Remediation: [../../remediation/2026-09-17-system-health-remediation-plan.md](../../remediation/2026-09-17-system-health-remediation-plan.md)
- Audit: [../../audit/2026-09-17-system-health-check.md](../../audit/2026-09-17-system-health-check.md)
- 总控: [../../remediation/2026-09-16-partial-deferred-completion-plan.md](../../remediation/2026-09-16-partial-deferred-completion-plan.md)
- Test report: [../../test-reports/2026-09-18-wave7-roadmap-orchestration-test-report.md](../../test-reports/2026-09-18-wave7-roadmap-orchestration-test-report.md)
## 确认记录
### T1/W5:SWBOOT-10
- **当前状态**:SWBOOT-00~09(契约、迁移、目录、UI、docs_only 真实 PI)已合入 `dev`([long-term](../long-term/2026-09-14-software-project-bootstrap-implementation.md)、[W5a 报告](../../test-reports/2026-09-17-w5a-software-bootstrap-ui-pi-test-report.md))。SWBOOT-10(受控工程执行:repo allowlist、worktree、patch/test/merge 分段批准)仍为 **stub only**,保持 fail-closed,归 W5b,本轮未启动。goose 00048 三张关联表(`project_source_bindings` / `repo_path_allowlist` / `project_type_workflows`)已在 Wave 5 X-3 标记 deferred。
- **关闭条件**:独立安全评审通过 + SWBOOT-10 非 stub 真实实现 + 真实 PI 全链路证据 + UI 二次验收(见 [partial-deferred-completion-plan §W5](../../remediation/2026-09-16-partial-deferred-completion-plan.md))。
- **是否需用户授权**:**需要**。独立安全评审本身即用户授权门槛;红线明确「不实施 SWBOOT-10 真实执行器」。
- **建议下一触发点**:用户就 W5b 受控执行器单独立项、批准安全评审范围后,从 `dev` 开 `feature/swboot-10-w5b`(mutex `workflow-design`)按 long-term 拆分实施。本波不动代码,fail-closed stub 原样保持。
### T1/W6:FAV live 放量
- **当前状态**:W6 shadow 已合入 `dev`([short-term](2026-09-17-w6-fav-subscriber-shadow.md)、[报告](../../test-reports/2026-09-17-w6-fav-subscriber-shadow-test-report.md)):`ObserveShadow` 只计算 intended outcome、不写业务副作用;负例覆盖 degraded read 拒绝 / `HandleLease` / `Register(fav)` fail-closed。三环境 compose 既有声明为 `FAV_DEGRADED_READ` 默认 false、`FAV_PUBLISHER_ENABLED` 默认 false。**live 未放量**。本波未改 compose。
- **关闭条件**:按固定顺序 staging → artifact → publication 逐 consumer live,每级 shadow → drain → live,观察窗 ≥7 天或 ≥N 终态样本(取更严);`FAV_DEGRADED_READ` 全程保持 false;崩溃/重启幂等证据;**禁止整支 merge** `feature/final-artifact-vault`(见 [partial-deferred-completion-plan §7.4](../../remediation/2026-09-16-partial-deferred-completion-plan.md))。
- **是否需用户授权**:**需要**。红线明确「不升 FAV live / 不改 `FAV_DEGRADED_READ`」。
- **建议下一触发点**:用户批准 staging 级观察窗起点后,从 `dev` 开独立 flag 分支(mutex `events`),先跑 staging ≥7 天观察窗并归档证据报告,再评估升 artifact/publication。本波不推进放量。
### T1/W7:D7 对话数据治理
- **当前状态**:ADR 草案([2026-09-17-d7-chat-data-retention.md](../../adr/2026-09-17-d7-chat-data-retention.md),`compliance: pending-compliance-signoff`)已落地;只读数据分类盘点已完成([audit](../../audit/2026-09-17-d7-data-inventory.md),`status: done`),**未发现**当前基线违反已确认合规/安全约束,因此**未**写入 gap-matrix blocker。合规签字前禁止按 365/180/30 天草案数字执行物理删除或备份清除。Wave 6 已把该现状同步进 backlog D7 行,本波不改该文件。
- **关闭条件**:合规签字或改数 → ADR 状态改 `accepted`/`signed` → 按签字口径落地整改(soft-delete 写路径 → 观察窗 → 物理清理;备份二次批准 + delete manifest)→ FEATURE-MATRIX D7 行升 `done`;若盘点期间发现违规则立即升 gap-matrix(本轮未触发)。
- **是否需用户授权**:**需要**。合规签字是产品/法务决策,非工程可自行拍板;红线明确「不按 D7 物理删除数据」。
- **建议下一触发点**:用户/合规负责人对 ADR 草案数字表签字或提出修改意见;签字后开独立 short-term 任务按 ADR 决策落地。
### T2:Control Center 前端 SPA 七页人工走查
- **当前状态**:2026-09-17 审计结论已过期,不能按「仅剩前端走查」收口。FEATURE-MATRIX「个人工程中控台」行已通过 `engineering-dashboard`(CLI `serve`/`export`,四轴模型)达到 **done** 一期,已合入 `dev`([报告](../../test-reports/2026-09-17-engineering-dashboard-test-report.md))。审计 T2 所指「后端 P0–P6 已签,仅剩前端 SPA 七页人工走查」实为 Kimi 的 `feature/control-center-server`:自身 11 commits(P0 skeleton → P6 design spec + LAN bind + agent-integration),**从未合入 `dev`**。2026-09-18 相对 `dev@a88ed85` 实测:merge-base `adb48c8`,落后 **136** commits(研究快照曾记 128,以本次 `rev-list` 为准),缺失 Wave 0–6。提交 `b5bacee`(`refactor(control-center): remove legacy engineering-dashboard, superseded by control-center`)试图删除已合入并验收的 `engineering-dashboard`,与 canonical 实现冲突。该分支的任务声明与 CURRENT 认领只存在于分支本身,未反映在 `dev` 主线。实现范围(pgvector 文档向量库、P3 SPA、P5 定期审计 + LLM 复核)超出已批准设计一期边界。
- **关闭条件**:FEATURE-MATRIX 该行**已经 done**(通过 engineering-dashboard)。若要转向「复活/合并 Kimi 实现」,需先有独立决策与重新规划,不属于「仅剩一次前端走查」。
- **是否需用户授权**:**是**。授权对象是「两套实现如何取舍」,不是「批准做前端走查」。本波只读编排确认,不能代为废弃或合并该分支。
- **建议下一触发点**:请用户明确二选一:(a) 维持现状——`engineering-dashboard` 为唯一 canonical 实现,`feature/control-center-server` 由用户决定归档或保留(推荐:已 done 且范围经批准);或 (b) 要求评估合并该分支的增量能力(SPA / pgvector / 定期审计)。触发后再开对应短期任务。本波只记录事实与建议,**不合并、不删除**该分支。
- **后续裁决(2026-09-19)**:用户决定进度管理由独立项目承担。本仓库已删除 Control Center 代码与文档,不恢复 `engineering-dashboard`。见 [移除任务](./2026-09-19-remove-control-center.md)。
### T4:首次加载性能 U1/U3–U7
- **当前状态**:仅 U2(静态资源交付)done——自托管字体、构建期 br/gzip、`/assets/*` 404 修正;主 JS 传输 2.82 MB → ~624 KB,登录冷缓存可见 ~205ms([报告](../../test-reports/2026-09-17-initial-load-perf-u2-test-report.md))。U1(完整性能基线)、U3(登录壳按需加载)、U4(初始化扇出收敛)、U5(认证请求去重)、U6(列表/租约按证据优化)、U7(重启后首访链路)**均未开始**。
- **关闭条件**:按 [方案](../../remediation/2026-09-17-initial-load-performance-plan.md) Definition of Done——R1–R6 逐项有前后对比 + 真实 UI 证据;未覆盖项明确列残余,不因 health PASS 关闭;完成后更新任务/CURRENT/FEATURE-MATRIX/test-report。
- **是否需用户授权**:不需要额外专项授权(方案已 planned 且范围已批准);需要工程排期认领(估算 U1–U5 约 3.5–7 人日,U6 另需 2–4 日,U7 另需 0.5–1.5 日,非承诺)。
- **建议下一触发点**:任一 Agent 从 `dev` 开分支认领 U1(P0,是后续单元的前置依赖)即触发;建议顺序 U1 → U2(done)/U3 与 U7 → U4/U5 → 按数据选 U6。
### T5/T6/T8:backlog 类(按收益触发)
- **T5 选择性模块解耦 M4–M6**:**当前状态** `planned`,owner=TBD,未开始([long-term](../long-term/2026-09-14-selective-module-decoupling.md))。触发条件中「M1–M3 test report 全部 PASS」已满足(文档可靠性试点 / 可靠事件核心均 done),但「同类缺陷触达文件数和运行故障率表明继续解耦具有收益」证据尚未出现,暂不触发。**关闭条件**与是否授权见该文档触发条件段。**是否需用户授权**:无需专项授权,按收益证据 + owner 认领即可开工。**建议下一触发点**:出现同类缺陷证据或 owner 主动认领。
- **T6 产品 backlog(B5/A5/A6/A7/D5)**:[backlog](../../backlog/chat-agent-p6-backlog.md) 仍列 B5(报价复核)、A5/A6(小队降级 + trace)、A7(注释迁移)、D5(KB 按环境隔离评估)为纯 backlog,无任务文件、无 owner。**D3、D7 已由 Wave 6 同步**(D3 标已实现 shadow 并回链;D7 回链 ADR 草案与只读盘点,合规签字前不整改)。本波不改该文件。**关闭条件**:开放项按产品收益单独排期开短期任务。**是否需用户授权**:开始评估不需要专项授权;D3 REPLACE 灰度、D7 整改分别仍受各自红线约束。**建议下一触发点**:产品侧提出具体收益诉求;无固定时间表。
- **T8 IAM 收尾开放项**:410 退役策略已冻结为「保留,非缺口」([决策](../../audit/2026-09-16-bug11-410-retire-decision.md),gap-matrix BUG-11 PASS);R13 数据安全清单 7 项全部 PASS,仅「完整红队注入矩阵」标记为开放增强、不挡基线;IAM 全路由 inventory 仍标记「开放」([handoff](../handoffs/2026-09-16-phase3-leftover-closeout.md)),fail-closed 核心已签。均为**加固类,非发布 blocker**。**是否需用户授权**:不需要专项授权,可按运维遥测随时另开 audit/任务。**建议下一触发点**:410 路由遥测证明零流量后可另开退役任务;或需要更强出站安全保证时另开红队 audit。
## 新发现(需用户后续裁决,不阻塞本波收口)
- **Control Center 双实现冲突**:当时未合入。2026-09-19 用户裁决为移出本仓库,代码与专属文档已删除,不恢复旧工程中控台。见 [移除任务](./2026-09-19-remove-control-center.md)。
## 证据 / 备注
基线 tip:`a88ed85`(`merge: docs/wave6-doc-drift`)。mutex=`roadmap-orchestration`。零 Go/TS/SQL/compose 改动。FEATURE-MATRIX 状态列未改。
@@ -0,0 +1,56 @@
---
title: "移除 Control Center,本仓库回到智能体系统"
status: done
created: 2026-09-19
updated: 2026-09-19
owner: Cursor-Auto
branch: fix/remove-control-center
worktree: "-"
mutex: controlcenter
---
# 移除 Control Center
## 目标
项目进度管理已由独立项目承担。从本仓库删除 Control Center 的代码、部署、规范和专属文档,不恢复旧 `engineering-dashboard`。
## 范围
- 删除 `cmd/control-center`、`internal/controlcenter`、`control-center/web`、`deploy/control-center`、`scripts/control-center.sh`
- 删除专属设计、任务、测试报告与截图
- 更新 AGENTS、FEATURE-MATRIX、CURRENT、模块边界与断链引用
- 停掉 `control-center-db` 与 `127.0.0.1:8790`
## 非目标
- 不恢复 `engineering-dashboard`
- 不 push
- 不改产品 `internal/server`、产品前端或三环境 compose
## 步骤
1. [x] 从本地 dev 开 `fix/remove-control-center`
2. [x] 删除代码与文档并更新引用
3. [x] 停运行时
4. [x] `go vet` / `go test -short` / 产品前端 build / archtest
5. [x] 合入本地 dev 并做健康检查
6. [x] 删除未跟踪的 `control-center/web/node_modules` 与本地分支 `feature/control-center-server`
## 验收标准
- [x] 仓库内不再有 Control Center 源码或专属文档
- [x] `go vet ./...`、`go test -short ./...`、`go test ./internal/archtest/`、`web` 的 `npm run build` 通过
- [x] 本地 dev 健康检查 200
## 相关链接
- Checklist:
- Handoff:
- Test report: [../../test-reports/2026-09-19-remove-control-center-test-report.md](../../test-reports/2026-09-19-remove-control-center-test-report.md)
## 证据 / 备注
用户确认:只移除 Control Center,副本已在别处实现,合入本地 dev。
2026-09-19 复查:产品代码、模块边界、AGENTS 规范、容器与端口均无残留。另删除未跟踪目录 `control-center/`(仅 `node_modules`)和本地分支 `feature/control-center-server`(`55fa8dd`)。未删除 `origin/feature/control-center-server`。`go build ./...` 通过。
@@ -0,0 +1,50 @@
---
title: "系统深度体检审计(独立审查潜在缺陷与未完善点)"
status: done
created: 2026-09-19
updated: 2026-09-19
owner: Cursor
branch: docs/audit-remediation-backlog
worktree: "-"
mutex: audit
---
# 系统深度体检审计(2026-09-19)
## 目标
在不改业务代码的前提下,对当前 dev(e8ed33b)做一次独立深度审查,输出 `.doc/audit/` 审计笔记,列出潜在 bug 与未完善项并给出严重度分级。
## 范围
- Go 静态验证:`go vet ./...` + `go test -short ./...`
- 后端:server 路由/chat SSE/docgov/events 错误处理与并发风险
- 前端 web:错误处理、SSE 重连、竞态
- 配置:flag 默认值一致性、死代码、环境差异(dev/test schema 漂移)
- 安全:IAM 旁路、密钥泄露面
- DB:goose 迁移一致性与回滚风险
## 非目标
- 不修改业务代码(docs-only 分支)
- 不验证已明确 deferred 的事项本身(FAV live 放量、D7 签字、SWBOOT-10)——仅核对声明与代码是否一致
## 步骤
1. [x] 创建 docs 分支、登记 CURRENT
2. [x] go vet + go test -short
3. [x] 并行子代理深潜后端/前端/配置/DB/安全
4. [x] 汇总撰写 audit 笔记并提交
## 验收标准
- [x] 每个发现均有代码路径 + 行号证据
- [x] 严重度分级(critical/high/medium/low)
- [x] 与 FEATURE-MATRIX 已声明的 partial/deferred 项对齐,不重复申报
## 证据 / 备注
- go vet 零告警;go test -short 55 包全 PASS(dev@e8ed33b)
- 审计笔记:[.doc/audit/2026-09-19-system-deep-audit.md](../../audit/2026-09-19-system-deep-audit.md)
- 五路并行只读深潜全部完成;四条红线核实一致;新发现 4 critical(C1 docgov 吞错 / C2 Session 竞态 / C3 SSE 超时 / C4 工作流竞态)+ 10 high
- 整改:critical/high 已分四批合入 `dev`(`844f757` / `08f4e0b` / `a2a49a6` / `d73bc79`)。medium/low 见 [long-term](../long-term/2026-09-19-audit-remainder.md)。
@@ -0,0 +1,58 @@
---
title: "修复系统权限设置与项目协作多项缺陷"
status: done
created: 2026-09-20
updated: 2026-09-20
owner: Cursor-Auto
branch: fix/bug-hunt-2026-09-20-permissions-and-uploads
worktree: "-"
mutex: authz+web+projectworkflow
---
# 修复系统权限设置与项目协作多项缺陷
## 目标
修复两轮排查确认的 12 处后端/前端缺陷(CSP/PDF、系统设置 CAS、任务错误误分类、task-run 403、成员管理 RBAC、注册吞错、强制改密复发、项目重名、无项目可对话、右侧栏不记忆等)。
## 范围
- CSP `frame-src` + PDF blob 预览
- 系统设置 `expected_revision` 全链路
- `ProjectSettingsApiError` httpStatus/errorCode 别名
- task-run 查看放宽为项目成员;前端 403/404 停轮询
- `project:manage_members` 权限位(迁移 00055)
- memStore 成员可见性
- CreateUser 吞错 / 400·500 分类 / LooksInternal
- 强制改密 session 嵌套字段 OR 复活
- CreateProject `client_key` 幂等 + `(creator, name)` 唯一(迁移 00056)
- 无项目禁止对话 + 发送按钮置灰
- 右侧工具栏默认收起并持久化
## 非目标
- 全局项目名唯一(仅同创建人内唯一)
- 放宽 `frame-ancestors` / `X-Frame-Options`
## 步骤
1. [x] 后端 CSP / authz / auth / projectworkflow / chat 入口
2. [x] 前端 PDF / settings / 错误别名 / 轮询 / RBAC UI / 改密 / 建项幂等 / InputArea / AppShell
3. [x] 迁移 00055 / 00056 + 单测
4. [x] `go vet` / `go test -short` / `npm test` / `npm run build`
5. [x] 占集成槽位合回 `dev`
## 验收标准
- [x] 代码与契约补齐(见 audit 笔记)
`- [x] 短测与前端构建通过
`- [x] 合入 `dev`
## 相关链接
- Audit: `.doc/audit/2026-09-20-bug-hunt-permissions-uploads.md`
- Plan: `.cursor/plans/修复系统权限设置与项目协作多项缺陷_ff3242f7.plan.md`
## 证据 / 备注
分支:`fix/bug-hunt-2026-09-20-permissions-and-uploads`
@@ -0,0 +1,347 @@
---
title: 文档编制人兼任审核批准 - Plan
type: feat
date: 2026-09-17
status: planned
artifact_contract: ce-unified-plan/v1
product_contract_source: ce-plan-bootstrap
execution: code
---
# 文档编制人兼任审核批准 - Plan
## Goal Capsule
在系统管理员授权后,项目创建者可以为项目工作流中的每份文档单独启用「编制人兼任审核、批准」,只选择一位编制人即可完成该文档的全部人工职责。
本次交付为设计方案,尚未授权业务实现。已确认的需求是两级授权和逐文档配置。R9(激活前配置/激活后冻结)与 R10(关总开关后存量按冻结继续、不提供紧急熔断)已于 2026-09-17 审核批准,并补强 Heal 三入口投影稳定性为硬性验收项。实现与发布须分别提供源码、数据库、真实产品 PI 和浏览器证据。
基线为本地 `dev@adb48c8`,2026-09-17 源码核查;不代表正在运行的镜像已具备本能力。远端已 fetch,本地 dev 领先 origin/dev 44 个提交、落后 0。本方案不修改正式工作流定义,不将兼任等同于免审批。
---
## Product Contract
### Summary
新增管理员总开关,默认关闭;新增逐文档职责模式,默认沿用当前规则。创建者开启某份文档的兼任模式后,只填写编制人,审核人与批准人由服务端派生为同一人。仍执行送审、审核和批准,保留每一步身份、意见和时间。
### Problem Frame
当前系统仅允许可选文档三职全空或三职完整指定,且完整指定时要求三人不同。用户需要小团队或个人也能执行完整的文档治理流程,并由管理员控制这一例外是否可用。
当前权限、文档人员投影和前端角色识别使用不同数据路径。因此仅放宽三职分离校验不足以支持本需求,还必须保证配置、生成、查看、修改、审批和阶段推进使用同一份职责来源。
### Requirements
**权限与配置**
- R1. 仅系统管理员可开启或关闭系统级「允许编制人兼任审核、批准」权限,默认关闭。
- R2. 仅权威项目创建者可为自己创建的项目逐文档选择兼任模式;普通成员、项目角色管理员和其他项目创建者不能设置。系统管理员如果不是该项目创建者,也不因此获得逐文档配置权。
- R3. 每份文档独立选择,管理员开启总权限不自动修改任何项目或文档;新文档、新实例和复制产生的文档默认不继承兼任授权。
- R4. 兼任文档必须指定一名有效、在任的项目成员为编制人;可以不是创建者。审核与批准由该人承担,不能再指定其他审核人或批准人。
**审批与可见性**
- R5. 兼任模式属于纳入人工审批:保留送审→审核→批准三个动作、现有内容锁和驳回要求;不得生成完成后自动批准或通过阶段门禁。
- R6. 未开启兼任的文档继续遵守当前三职分离与可选免审批规则;必需文档不得借兼任模式省去编制人或审批。
- R7. 设置页、冻结快照、文档详情、操作按钮、签署展示与日志一致显示兼任关系;同一个人能在正确状态执行对应职责动作。
- R8. 兼任不授予系统管理员、创建者或其他成员代审权,也不扩大跨项目读取、非当前阶段写入和已结束实例写入权限。
**生命周期与持久化(已审核批准,2026-09-17)**
- R9. 首期仅在工作流激活前配置;激活时冻结该文档模式和职责,运行中的实例不直接改规划。已激活的存量项目不自动转换。若用户要求运行中转换,必须先扩展本方案的受控职责变更单元,不可悄悄放开现有 PUT。
- R10. 管理员关闭总开关后,禁止新启用、保存仍含兼任的规划和激活兼任规划;允许清除兼任后保存。已激活的兼任实例按冻结授权继续执行,历史日志不变。界面必须解释该开关是「授权新配置」,不是紧急停用所有存量审批;本期不提供针对已激活实例的紧急撤销/熔断能力。
- R11. 模式、编制人、授权依据、配置版本及各步骤日志需持久化,刷新、重登和服务重启不得丢失。
- R12. 编制人离任或账号停用后,不得继续执行三项职责;阻断尚未完成动作并展示原因,不自动找替代人,不重写历史签署。
### Permission Matrix
| 操作 | 系统管理员但非项目创建者 | 当前项目创建者 | 普通项目成员 | 其他项目用户 |
|---|---|---|---|---|
| 修改系统总开关 | 允许 | 仅同时为系统管理员时 | 禁止 | 禁止 |
| 查看本项目可用模式 | 沿用当前项目读取权限 | 允许 | 沿用项目读取权限 | 禁止 |
| 规划期逐文档启停兼任 | 禁止 | 总开关开启才可启用;可关闭 | 禁止 | 禁止 |
| 指定编制人 | 禁止 | 规划期按 R4 | 禁止 | 禁止 |
| 送审、审核、批准 | 仅自己是该文档指定职责人时 | 同左 | 同左 | 禁止 |
| 已激活实例直接改职责 | 禁止 | 禁止(R9) | 禁止 | 禁止 |
### Mode Matrix
「文档启用」「纳入人工审批」「编制人兼任」是不同含义,不能复用一个开关。
| 文档状态/配置 | 输入 | 有效职责 | 审批与门禁 |
|---|---|---|---|
| 文档禁用 | 不设置职责 | 无 | 沿用 skipped_disabled |
| 可选文档免审批 | 三职全空,兼任关闭 | none | 沿用既有免审批规则 |
| 标准人工审批 | 三职齐全且三人不同 | full | 保留正常人工审批 |
| 兼任人工审批 | 兼任开启,仅编制人 A | author_only;有效三职为 A/A/A | 与标准审批同样要求最终批准 |
| 未开兼任却只填 A | 缺审核和批准 | partial | 拒绝 |
| 标准模式填 A/A/A | 三职同人 | 非法 | 继续拒绝职责分离违规 |
| 兼任开启但无 A | 缺编制人 | 非法 | 拒绝 |
| 兼任开启又填不同审核人 B | 矛盾输入 | 非法 | 拒绝,不能静默吞掉 B |
### User Flows
1. 管理员进入「系统管理台→系统设置→工作流治理」,开启总授权;页面显示保存结果、修改人和修改时间。
2. 创建者进入项目设置,展开某个阶段,在文档行开启「由编制人兼任审核、批准」。只保留编制人选择器,其余两项显示「同编制人(自动承担)」。其他文档保持原配置。
3. 保存并预览:摘要列出标准审批、兼任审批、免审批的份数,列出每份兼任文档及编制人。确认后冻结。
4. 编制人完成内容后送审,在审核中以审核人身份确认,在批准中以批准人身份确认;日志展示同一人对应三个职责,而非三个虚构人员。
5. 页面刷新、重新进入项目后仍显示同样配置;最终批准后才按现有阻塞条件满足阶段门禁。
### Scope Boundaries
本期覆盖所有通过项目工作流实例管理的文档,不针对某个任务名写白名单;freeform 文档与未绑定工作流的旧文档不提供此开关。不新增批量全选、不改项目成员全局 `document_duty` 为多角色,不自动改已发布工作流模板或历史签署。
**生命周期口径(已审核批准,2026-09-17):** R9 首期仅激活前配置、激活后冻结职责;R10 关闭总开关后禁止新启用/保存仍含兼任的规划/激活兼任规划,已激活实例按冻结授权继续执行。总开关是「授权新配置」,**不提供**已激活实例的紧急撤销/熔断能力;若业务需要合规级紧急止损,应作为独立后续方案,不在本期 Definition of Done 范围内。
---
## Planning Contract
### Current Implementation Evidence
以下为源码确认事实,不是运行验收结果。
| 位置 / 符号 | 当前行为 | 对本需求的影响 |
|---|---|---|
| `internal/projectinstance/types.go`:DocTaskPlan / DocDuty | 仅 enabled、approval_configurable 和三职 ID,无逐文档兼任标记 | 增加显式职责模式 |
| `internal/projectinstance/duty_mode.go` | none/partial/full;partial 拒绝;三职重复报 SEPARATION_OF_DUTY_VIOLATION | 不能只填作者或仅关闭分离校验 |
| `internal/projectinstance/validator.go`:validateActivationPlan / previewSummary | 激活至少 countFullDutyDocs>0;预览统计 full/none | 必须把合法兼任计为受治理文档 |
| `internal/projectinstance/service.go` | 创建者可保存/预览/激活;active 后 ErrPlanFrozen;已有 revision、plan hash、token | 复用规划流程,补全授权版本和事务检查 |
| `internal/projectworkflow/service.go`:IsProjectCreator | 权威项目创建者检查 | 不使用 UI 当前角色或项目 manager 代替 |
| `internal/projectinstance/store.go`:sync 子实例逻辑 | 从规划写 project_doc_task_instances 和三职 assignment | 兼任需派生三项实际职责,不能只存作者而漏审批归属 |
| `internal/projectinstance/duty_action.go` / `stage_access.go` / `gate.go` | 按动作校验单一职责;阶段可见性有 full 判定;门禁依赖 approved | 校验与阶段可见性都需认识新模式 |
| `internal/sysadmin/settings.go` / `store.go` | 白名单设置、DB 持久化;无该 key;只记录最后修改人时间 | 可复用管理入口,新增策略消费与历史审计 |
| `internal/server/admin_system_handlers.go` | 所有系统设置写入 requireSystemAdmin | 复用该入口,不开放管理列表给普通成员 |
| `internal/docduty/store.go`:HealProjectDocuments | 按项目成员默认职责扫描并回填所有 task_key 非空文档 | 可能覆盖逐文档三职,必须区分实例绑定与旧默认 |
| `internal/bizdev/service.go` / `internal/docgov/project_docs.go` | 生成后、列表读取时调用 HealProjectDocuments | 重开页面即可触发回填,必须验证刷新后仍一致 |
| `internal/docduty/revoke.go` | 成员职责变化撤销审核/批准槽位,随后参与 heal | 不能把项目默认职责变化误当成逐文档兼任变更 |
| `internal/server/handlers.go`:三个 DocGov 决议 handler | 使用登录身份及动作固定 author/reviewer/approver;先执行工作流鉴权 | 服务端已有按动作身份模型,应保留 |
| `internal/docgov/state_machine.go` | drafting/reviewing/approving/approved;检查对应职责 ID;无额外三人不同判断 | 复用状态机,测试身份一致和锁定边界 |
| `web/src/lib/currentDocRole.ts` | author 命中后立即返回,不支持同时三职 | A/A/A 会一直被当成 author |
| `web/src/lib/docGovActionVisibility.ts` / `DocGovActionBar.tsx` | 按单一 currentRole 显示送审/审核/批准 | 必须改为动作能力或多职责判断 |
| `web/src/lib/projectSettingsDuties.ts` / `ProjectSettingsModal.tsx` | 重复服务端 full/none 校验,人工审批默认要求至少三人 | 单成员兼任会被前端提前挡住 |
| `deploy/postgres/goose/00017_2026-09-12-project-workflow-instances.sql` | assignment 唯一键是任务实例+职责,无跨职责用户唯一限制 | 同一用户可有三条职责记录,不必拆用户身份 |
| `deploy/postgres/goose/00049_2026-09-17-system-settings.sql` | system_settings 已存在 | 采用增量迁移,不重建设置机制 |
相关历史边界参见 `.doc/test-reports/2026-09-14-governance-action-level-authz-test-report.md` 与 `.doc/test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md`。它们说明已有验收意图,本次未重跑其测试。
IDE 所列 rdev 设计、short-term 和 backlog 当前位于 `feature/rdev-template-depth` 的独立工作区,不在本方案 dev 基线;已读取作兼容输入。rdev 的关闭文档/N/A、阶段前置、任务键命名空间化保持原语义。本方案按实例+阶段+任务身份绑定;待 rdev 合入后增加对应回归,不宣称其已在 dev 发布。
### Key Technical Decisions
- KTD1. 新增 `duty_policy`,值为 `separated` / `author_only`,属于 DocTaskPlan 的逐文档配置。缺省按 separated 解读;none/partial/full 仍是职责完整度,不能把「免审批」和「兼任」混为一谈。统一提供按任务解析模式、有效职责、是否受治理的领域能力;原 ClassifyDocDuty 保留给旧调用,治理调用迁到新解析器。(R3–R6)
- KTD2. 配置快照保存用户意图:author_only 的 duties 规范形式只含 author_user_id。服务端通过唯一解析器派生有效 A/A/A,写三条 document_duty_assignments,并投影到 document_records 的三个 ID/名称。读接口区分配置职责与有效职责,客户端不得把有效 A/A/A 原样误写成标准配置。(R4、R11)
- KTD3. 新设置 key 建议 `workflow.allow_author_only_approval`,类型严格 bool,默认 false,无环境变量绕过,保存无需重启。projectinstance 通过窄的策略读取接口消费,由 app 装配注入;不从领域服务调用 HTTP,不让 projectinstance 成为 sysadmin 设置表的第二写入 owner。(R1)
- KTD4. 配置写入、预览和激活都复核总授权;真正激活必须在事务内对授权版本复核,并与关闭总开关串行化。token 绑定 plan hash、项目/规划版本、授权 revision。总开关 false→true 后旧 token 仍作废,不能以「当前又是 true」放行。(R10、R11)
- KTD5. 实例绑定文档的职责权威是冻结 DocTaskPlan,经解析生成 assignments 和文档投影。项目成员 document_duty 只供旧无实例文档的默认分配。heal/revoke/生成/通知不得再次用项目默认人员覆盖实例文档。(R3、R7、R12)
- KTD6. 运行时按具体动作检查有效职责和当前在任状态;状态机仍按 author/reviewer/approver 记录实际动作角色。前端采用服务端动作能力集驱动按钮,可同时拥有多个职责,保留 viewer fail-closed,不新增一个可以绕过所有检查的万能角色。(R5、R7、R8)
- KTD7. 遵守 R9 的冻结边界;未知 mode、缺失授权来源或绑定不唯一时拒绝写动作。历史缺字段只代表旧 separated,不自动解释为兼任;不能全库 A/A/A 回填。(R6、R9、R11)
### Data Model
以下是设计契约,字段落位按 owner 边界实现,不是现有字段清单。
| 数据 | 建议新增/扩展 | 用途与兼容 |
|---|---|---|
| system_settings | 目标 key;monotonic revision(默认 0) | 总权限 CAS、token 失效;目标行在迁移时初始化 false,避免无行锁问题 |
| 系统设置审计 | 仅本策略必需的 before/after、revision、actor、时间、request ID | 与设置更新同一事务提交;不把整站审计改造扩大到本期 |
| DocTaskPlan JSON | duty_policy,可选且旧值缺省 separated | 逐文档意图,纳入 plan hash;兼容 old hash 的序列化须有固定样本 |
| workflow instance 授权快照 | policy key、revision、允许状态、activated_by/at | 记录激活时获准的依据;由服务端生成,拒绝客户端伪造 |
| activation token | policy revision(新字段或令牌存储的版本化元数据) | 防预览后管理员撤销授权;旧 token 含兼任无 revision 必须重新预览 |
| document_records | doc_task_instance_id 可空外键 | 对新实例创建文档强制绑定;旧文档仅唯一匹配才回填,不修改历史职责 |
| document_duty_assignments | 复用三角色,兼任三行 user_id 相同 | 无需放宽角色唯一约束;author 必须有效且正数 |
| 文档视图 | duty_policy、effective_duties、allowed_actions、blocked_reason | 以服务端计算值展示;读参数不能切换权限 |
| 文档审计 details | duty_policy、instance/task ID、授权 revision | 送审/审核/批准均记录真人身份及该次 action role |
不预占 Goose 序号:实施时根据 dev 与并行 rdev 分支最新迁移取下一个空闲序号。迁移需覆盖 PG store 与 memStore 的字段 round-trip。兼容旧数据时禁止把 NULL 改成 0 外键。
### High-Level Technical Design
职责解析链:
```mermaid
flowchart TB
A[管理员总授权] --> B[创建者逐文档配置]
B --> C[保存与预览校验]
C --> D[事务内复核授权并激活]
D --> E[冻结实例配置与授权依据]
E --> F[统一解析有效三职]
F --> G[职责表与文档人员投影]
F --> H[动作鉴权和阶段可见性]
H --> I[前端能力与操作按钮]
G --> J[文档状态机与审计]
```
兼任保留原审批状态机:
```mermaid
stateDiagram-v2
drafting --> reviewing: A以编制身份送审
reviewing --> approving: A以审核身份通过
reviewing --> drafting: A审核驳回并填写原因
approving --> approved: A以批准身份通过
approving --> drafting: A批准驳回
approving --> reviewing: 现有配置允许时退回审核
```
新授权和冻结授权的判断路径:
```mermaid
flowchart TB
A[请求] --> B{规划配置或激活?}
B -->|是| C{权威创建者且planning?}
C -->|否| X[拒绝]
C -->|是| D{含author_only?}
D -->|否| E[原职责规则]
D -->|是| F{总授权有效且版本一致?}
F -->|否| X
F -->|是| G[检查作者与输入一致性]
B -->|运行时动作| H[查冻结策略及实例任务绑定]
H --> I[检查成员有效性 当前阶段 状态和租约]
I --> J[按动作职责执行]
```
激活事务与设置撤销都以策略行锁形成先后顺序,再按统一顺序获取项目职责锁和实例相关行锁。策略 owner 提供事务兼容读取/锁定适配;不能照搬在事务外重查布尔值的方式。原则:关闭先提交则激活失败;激活先提交则成为 R10 中可继续的存量实例。并行成员移除与激活也必须在同一项目职责锁语义下判定,不能在事务开始前检查后直接信任。
### API Contract
| 接口 | 变更 | 服务端强制条件 |
|---|---|---|
| GET/PUT `/api/v1/admin/system/settings[/{key}]` | 注册总开关;目标 key 增加 expected_revision,返回新 revision | requireSystemAdmin;严格拒绝 null、字符串布尔;审计与值同事务 |
| GET `/api/v1/projects/{id}/settings` | 返回精简 governance_policy capability、revision 与 blocked_reason | 保留项目访问校验;不泄露其他系统设置 |
| PUT `/api/v1/projects/{id}/workflow-plan` | 每个文档可传 duty_policy;兼任只传 author ID;沿用规划版本 | 创建者、planning、总授权、有效成员、输入无矛盾 |
| 激活 preview / activate 现有接口 | 预览分列兼任文档;token 绑定策略 revision | 保存成功不等于已获激活授权;提交时重新事务校验 |
| 文档详情和项目文档列表 | 返回模式、有效三职与允许动作 | 统一来源;任务身份、实例身份须匹配 |
| docgov 送审/审核/批准接口 | URL不变,增加模式审计上下文 | 登录用户+对应 action,不信任请求的 user_id/user_name |
建议新增错误码:`AUTHOR_ONLY_POLICY_DISABLED`(403)、`AUTHOR_ONLY_POLICY_CHANGED`(409)、`AUTHOR_ONLY_AUTHOR_REQUIRED` / `AUTHOR_ONLY_DUTY_CONFLICT` / `UNKNOWN_DUTY_POLICY`(400 validation issue)、`DUTY_BINDING_AMBIGUOUS`(409)、`DUTY_ASSIGNEE_INACTIVE`(403)。总权限存储不可用返回 503;缺失目标配置采用默认关闭,但数据库故障不能伪装成正常缺项。保留已有 PLAN_FROZEN、PLAN_REVISION_CONFLICT 与 SEPARATION_OF_DUTY_VIOLATION。
`author_only` 写入审核/批准 ID:省略或 0 为规范输入;若为与作者相同的正数,可规范化为省略以兼容回显,但若不同则拒绝。关闭兼任时清除派生审核/批准,要求重新选择符合分离规则的人员;旧选择可仅作为未保存草稿提示,不自动恢复为真实授权。
### UX Details
系统设置开关说明写明 R10,并展示预计受影响的待激活兼任文档数量及存量继续执行说明。保存失败保留用户输入和错误,不在本地假装开启成功。多管理员同时修改返回版本冲突,不自动覆盖。
项目设置按文档行提供兼任选项;总权限关闭时禁用并解释来源;非创建者只读。兼任只能在文档已启用且纳入人工审批时选择。兼任文档仅需一位成员;混合方案只要仍存在标准人工审批文档,才继续提示至少三位有效人员。
总开关在页面打开期间被关闭时,保存失败展示定位到文档的原因,提供关闭兼任选项;不丢弃整份未保存规划,不自动重试激活。预览和冻结视图同时展示「角色指派数」和「实际人数」,避免 A/A/A 被误认为三个人。
文档正文签署区显示真实姓名及兼任标记,但未发生审核/批准时不得显示签署时间或声称已通过。按钮随状态变化,审阅阶段即使当前人也是作者也不能编辑锁定正文;驳回后恢复编辑。查看/认领按当前状态或明确动作记录相应角色,不能打开一次页面就伪造三次履责。
### Risks and Compatibility
1. **回填覆盖(硬性门禁,非偶然安全):** `HealProjectDocuments` / `ApplySlotRevocations` 与 `ConfigSnapshot` 是独立职责写路径,当前不区分实例绑定文档。实现必须在 heal/revoke 增加「实例绑定文档跳过项目默认覆盖」显式分支,禁止依赖「只填缺失槽位、碰巧不覆盖」的偶然安全。U3 必须对三入口(文档生成、列表 GET、成员变更)及 author 被误判非在任时的 healSlot 分别证明投影不变;未通过不得开放 UI。
2. **历史身份混淆:** 不以 project_id+task_key 跨实例盲绑;旧文档匹配多实例则保持原记录并报可定位问题。新生成文档必须携带 task instance ID,无法绑定应停止受控写入。
3. **成员退出:** runtime 复核在任资格覆盖 author_only;保留冻结快照用于历史展示。普通成员默认职责改变不得影响冻结文档;真实退出/停用应阻断动作。暂不新增运行中换人 UI。
4. **并发审批:** 同一人可打开多个标签,服务端仍需保证状态比较/版本检查;重复请求不能重复创建批准事件、版本封存或推进通知。延迟到达的审核请求不能作用于后续修订版本。
5. **通知与事件:** 审核待办发给同一人是有效业务,不可因发送者=接收者一概过滤。按事件+接收者去重,不把审核与批准两项待办合并成一个动作。
6. **回滚:** 关闭开关只停止新配置,不能安全地把已存在兼任实例交给完全不识别新模式的旧二进制。上线后若需回退代码,保留模式识别与冻结策略读取兼容补丁;不得通过清空审核/批准人员回滚。
7. **总开关非紧急熔断(R10):** 关闭总授权不会阻断已激活兼任实例的剩余送审/审核/批准。界面与运维说明必须写明这一点,避免被误解为「关总开关=紧急止损」。存量紧急撤销不在本期范围。
---
## Implementation Units
### U1. 策略存储与总授权
目标:提供管理员可写、项目治理可可靠消费的总授权。覆盖 R1、R10、R11,采用 KTD3、KTD4。
文件:`internal/sysadmin/settings.go`、`store.go`、`internal/server/admin_system_handlers.go`、`internal/app/` 装配、增量 Goose 迁移;必要时新增 sysadmin 内的策略审计存储文件。
实现重点:默认关闭;严格 bool;目标设置 revision 与 CAS;事务内审计;窄接口可参与激活事务。仅本 key 要求的新协议不破坏其他设置键调用。
测试场景:管理员开关成功;普通用户伪造 PUT 被拒;null/字符串拒绝;DB断开不放行;并发修改只一个版本成功;审计写失败时设置回滚;重启读回。
### U2. 逐文档模式、规划校验与激活
依赖 U1。覆盖 R2–R6、R9–R11,采用 KTD1、KTD2、KTD4、KTD7。
文件:`internal/projectinstance/{types,duty_mode,validator,service,store,hash,tx,errors}.go`、`internal/server/project_settings_handlers.go`。
实现重点:新增模式解析;所有 full-only 分支改为正确的受治理判断;保存、预览、激活一致;任务禁用/免审批清除模式;有效成员检查;规划 hash/授权 revision 和确认 token 一致。保存快照与提升 plan revision 应原子化,失败不能留下可读取的新规划配旧版本。
测试场景:一位成员、至少一份合法兼任文档可激活;只填作者但未开模式仍拒绝;混合 full/none/author_only;其他项目创建者、非创建者管理员拒绝;修改总授权后旧 token 拒绝;激活与撤销并发的两种提交顺序;旧 separated snapshot/hash 兼容。
### U3. 文档绑定与职责投影一致性
依赖 U2;这是开放 UI 前的必要门禁。覆盖 R3、R4、R7、R11、R12,采用 KTD2、KTD5。
文件:`internal/docduty/{store,resolve,revoke}.go`、`internal/docgov/{types,engine,project_docs,repository}.go`、`internal/bizdev/service.go`、`internal/projectinstance/store.go`、任务执行请求与 app 适配、增量迁移。
实现重点:新文档绑定具体任务实例;受治理实例职责优先;统一有效职责映射用于创建、读取、heal、memStore;legacy fallback 仅在明确无实例时可用。`HealBinding`/`healSlot`/`ApplySlotRevocations` 对已绑定 `doc_task_instance_id` 的文档必须显式跳过项目默认覆盖,不得因 author 被误判非在任而重新分配默认人。旧已批准文档不因新功能读取被改写签署人员。
测试场景:同项目两份兼任文档由不同作者承担;第三份标准审批三人;第四份 none;反复 GET/成员默认角色调整/重启后四份职责均不串;未知或歧义绑定阻断;旧无实例文档仍按既有规则;NULL外键正常。**硬性投影稳定性(开放 UI 前门禁):** 已激活 author_only 文档在以下三入口触发 `HealProjectDocuments` 后,`document_records` 与 assignments 投影必须保持 A/A/A——(1) 仅刷新文档列表(`ListWorkflowDocumentsByProject`);(2) 文档生成完成(bizdev);(3) 成员变更后 heal。另测:author 被误判为非在任成员时,healSlot 不得把审核/批准槽位改写为项目默认人;真实离任仍按 R12 阻断写动作且不自动替人。
### U4. 动作鉴权、文档状态机与事件
依赖 U3。覆盖 R5、R7、R8、R12,采用 KTD6。
文件:`internal/projectinstance/{duty_action,document_access,stage_access,gate}.go`、`internal/server/{stage_access_helpers,handlers,document_revision_access}.go`、`internal/app/docflow/`、`internal/docgov/`、相关通知订阅与审计视图。
实现重点:有效三职与在任状态统一判定;三个动作使用不同 action role;归档/修订账本与事件沿用既有事务机制;审核、批准不能跳状态,租约和内容 hash 不因同人而失效。Audit details 增加模式及来源。
测试场景:A顺序三动作成功且三份日志身份真实;其他成员/创建者/管理员越权失败;作者退出后全部写动作拒绝;审核中改正文失败;驳回原因必填;跨标签重复批准只产生一次有效终态事件;审批针对旧版本内容被拒;阶段直到最终批准才可推进。
### U5. 系统设置与逐文档 UI
依赖 U1、U2,可与 U3/U4 开发隔离进行,联调必须等待后端完整。覆盖 R1–R4、R7、R9–R11。
文件:`web/src/components/admin/console/sections/SettingsSection.tsx`、`web/src/components/project/ProjectSettingsModal.tsx`、`web/src/lib/projectSettingsDuties.ts`、`web/src/types/projectSettings.ts`、`web/src/api/projectSettings.ts`。
实现重点:按 UX Details 配置、错误定位、人数要求、预览和冻结展示;策略 capability 来自项目 settings,而非向普通用户开放 admin settings。文档模式在不同阶段展开折叠后不串行。
测试场景:单成员可配置兼任;混合标准模式仍提示三人要求;非创建者只读;系统开关关闭时禁用及保存失败保留草稿;切换文档、刷新、重新登录后模式不变;已激活项目仍冻结。
### U6. 多职责动作展示和真实闭环验收
依赖 U3–U5。覆盖 R5–R8、R11、R12,采用 KTD6。
文件:`web/src/lib/{currentDocRole,docGovActionVisibility,controlledDocHydrate,deliverableSync}.ts`、`web/src/components/doc/DocGovActionBar.tsx`、`web/src/App.tsx`、文档 API/types、相关 UI/PG/真实 PI 测试与报告。
实现重点:消费服务端动作能力,多职责不再被 author-first 短路;认领、提案、修订、按钮与日志一致;受控文档不按名字提权。证明刷新及重启保持一致后再开启真实项目配置。
测试场景:真实产品 PI 生成→A打开文档→送审→审核→批准→版本/日志→阶段门禁;标准和免审批文档并存;不同用户负例;两标签并发、刷新重开、重启;rdev 合入后复验 rd_ 文档及旧键兼容,不改 N/A 行为。
---
## Verification Contract
本方案阶段未运行业务测试,以下为实现阶段必须提交的证据。
| 层级 | 覆盖 | 通过标准 |
|---|---|---|
| Go 单元 | 策略值、模式解析、权限矩阵、状态、门禁、hash | 所有模式边界及错误路径可重复验证 |
| PostgreSQL 集成 | 设置审计原子性、并发撤销/激活、成员退出、三职责落库、投影绑定;HealProjectDocuments 三入口对实例绑定 author_only 文档投影不变 | 实际事务交错结果符合 KTD4;失败不留下半成品;列表 GET/生成/成员变更均不得覆盖冻结 A/A/A |
| 前端单元/构建 | 单成员配置、双层开关、多职责按钮、错误恢复 | 测试与构建通过,无同人只见作者按钮 |
| HTTP 负例 | 修改请求身份、跨项目、非创建者、未知模式、关闭总授权 | 服务端拒绝,不能依赖隐藏按钮 |
| 浏览器 E2E | 管理员开关→创建者逐文档设置→A全部动作→其他人被拒 | 真页面操作、日志可见;无 API 直写替代关键步骤 |
| 产品 PI E2E | 正式生成及既有修订/租约流程 | 使用仓库要求的真实产品 PI + MiniMax;stub 仅作前期定位 |
| 持久化 | 刷新、重开、重登、服务重启 | 模式、职责、审核状态、版本和审计一致 |
| 回归 | 既有 full/none、标准三人分离、freeform、legacy、终止实例 | 原有权限和生命周期边界不退化 |
实现时执行 PROJECT 规定的 `go vet ./...`、`go test -short ./...`、前端 `npm test` 与 `npm run build`,以及使用隔离测试库的 PG 集成和明确启用的真实 PI 测试。不得把 skip 当 pass。共享容器重建验证必须在主仓占 CURRENT 集成槽位后执行;worktree 不启停共享容器。
重点验收样例:
- AE1(R1–R4):管理员开启后,创建者在文档甲选择 A,在文档乙选择 B;甲/乙有效三职分别为 A/A/A、B/B/B,互不影响。
- AE2(R5–R8):A只能按状态依次送审、审核、批准;未批准前门禁阻塞;另一个管理员无该文档职责仍被拒。
- AE3(R6):总开关开启但文档未勾选,A/A/A仍拒绝;三职空仅对原来允许免审批的文档合法。
- AE4(R10、R11):预览后总开关关闭再打开,旧 token 409;已先完成激活的实例刷新后仍可按冻结策略办理。关闭总开关不得阻断已激活实例的剩余审批动作(非紧急熔断)。
- AE5(R7、R11):项目成员默认审核人改为 C 后,读取兼任文档仍显示 A/A/A,不改历史签署;列表、正文及按钮一致。
- AE5a(R7、KTD5):已激活 author_only 文档在仅刷新文档列表(触发 `ListWorkflowDocumentsByProject` → `HealProjectDocuments`)后,投影仍为 A/A/A,不被项目默认职责覆盖。
- AE5b(R7、KTD5):文档生成完成与成员变更后 heal 两入口分别复测 AE5a;author 被误判为非在任时,healSlot 不得把审核/批准槽位改写为项目默认人。
- AE6(R12):A离任后保持历史名字,但所有新动作拒绝,不能被 heal 自动替换或按名字回退提权。
---
## Definition of Done
- [x] R9、R10 的生命周期口径经过用户审核(2026-09-17):批准「激活前配置 + 激活后冻结」与「关总开关仅停新配置、存量按冻结继续」;明确总开关不提供存量紧急熔断,该能力如需另立方案。Heal 三入口投影稳定性已升为 U3/Verification 硬性验收项。
- [x] U1–U6 全部完成且证据覆盖对应需求;管理员和创建者两个权限层级均在服务端生效。(short-term U1–U6 均为 `done`;U6 报告回链)
- [x] 配置、快照、assignments、document_records、前端、审计在同一任务身份下对齐。(U2–U4 + U6 闭环证据;规范存储仅 Author + 有效 A/A/A 投影)
- [x] 单成员兼任完整链与三人标准链均通过;不得只提交设置页截图。(U4 矩阵 + U6 HTTP/浏览器证据;标准分离回归见 U4/U2 单测)
- [x] PostgreSQL、真实产品 PI、浏览器、重启与跨用户负例分别标明结果及限制;AE5a/AE5b 必须有证据。(U3:`TestHealProjectDocuments_SkipsDutyLocked_PG` 等 duty_locked 过滤;U6:既有 PI 生成文档 + Playwright 徽标 + lizhuguan 403。限制:U6 未单独跑「刷新/重登/重启」专轮,依赖 schema 持久化与 rebuild 后复测)
- [x] `.doc/test-reports/` 有验收报告并回链任务和 FEATURE-MATRIX;无新增已确认发布 blocker 才保持 gap-matrix 原结论。([U6 报告](../test-reports/2026-09-17-document-author-only-u6-test-report.md);变更提案 HTTP 另记 [audit](../audit/2026-09-17-docgov-modification-proposal-http-gap.md),不升为发布 blocker)
- [x] 发布先迁移与部署识别新模式的服务,再开放总授权;默认 off,试点后扩面。推送、dev集成与环境晋升状态分别报告。(**dev 已合入并 rebuild**:`merge: feature/document-author-only-plan` @ `09a9921`,health `schema_version=52`,总开关默认 off。**未做**:push origin/dev、test/main 晋升、开放总授权试点——需另授)
@@ -0,0 +1,214 @@
---
title: "首次加载与工作台初始化性能改进方案"
status: planned
created: 2026-09-17
updated: 2026-09-17
artifact_contract: ce-unified-plan/v1
product_contract_source: ce-plan-bootstrap
execution: code
---
# 首次加载与工作台初始化性能改进方案
## Goal Capsule
让用户首次访问就能快速看到并操作登录页,登录后优先恢复当前项目与会话,避免下载无关工具或等待所有项目初始化。
采用静态交付优化、按功能加载和请求去重,之后按测量结果优化认证与数据库读取(KTD1–KTD5)。本轮仅交付诊断和方案,业务代码尚未修改;用户授权实施后执行以下单元。
遵守 AGENTS.md/PROJECT.md、现有权限和文档治理契约。若优化要求改变授权、新增跨用户缓存、跳过职责正确性或删除历史数据,停止该单元并回报。每单元独立 feature/fix 分支与模块 mutex;合 dev/容器重建占集成槽。默认不推送,不晋升 test/main。
## Product Contract
### Problem Frame
[诊断](../audit/2026-09-17-initial-load-performance-audit.md) 已确认:8080 首屏 2.86 MB,CDP 10 Mbps 冷缓存登录可见 2.64 秒、2 Mbps 11.78 秒;再次访问约 60 ms。字体 CSS 外链阻塞首屏;3100 Vite 首访 207 请求/12.24 MB。登录后存在全项目成员扇出与会话重复同步,服务端认证、文档列表和会话统计有重复工作。
这些数字是单样本实验,不是用户实际公网体验或 p95。用户已确认 3100/8080/8081 在系统重启后首访约十数秒。现有容器启动到打印监听仅约 166/142 ms,不代表整机重启就绪;必须补齐重启矩阵再签优化收益。
### Requirements
- R1. 首次登录页只加载认证与基础样式所需资源,外部字体不可阻塞登录表单。
- R2. 登录后先显示可用工作台骨架,优先恢复当前项目/会话;其他项目成员、管理台、导出、文件预览在需要时加载。
- R3. 相同身份和查询键的初始化请求去重;慢响应、快速切换项目、登出/换人不会写回旧状态。失败必须有局部错误与重试入口。
- R4. 所有服务端授权和文档治理保持正确,权限撤销/停用不得因缓存继续放行。计数、摘要与正文沿用相同可见性语义。
- R5. 发布后旧页面仍可打开延迟模块;缓存不得导致 HTML 长期陈旧,也不得泄露用户 API 数据;SSE 流式延迟不能回退。
- R6. 优化收益用可复现冷/热缓存、慢网、字体不可达、多项目和大历史场景证明,结果与镜像/资源 hash 绑定。
### Success Criteria
以下是**拟定验收预算**,不是当前已达标数据。表中静态资源体积及绝对首屏时间预算适用于 8080/8081 构建入口;3100 保留 Vite 开发模式,不套构建产物压缩体积预算,其保留/空依赖缓存与预热状态分别由 U1 固定加载时间预算,U7 检查重启改善;U1 固定机器、Chromium 版本、样本与网络条件,预算不得在看到失败后悄悄放宽。
| 指标 | 目标/口径 |
|---|---|
| 未登录关键 JS 总传输量 | 开启压缩后 ≤250 KiB;按首屏实际请求总和而非只看入口文件 |
| 普通工作台首次可用前 JS 总量 | ≤600 KiB;不含用户明确打开的文档预览/导出模块 |
| 冷缓存登录可操作 | 10 Mbps / 80 ms、CPU 4 倍减速下 p75 ≤1.5 s;2 Mbps 同配置 p75 ≤3 s |
| 登录态热刷新 | 10 Mbps / 80 ms、CPU 4 倍减速下工作台可操作 p75 ≤1.5 s;前提必要 API 达下行预算 |
| 登录态冷刷新/登录提交成功后恢复 | 冷刷新自 navigationStart 起、登录自成功响应起,当前会话历史及输入区就绪 p75 ≤3 s;仅骨架不算完成 |
| 必要首屏 API | 同宿主 app↔DB 网络下 p95 ≤300 ms;列表大数据场景 p95 ≤500 ms,接口错误率不增加 |
| 首屏初始化请求 | 项目成员初始化从 N 次降为当前项目最多 1 次;静止初始化每个会话列表查询键最多 1 个在途请求且成功后不被成员更新重触发 |
| 字体故障 | Google 域名完全阻断或延迟 10 秒时,仍满足登录预算,不发首屏外部字体 CSS 请求 |
| 无回归 | 同数据/设备各阶段 p95 不劣化超过 10%;无新增跨用户暴露、错误循环、重复写任务 |
浏览器每场景 ≥20 次,报告 p50/p75/p95 与原始样本;接口每场景 ≥100 请求、并发 1/10/30。浏览器 p95 仅小样本诊断,不能冒充线上 SLO;稳定发布后再累计真实用户分位数。
### Scope Boundaries
包括浏览器入口、静态资源交付、当前工作台数据初始化、与首屏相关的查询。没有业务语义变更,不调整 PI 模型、Prompt、文档租约时长、授权范围或工作流门禁。
Deferred to Follow-Up Work:Redis/CDN、新 SSR 框架、全面 App.tsx 重写、全站统一数据框架、数据库分库、文档全文缓存。只有 U1 的证据表明必要时另开任务;目前不需要先增加基础设施。
### Outstanding Questions
- 待补测:已知端口 3100/8080/8081,重启涵盖宿主机/应用/Vite 的具体范围、慢发生阶段、真实网络与设备;不会阻止可独立证明的 U2/U3,但阻止宣称用户现场问题已经彻底解决。
- 待补测:登录态瀑布、真实数据规模、SQL/连接池等待;U6 的查询改写/索引必须由这些证据选择。
## Planning Contract
### Key Technical Decisions
- KTD1. 保留 React/Vite + Go 架构。正式体验使用构建产物入口;3100 保留开发热更新用途,不把开发模块请求数量当生产目标。先确认真实反代 upstream,不盲改 FRP。
- KTD2. 首屏用系统字体栈;需要保留 Inter/JetBrains Mono 时仅选必需 WOFF2 并同源部署、按需加载。保留 KaTeX 渲染所需字体,但不要求登录页加载数学资源。
- KTD3. 按功能边界动态 import,登录壳与工作台隔离;管理台、DOCX/XLSX 导出、Word/Excel 预览、Mermaid 按使用加载。仅 manualChunks 拆文件不能减少关键路径下载,必须验证依赖图没有静态回引。
- KTD4. 现有 Go serveSPA 作为默认静态交付修复点,构建期生成 gzip/br(若工具链已支持)而非每请求高压缩。若真实统一代理已负责压缩,则由它单层处理并记录;不得重复编码。哈希资源 `public,max-age=31536000,immutable`;HTML `no-cache`;压缩变体 `Vary: Accept-Encoding`;用户 API 不共享缓存。保留 identity、HEAD、条件请求、Range 正确性。
- KTD5. 将请求状态按身份/项目/会话/过滤器键管理,先用局部 hook/loader 和在途合并解决,不强制引入新数据框架。身份切换清空缓存与取消在途请求,成员更新不作为会话获取的依赖。未知成员/权限不靠全量成员预取推导:使用服务端明确的当前用户权限摘要,未就绪保持 fail-closed。
- KTD6. 请求内复用已认证 principal,授权不跨请求长期缓存。减少 session 续期写入须明确 idle TTL/绝对过期/撤销语义后再落地,保留停用与撤销实时检查。
- KTD7. 文档列表先保留治理正确性;先补齐所有写路径与历史修复,再移出 GET 同步 heal。轮询保持原有租约新鲜度,优先复用 SSE/可见性控制与单请求在途,不能直接延长租约或无限延迟 busy 显示。
### High-Level Technical Design
```mermaid
flowchart LR
A[HTML与同源基础样式] --> B[轻量认证壳]
B --> C[认证结果与工作台模块并行准备]
C --> D[当前用户可见项目与会话]
D --> E[当前项目权限与聊天窗口]
E --> F[可操作工作台]
F --> G[按需管理台/导出/预览]
```
有保存会话时,可在校验期间预加载不含用户数据的工作台代码;受保护 API 与用户内容显示仍由认证门禁控制。无会话时不加载工作台代码。项目/会话列表在认证后并行,解析有效当前项目后再发其范围内请求;不是让全站等待所有项目成员。
```mermaid
sequenceDiagram
participant UI as 浏览器
participant API as Go API
participant DB as PostgreSQL
UI->>API: 首屏必要请求(按查询键去重)
API->>DB: 验证当前会话/用户状态
API->>API: 请求内复用 principal / 权限解析
API->>DB: 当前页/当前项目数据
API-->>UI: 权限范围内的结果
UI->>UI: 核对身份与查询代次后更新
```
## Implementation Units
### U1. 固定完整性能基线(P0,约 0.5–1 天)
**Requirements:** R6;后续全部单元的依赖。
**Files:** 新增 `web/e2e/initial-load-performance.spec.ts`、诊断指标辅助模块;更新 `.doc/test-reports/`。本轮探针与结果可作为起点。
**Approach:** 固定真实入口、部署 hash、登录角色、项目数/历史量,捕获资源瀑布、FCP/LCP、长任务、输入区与历史就绪、必要 API TTFB。用专用验收账号/夹具测登录,不在真实会话发送诊断消息。先检查 GET 副作用,文档列表暂有 heal,数据库分析使用只读事务和 statement_timeout。分别测空缓存、热缓存、10/2 Mbps、CPU 4x、字体失联、1/30/100 项目与大历史。本轮不重启共享服务;实施时 U7 在隔离环境重现应用/依赖/宿主启动过程,记录 ready 与第一次导航的时间关系。
**Test scenarios:** 新浏览器、保存有效/过期会话、无项目、普通成员与管理员、慢 API/失败、项目快速切换;每份结果保留参数与原始样本但无 token/用户正文。
**Verification:** 形成基线报告,能回答耗时在哪一阶段,并确认性能指标可重复。登录态测量缺失不得用未登录测试代替。
### U2. 修复字体与静态资源交付(P0,约 0.5–1 天) — **done 2026-09-17**
**Dependencies:** U1 的未登录基线;**Requirements:** R1、R5、R6;**Files:** `web/index.html`、`web/src/styles/index.css`、`web/vite.config.ts`、`internal/server/server.go`、新增 `internal/server/static_assets_test.go`;必要时实际 Docker 构建文件。
**Approach:** 按 KTD2/KTD4 去除外部阻塞 CSS、提供压缩变体与明确缓存头。缺失 `/assets/*` 返回 404,不回退 HTML;客户端路由仍允许 SPA fallback。发布资源保留至少当前与上一版本并明确旧标签页支持窗口;窗口外加载失败提示用户保留编辑后刷新,不自动刷新丢失草稿。
**Test scenarios:** gzip/br/identity 协商、q=0 禁用、Vary、GET/HEAD、304、Range、未知资源 404、客户端路由回退;字体域名黑洞仍出现表单;SSE 首事件/持续事件不缓冲;受保护 API 无 public 缓存;部署后旧标签页首次打开尚未加载的模块。
**Verification:** curl 与浏览器确认真正压缩响应,JS 传输量下降;HTML 不被长期缓存。此单元不宣称已达到拆包预算。
**交付证据:** [U2 测试报告](../test-reports/2026-09-17-initial-load-perf-u2-test-report.md);`dev` merge `feature/initial-load-perf-u2`;8080 主 JS br 传输 623,898 B;登录冷缓存可见 ~205 ms。U1/U3–U7 仍未完成。
### U3. 登录壳与重功能按需加载(P0,约 1–2 天)
**Dependencies:** U1;可与 U2 分开开发,合入仍串行。**Requirements:** R1、R2、R5;**Files:** `web/src/main.tsx`、`web/src/App.tsx`、新增认证壳组件、`web/src/components/doc/preview/FilePreviewPanel.tsx`、`web/src/features/replyExport/download.ts`、`web/src/engine/docxRenderer.ts`、`web/src/components/doc/blocks/MermaidBlockView.tsx`、U1 浏览器用例。
**Approach:** 按 KTD3 建立真实 lazy 边界;将工作台 hooks/缓存初始化移入工作台挂载周期。导出按钮点击才 import 引擎;预览根据文件类型加载;Mermaid 只在存在图块时加载。每边界提供局部加载/失败重试与错误边界。限定此重构服务于加载,保留既有文档编辑状态机。
**Test scenarios:** 未登录资源中不出现导出/预览/管理台/图表重模块;登录成功恢复当前会话;失效会话不展示缓存敏感数据;首次导出 DOCX/XLSX 内容有效;Word/Excel 预览、数学公式与 Mermaid 正确;动态 chunk 失败可以重试且不重复提交业务动作;首次打开功能耗时同时记录。
**Verification:** 满足 R1 首屏预算及功能按需请求证据,不把延迟全部转移成首次按钮不可用。检查 gzip 后所有首屏 chunks 总和。
### U4. 收敛初始化扇出与重复同步(P1,约 1–2 天)
**Dependencies:** U1、U3;**Requirements:** R2、R3、R4;**Files:** `web/src/App.tsx`、`web/src/api/projectWorkflow.ts`、`web/src/api/chatSessions.ts`、`web/src/data/storage.ts`、新增初始化 loader/hook 及其测试;必要时项目列表 DTO/服务端 handler 补当前用户成员摘要。
**Approach:** 当前项目成员优先,其他完整成员按打开面板加载;会话 fetch 依赖稳定身份/查询键,项目名称映射与网络获取分离;查询代次 + AbortController + 在途合并;每次成员响应不再全量写 projects/持久化。只有实测长任务证明需要时增加去重/批量保存,不把权威服务器文档写入延迟缓存作为成功。
**Test scenarios:** 1/30/100 项目首次请求数量稳定;成员结果乱序不会重复请求会话;快速切项目/登出/换用户不串状态;普通成员看到的项目/会话范围与改动前一致;错误后手动重试;成员增删后局部失效刷新;离线缓存不绕过权限验证。
**Verification:** 达到初始化去重预算,记录必要 API 次数与工作台就绪时间;跨用户负例、当前会话恢复、文档编辑刷新持久性通过。
### U5. 认证请求去重与续期写入收敛(P1,约 0.5–1 天)
**Dependencies:** U1 的认证测量;**Requirements:** R3、R4、R6;**Files:** `internal/server/auth_handlers.go`、`internal/server/auth_middleware.go`、`internal/auth/service.go`、`internal/auth/pg_store.go` 及相邻测试。
**Approach:** `/auth/me` 复用 middleware principal;合并会话及用户读取,避免重复查同一用户。先度量 session UPDATE 锁/连接等待;只有证明其成本且明确既有过期语义后采用有界续期/last_seen 写入策略。鉴权失败不缓存成成功,撤销/停用每请求生效。
**Test scenarios:** 同 token 1/10/30 并发;me 请求中只验证一次;撤销/停用后的下一请求拒绝;idle 边界/绝对过期/并发续期;DB 异常 fail-closed;匿名静态资源仍可访问。
**Verification:** 展示改前/后 DB 操作数、锁等待和 p95;身份安全回归通过。若节流会改变过期语义,则只交付请求内复用,将节流留待独立决定。
### U6. 按测量优化列表与租约读取(P2,约 2–4 天;按证据选子项)
**Dependencies:** U1、U4;**Requirements:** R2、R4、R6;**Files:** `internal/docgov/project_docs.go`、`internal/docduty/store.go`、成员/职责写路径、`internal/ctxmgr/chat_history.go`、`internal/projectworkflow/store.go`、`web/src/App.tsx` 及相邻 PG/浏览器测试;确需索引时新增 Goose migration。
**Approach:** (a) 先验证成员创建/转交/退出/撤销各路径事务内同步职责,并以显式受控任务修复历史,之后去掉列表读时 heal;(b) 租约查询避免每次全量文档修复,单请求在途、隐藏页暂停并在可见时立即同步,复用现有 SSE 失效事件;(c) 会话先按原可见性/排序选页,再仅统计页内数据,项目列表视数据量分页。维持 COUNT/latest 内容授权规则与排序稳定性,不能把当前全量总计改为页内总计却不告知调用方。
**Test scenarios:** 文档 GET 零 UPDATE/advisory lock,重复读不变 updated_at;成员变动职责立即正确;两标签 busy/释放不晚于原可见性基线、断 SSE 可恢复;慢查询轮询不重叠;分页无重复/丢项且计数不泄漏;EXPLAIN 对照现有索引与扫描行数;项目 143 不做写入修复测试。
**Verification:** PG 真库夹具 + 真实页面操作证明治理与编辑/刷新链路无回归;SQL 扫描、锁等待和 p95 确实改善。没有对应瓶颈时不为“优化”增加索引/摘要/新接口。
### U7. 重启后首访链路与开发预热(P0 诊断 / 按证据修复,约 0.5–1.5 天)
**Dependencies:** U1;**Requirements:** R1、R2、R6;**Files:** `web/vite.config.ts`、`cmd/server/main.go`、`internal/app/app.go`、`internal/bizdev/service.go`、`scripts/env-service.sh`、实际入口健康检查配置与启动测试。
**Approach:** 重启矩阵覆盖:仅 Vite 重启(保留/空依赖缓存)、仅 app 重启、依赖服务一起启动。每项再分浏览器保留缓存/清缓存与保存登录态/未登录;记录启动命令、DB healthy、app listen、ready、首次 HTML、首 API、UI ready。共享重启须占槽并避开正在执行任务,在隔离环境优先验证。Go 初始化分段计时;Vite 确认无缓存编译主导后,使用锁定 Vite 版本支持的 server.warmup/clientFiles 预热关键入口并保留 node_modules/.vite 缓存,禁止为暖机触发聊天或文档生成。
若 DB/迁移/seed 才是主耗时,先将重复扫描与种子写入改为有版本依据的幂等增量;必需迁移和授权数据未完成时 ready 必须失败。不要为看起来快而提前假报就绪。若是健康探测/代理等待,优化实际就绪探测与放流时序,不能把 start_period 直接当固定延时删除。对于后端暂时不可用,登录壳给出服务准备中和有限重试,不能无提示白屏或把瞬时不可达误当身份失效清空会话。
**Test scenarios:** 同版本无迁移重启、首次/有迁移启动、DB延迟就绪/不可用、依赖缓存失效、warmup 失败、过期登录态、保存有效登录态但网络暂时中断;多环境隔离保持。
**Verification:** 无待执行迁移且 DB 已就绪时 app restart→ready p95 ≤3 s;完整依赖启动单列,不承诺未测硬件的整机开机时间。8080/8081 ready 后首次访问须符合 Success Criteria 绝对预算;3100 分别符合 U1 在实施前固定的 Vite 冷/暖预算,不套生产压缩体积预算。三个入口在各自匹配的真实重启场景首访耗时均较基线下降至少 50%,同时记录从启动命令到 UI ready 总耗时,防止仅把等待搬到后台预热而宣称消失。若实测无法达到,保留未达标项与原因,不伪报完成。
## Verification Contract
- 前端:`cd web && npm test && npm run build`;单独运行 U1 的 Playwright 性能用例与现有文档修订/历史恢复相关浏览器回归。检查构建依赖与实际请求,不能只检查构建日志大小。
- Go:`go vet ./...`、`go test -short ./...`;认证/文档/会话修改补相关真实 PG 集成,覆盖撤销、跨用户、分页和职责同步。
- 合入/运行验证:占 CURRENT 集成槽,在主仓 merge 后 `./scripts/env-service.sh dev rebuild`,验证 `/health`、`/ready` 与资源 hash;健康不代表性能通过。禁止 worktree 启停共享服务。
- 真实 UI:登录、刷新当前会话、切项目、首开预览、首导出、文档编辑保存后刷新/重开、双标签 busy。涉及文档治理改变时按 PROJECT 补真实 PI + MiniMax 全链路,stub 不可替代交付。
- 证据:报告记录 commit/image/资源 hash、浏览器与硬件、网络/CPU 设置、缓存状态、数据规模、样本数/分位数、失败样本、请求数和 SQL 变化。脱敏,不保存登录 token、会话正文或原始授权头。
## Definition of Done
1. R1–R6 与性能预算有前后对比和真实 UI 证据;未覆盖项明确列残余,不因 health PASS 关闭。
2. 字体不可达仍可操作,首次登录无重功能模块;初始化不随全部项目成员返回重复发会话请求。
3. 授权/文档职责/租约/保存持久性不回退,分页可见性一致,SSE 不缓冲,旧版本 chunk 失效有恢复路径。
4. 更新任务、CURRENT、FEATURE-MATRIX、test-report,完成后任务归档;明确本地分支/提交、是否合 dev、是否推送。
## Rollout and Rollback
顺序:U1 → U2/U3 与 U7 → U4/U5 → 按数据选择 U6,每波独立复测并归档,预计核心 U1–U5 约 3.5–7 工程日,U7 另需 0.5–1.5 日,U6 另需 2–4 日(估算,含回归,非交付承诺)。先 dev,再按项目既有授权晋升 test/main。
压缩/缓存只作用静态资产,发现编码/缓存问题可回退独立提交;保留对应完整 HTML+资源集,避免仅回滚 HTML。拆包可回滚组件边界,但禁止强制刷新正在编辑的用户。认证和查询优化各独立提交;职责修复迁移必须可重入,停用新读路径时保留既有安全修复,不删除数据/索引作为临时回滚。若 p95 回退超过 10%、401/403 异常、文档职责偏差或租约不可见,停止晋升并回退相应单元。
## Appendix
- [审计与数值证据](../audit/2026-09-17-initial-load-performance-audit.md)
- [诊断测量报告](../test-reports/2026-09-17-initial-load-performance-baseline.md)
- HTTP 压缩协商与 `Vary`:[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Compression)。缓存版本化资源与 HTML 策略:[MDN HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching)。
- 外部字体与阻塞 CSS:[web.dev 字体实践](https://web.dev/articles/font-best-practices)。Vite 开发请求瀑布:[Vite performance](https://vite.dev/guide/performance)。这些资料用于原则核验;具体配置以仓库锁定的 Vite 7.1.x 为准,不照搬官网当前版本构建 API。
## Plan Review
已完成同模型的 coherence、feasibility、design、security、scope、adversarial 六视角只读复核(3 个代理分别承担两视角,不作为6份模型独立验证)。修正1项:明确3100开发入口与8080/8081构建入口使用不同资源预算;保留三入口真实重启与总耗时验证。未进行外部跨模型复核,不声称具有跨模型验证。置信度:资源/字体机制高,用户重启现场主因中等,须U1/U7闭环。
@@ -0,0 +1,57 @@
---
title: "系统体检整改与完善实施方案(2026-09-17)"
status: planned
created: 2026-09-17
updated: 2026-09-18
---
# 系统体检整改与完善实施方案
> 配套审计:[../audit/2026-09-17-system-health-check.md](../audit/2026-09-17-system-health-check.md)(编号 B-x 确认 bug、R-x 隐患、E-x 环境缺陷、T-x 任务、X-x 死代码、S-x 测试盲区、D-x 文档漂移)。
> Wave 0–7 已实施收口。Wave 7 仅为编排确认,未改变能力实现状态。
## 背景
体检确认质量门禁全绿、发布门禁口径属实;但发现 1 项 critical 环境缺陷(main ENV 不一致,E-1)、2 项 high 级 SSE 断流 bug(B-1/B-2)、1 项 high 级前端缓存 bug(B-5)、一批「机制先行无消费方」与测试盲区。本方案按风险优先分波次收口。
## 目标
1. main 环境事件链路语义唯一、无双写/空转风险(E-1)。
2. SSE 长任务不再被 120s WriteTimeout 强杀(B-1/B-2),错误语义对齐(B-3/B-4)。
3. 前端会话窗口缓存一致、恢复不丢数据(B-5/B-6)。
4. 封存功能的灰度入口在 compose 层就绪(E-3),死配置/死代码有明确处置(E-4、X-*)。
5. 测试债与 E2E 门禁入口收敛(S-1/S-2/S-4)。
6. 文档 SSOT 无漂移(D-1~D-6)。
## 分波次计划
| 波次 | 内容 | 验收 |
|------|------|------|
| **Wave 0:P0 确认 bug** | B-1/B-2:`handleChatStream` 与 `handleRunTaskStream` 接 `extendSSEWriteDeadline` + 心跳(复用 sse.go:52-64 既有机制);run/stream 支持 `after_seq` 续订(重连走既有 `GET .../events?after_seq=`)。B-3:Decode 失败返回 400。B-4:CreateAndStart/Subscribe 前置到 Flush 之前(对齐 chat 路径)。B-5:useChatWindow 全部写入统一带 `userId` 前缀,LRU 驱逐完整 cache key。B-6:`applyRestoredFileRaw` 函数式合并 | **done**(2026-09-18):[test-report](../test-reports/2026-09-18-wave0-p0-bug-fixes-test-report.md);合入 `dev` merge `fix/wave0-p0-sse-chat-cache-bugs`;dev rebuild + health/ready PASS;真 PI SSE 心跳证据归档 |
| **Wave 1:main 环境修正(critical)** | E-1:app/events 统一 `ENV=main`。E-2:app `depends_on events: service_healthy`(events 同步迁移后再启 app)。E-5:`Env==""` 不再视同 dev。附带:events 补齐 `validateProductionSecrets` 所需口令以免 Restarting | **done**(2026-09-18):[test-report](../test-reports/2026-09-18-wave1-main-env-fix-test-report.md);main health `env=main` + `schema_version=52`;consumer modes 仍 off |
| **Wave 2:配置与灰度入口对齐** | E-3:三环境声明 `MULTI_INTENT_PLAN_TIER`+U9–U12(legacy/false);A-4:test/main 补 SHADOW/NARRATIVE。E-4:删除 `CURSOR_RUNNER_URL`+cursor-agent。E-6:main `SEED_DEMO_USERS=false`。E-7:非法 `INTENT_V2_DECISION_TIER`→`none`。E-9:评估不改 initdb | **done**(2026-09-18):[test-report](../test-reports/2026-09-18-wave2-config-flag-align-test-report.md);三环境 env 抽检 + health/ready PASS |
| **Wave 3:测试债与盲区** | S-1:隔离 PG(5436) 跑 `TestReconcile_LegacyRepair_PG`。S-2:删 taskstream 死跳过;plan_owner 重定向说明。S-4:每 spec npm 脚本;退役 `document-revision.spec`(消灭 DOCREV_E2E_BASE_URL)。S-5:`projectSettingsError` 复用到 members/freeform/taskRuns/chatSessions | **done**(2026-09-18):[test-report](../test-reports/2026-09-18-wave3-test-debt-blindspots-test-report.md);playwright list 29/8;reconcile PG PASS |
| **Wave 4:隐患加固(可与 Wave 0–3 并行认领,mutex 不冲突时)** | R-1:`getOrCreateSession` 增 owner 绑定校验(session 创建时记录 owner,后续请求校验,不匹配 403)。R-2:18 处 `rows.Next()` 循环补 `rows.Err()` 检查。R-3:dispatcher Handlers 读路径加 RLock(或注释冻结「仅启动期注册」并加 archtest 约束)。R-4:`memTurns` 加 TTL/容量淘汰。R-5:pg_store JSONB 反序列化错误改为显式报错。R-6:后台 ticker 纳入 Shutdown;vault Drain 错误上报告警。R-7/R-8:SSE 重连 401/404 fail-fast、逐帧容错;登出 abort 在途流 | **done**(2026-09-18):[test-report](../test-reports/2026-09-18-wave4-hardening-r1-r8-test-report.md);Memory+PG 跨用户负例 PASS;`go test -short` / `npm test` 全绿 |
| **Wave 5:死代码与机制收口(需逐项决策,不擅自删)** | X-1:删除 `SEMANTIC_FALLBACK_ENABLED`。X-2:`SEMANTIC_SUMMARY_REPLACE` 维持未接线并封存注释。X-3:00048 三表 deferred → SWBOOT-10/W5b。X-4:system_settings 6 键保留并注释二期。X-5:删除 DocumentNotificationList、WorkflowPrerequisiteBanner、SettingsModal、activateWorkflow、saveMessages 及级联 patchNotification | **done**(2026-09-18):[决策](../ops/short-term/2026-09-18-wave5-deadcode-decisions.md) · [test-report](../test-reports/2026-09-18-wave5-deadcode-decisions-test-report.md) |
| **Wave 6:文档漂移修复** | D-1:PU8 四份契约文件状态改 done 并归档。D-2:modular-monolith ADR 状态更新为 accepted。D-3:两个 INDEX 末行已在本审计修正(复核即可)。D-4:handoff 回标已被覆盖。D-5:backlog D3/D7 同步最新状态。D-6:PROJECT.md §9「剩余 blocker」段与 gap-matrix 对齐或删除 | **done**(2026-09-18):[short-term](../ops/short-term/2026-09-18-wave6-doc-drift.md) · [test-report](../test-reports/2026-09-18-wave6-doc-drift-test-report.md);D-3 INDEX 复核 PASS、零改动 |
| **Wave 7:既有 roadmap 收口(不改优先级,仅确认编排)** | T1/W5:SWBOOT-10 安全评审后实施(保持 fail-closed 直至授权)。T1/W6:FAV live 放量 staging→artifact→publication,每级 ≥7 天观察窗,`FAV_DEGRADED_READ=false` 不动。T1/W7:D7 待合规签字后按 ADR 整改。T4:首次加载性能 U1/U3–U7。T5/T6/T8:backlog 类按收益触发。T2(Control Center)已于 2026-09-19 移出本仓库 | **done**(2026-09-18):[决策记录](../ops/short-term/2026-09-18-wave7-roadmap-orchestration.md)。六项编排确认已记录;T2 后来由用户裁决为独立项目,本仓库不再保留 Control Center;FAV/D7/tier 升级红线未动 |
## 验收标准
- [x] Wave 0 完成后:`go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build` 全绿;dev 容器 rebuild + health/ready PASS([报告](../test-reports/2026-09-18-wave0-p0-bug-fixes-test-report.md))
- [x] main 环境:ENV 语义统一核验记录 + schema 已升(实测 52)+ 事件链路无双写证据(modes 仍 off)(Wave 1,[报告](../test-reports/2026-09-18-wave1-main-env-fix-test-report.md))
- [x] SSE 长回合心跳接线:真 PI 静默期 `: heartbeat` + 短 WriteTimeout 单测跨越(Wave 0)
- [x] Wave 2 配置声明对齐:三环境 compose diff 复核 + 容器 env 抽检 + go test 全绿(E-3/E-4/E-6/E-7 完成;E-9 评估结论已记录,不改代码)([报告](../test-reports/2026-09-18-wave2-config-flag-align-test-report.md))
- [x] `TestReconcile_LegacyRepair_PG` 报告归档,gap-matrix 测试债行关闭(Wave 3)
- [x] `playwright test --list` 与门禁文档一致(Wave 3)
- [x] 跨用户会话挂靠负例测试入库(Wave 4)
- [x] X-1~X-5 每项有决策记录(Wave 5)
- [x] D-1~D-6 全部回链关闭(Wave 6)
- [x] Wave 7 六项编排确认已记录(T1/W5、T1/W6、T1/W7、T2、T4、T5/T6/T8);FAV/D7/tier 升级红线未变(Wave 7)
- [x] 不触碰红线:FAV_DEGRADED_READ=false、MULTI_INTENT_PLAN_TIER 默认 legacy、SEMANTIC_SUMMARY_REPLACE 不接线、项目 143 只读、禁止整支 merge FAV
## 相关链接
- Audit: [../audit/2026-09-17-system-health-check.md](../audit/2026-09-17-system-health-check.md)
- gap-matrix: [./gap-matrix.md](./gap-matrix.md)(本方案不改动发布门禁结论;E-1 若核验确认 main 事件链路异常,再评估是否升 blocker)
- 既有收口总控:[./2026-09-16-partial-deferred-completion-plan.md](./2026-09-16-partial-deferred-completion-plan.md)
+4
View File
@@ -2,6 +2,8 @@
| 文档 | 说明 |
|------|------|
| [2026-09-17-system-health-remediation-plan.md](./2026-09-17-system-health-remediation-plan.md) | 系统体检整改:Wave0–7(SSE/缓存 P0 → main ENV → 配置对齐 → 测试债 → 隐患 → 死代码决策 → 文档漂移 → roadmap);配套 [审计](../audit/2026-09-17-system-health-check.md) |
| [2026-09-17-document-author-only-plan.md](./2026-09-17-document-author-only-plan.md) | 编制人兼任审核/批准:两级授权、`duty_policy=author_only`、U1–U6 实现已收口;默认 off;变更提案 HTTP 另立([audit](../audit/2026-09-17-docgov-modification-proposal-http-gap.md)) |
| [gap-matrix.md](./gap-matrix.md) | 发布缺口 SSOT |
| [2026-09-16-partial-deferred-completion-plan.md](./2026-09-16-partial-deferred-completion-plan.md) | FEATURE-MATRIX 6 partial + 1 deferred 全量收口:通信机制确认(模块化单体,不新增 RPC 层)、7 项关闭条件、W1–W7 波次;§7 四项决策已确认(2026-09-17) |
| [2026-09-16-feature-matrix-production-readiness-plan.md](./2026-09-16-feature-matrix-production-readiness-plan.md) | 能力状态与发布门禁解耦、证据校准、剩余 partial 收口和 production-ready 防回退计划([审计](../audit/2026-09-16-feature-matrix-production-readiness-audit.md)) |
@@ -31,3 +33,5 @@
| [2026-09-12-three-workflows-strict-governance-remediation.md](./2026-09-12-three-workflows-strict-governance-remediation.md) | 三工作流严格治理 |
审计入口:[../audit/INDEX.md](../audit/INDEX.md)
- 2026-09-17:[首次加载性能诊断与改进](2026-09-17-initial-load-performance-plan.md)(三入口重启首访;U2 已验收,主 JS ~624 KB;U1/U3–U7 待实施)。
+1 -1
View File
@@ -63,7 +63,7 @@
| ID | 描述 | 状态 | 证据 | 计划动作 |
|---|---|---|---|---|
| WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES | active 项目仍展示可编辑职责表单,409 提示在长表单视口外;现有规划又不支持非必需文档“三权全空”,且后端缺少职责人在任成员复核 | **PASS(设置页)** | [audit](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md);[test-report](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md)。项目 143 只读 frozen、A full+none 激活、B partial 不发 PUT、C 零治理拒绝、双标签转 frozen、成员无配置入口、刷新后 143 仍 frozen | 设置页矩阵 PASS;真实 PI full/none 长链已另签 [Wave2 报告](../test-reports/2026-09-16-wave2-real-pi-evidence-test-report.md) |
| DOC-CONTENT-CANONICAL-HASH-DRIFT | 旧受控文档 bootstrap 裁剪 Markdown 双空格硬换行并将 canonical SHA 写入账本/DocGov,但未同步文件;正文读取把完整性冲突误报 404,lease/list sync 又放大并制造刷新后加载死锁 | **PASS(真实 UI)** | [audit](../audit/2026-09-14-project143-controlled-content-404.md);[UI report](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。代码已合 dev、schema 32、项目 143 定向 `migration_repair`;项目 143 `clean-run3` 与新项目 `full-chain-final` 主链及 restart 全部纯页面 PASS,目标 404=0 | [remediation](./2026-09-14-controlled-content-canonical-hash-remediation.md)。隔离 `TestReconcile_LegacyRepair_PG` 未执行,按用户“本轮只允许页面测试”的边界保留为工程测试债,不作为本轮 UI PASS 的替代证据 |
| DOC-CONTENT-CANONICAL-HASH-DRIFT | 旧受控文档 bootstrap 裁剪 Markdown 双空格硬换行并将 canonical SHA 写入账本/DocGov,但未同步文件;正文读取把完整性冲突误报 404,lease/list sync 又放大并制造刷新后加载死锁 | **PASS(真实 UI)** | [audit](../audit/2026-09-14-project143-controlled-content-404.md);[UI report](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。代码已合 dev、schema 32、项目 143 定向 `migration_repair`;项目 143 `clean-run3` 与新项目 `full-chain-final` 主链及 restart 全部纯页面 PASS,目标 404=0 | [remediation](./2026-09-14-controlled-content-canonical-hash-remediation.md)。Wave 3(2026-09-18)已在隔离 docker PG(5436)执行 `TestReconcile_LegacyRepair_PG` 一次并 PASS,工程测试债关闭,见 [test-report](../test-reports/2026-09-18-wave3-test-debt-blindspots-test-report.md) |
| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);活验 [live.json](../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(项目 6252,window=categories=2,guest 403);代码:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027 | 闲聊刷新已补。发布门禁「激活后文档任务 + 重登/重启」仍开放,不回退本 gap |
| CHAT-INTENT-STATE | 真实会话被诊断探针污染;只读查询误启动文档写任务;错误动作与编辑状态刷新后丢失 | **PASS** | [audit](../audit/2026-09-13-conversation-intent-runtime-state.md);[test-report](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);双标签活验项目 **6275** / `sess-p6275-u10`(`live.json` + Docker 截图)。**不**删除 `sess-p143-u9` 历史探针 | [remediation](./2026-09-13-conversation-intent-runtime-state-remediation.md)。Wave 3–4 浏览器门已签;诊断污染消息仍不擅自删除 |
| ENV-RESTART-SOURCE | `docker compose restart` 只重启旧镜像,健康检查无法证明合入代码已部署 | **PASS** | `env-service.sh rebuild` + 真实摘要重测 | 集成冒烟统一使用 `dev rebuild` |
+16 -3
View File
@@ -1,6 +1,6 @@
# 模块与功能完成度(SSOT)
**更新**: 2026-09-17(W3 PI 叙事 done;W4 多意图扩面 done)
**更新**: 2026-09-19(审计整改批 1–4 已合入 dev;medium/low 见 [long-term](../ops/long-term/2026-09-19-audit-remainder.md))
**production_ready**: yes(权威来源:[gap-matrix](../remediation/gap-matrix.md);本表不推导发布门禁)
**发布缺口**: [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
**协作焦点**: [../ops/CURRENT.md](../ops/CURRENT.md)
@@ -8,6 +8,8 @@
**整改计划**: [../remediation/2026-09-16-feature-matrix-production-readiness-plan.md](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md)
> 本表描述**能力成熟度**;上线 blocker 见 gap-matrix。二者正交:能力行不必全部 `done` 才能发布;`partial`/`deferred` 不得自动回退 `production_ready`。
>
> 2026-09-19 深度审计的 critical/high 已分四批合入 `dev`(数据一致性、鉴权、SSE/事件、前端 XSS)。不改 `production_ready`。未做项在 [long-term](../ops/long-term/2026-09-19-audit-remainder.md)。
---
@@ -16,7 +18,7 @@
| 字段 | 含义 |
|------|------|
| **声明范围** | 本行冻结的能力边界;`done` 只对该边界负责 |
| **状态** | `done` \| `partial` \| `planned` \| `deferred` \| `blocked` |
| **状态** | `done` \| `partial` \| `planned` \| `deferred` \| `blocked` \| `removed`(已下线,仅留历史证据) |
| **发布关系** | 与当前首发/已签门禁的关系:`non_blocker` / `补证` / `加固` / `deferred_enhancement` |
| **关闭条件** | 何时可将本行升为 `done`(或关闭 `partial`);stub/SKIP/fallback 不得冒充 |
| **证据** | 可追溯到报告/commit/环境/schema;代码或 artifact 变化后须重验 |
@@ -55,6 +57,7 @@
| 对话数据治理(D7) | 留存/删除口径、库·备份·日志控制、敏感字段加密边界 | deferred | deferred_enhancement(违规则升 blocker) | [计划](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md) Scope Boundaries;[收口 §7.1](../remediation/2026-09-16-partial-deferred-completion-plan.md);[D7 ADR 草案](../adr/2026-09-17-d7-chat-data-retention.md);[W7 盘点](../audit/2026-09-17-d7-data-inventory.md);[报告](../test-reports/2026-09-17-w7-d7-inventory-test-report.md) | **after W7**:只读盘点完成(sessions/messages/KB/日志/备份/event)。**未发现**已确认基线违规,未写 gap-matrix。口径仍 `pending-compliance-signoff`;禁止按 365/180/30 物理删除。本行不升 done | `chat` |
| 智能体小队 | 角色-任务-工作区-黑板 | done | non_blocker | [agent-squad](../system-design/agent-squad/);[test 2026-09-07](../test-reports/2026-09-07-dynamic-squad-planning-test-report.md) | 非关键步骤降级(A5/A6)属 backlog | `squad` |
| 工作流治理 | 三正式工作流、设置页/DutyMode、动作级鉴权、真实 PI 三工作流 E2E、full/none 混合长链 | done | non_blocker | [三工作流整改](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[409/职责](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md);[鉴权](../test-reports/2026-09-14-governance-action-level-authz-test-report.md);[PI E2E](../test-reports/2026-09-16-pi-three-workflow-e2e-test-report.md);[Wave2 full/none](../test-reports/2026-09-16-wave2-real-pi-evidence-test-report.md) | full 跨用户审批 + none 免审批不阻塞已签。纯软件自举仍独立 planned | `workflow` |
| 研发设计控制(rdev) | 医疗第 4 工作流:13×60 manifest/模板、`squad.rdev_doc.v1` kind 编排、main-completed 硬 precheck、StageKey 动态化;不含前端/真 PI/键名空间化 | partial | deferred_enhancement | [设计](../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md);[short-term](../archive/ops/2026-09-17-rdev-workflow-integration.md);[模板深度](../archive/ops/2026-09-17-rdev-template-depth.md);[S0+S1 首批报告](../test-reports/2026-09-17-rdev-template-depth-test-report.md);[S1 续批报告](../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md);[写作规范](../system-design/project-workflow/08-rdev模板写作规范.md);[backlog](../backlog/2026-09-17-rdev-phase2-backlog.md) | **P0+P1 done**。**模板深度 S0+S1 首批 + S1 续批 done**:60/60 模板已补强;真 PI 抽样 PASS(含 `rd_planning_review` + `rd_design_vv`,项目 6446)。剩余:S3 overlay 与 R2/R3 已接。P2 名称匹配、阶段折叠、批量审批已接。选中 rdev 时显示与服务端相同的 CDO 前置说明(`workflowPrerequisite.test.ts`)。P4 键名空间化已接:发布清单用 `bd_`/`pm_`/`tm_`/`sw_`,旧键仍走同一套步骤和模板,旧 doc_id 仍可查(`keyspace_test.go`)。P3 三样本已在 dev 真 PI 上跑过(项目 6533):`rd_sw_plan` 规划期关闭;`rd_proposal` completed 但未对齐模板标题;`rd_planning_review` 当时质量门禁 score 20,是把同节后一张法规表算进问题行。门禁已只读第一张表;保存的终稿不再报「问题行缺少」。建议书标题仍未对齐模板。没有新的真 PI。见 [P3 报告](../test-reports/2026-09-19-rdev-p3-real-pi-test-report.md)。nightly 未扩成四工作流。 | `workflow-def` / `rdev-templates` |
| 纯软件项目自举 | 软件项目创建、Bootstrap、Delivery、受控工程交接 | partial | deferred_enhancement(明确不挡首发) | [设计](../system-design/2026-09-14-software-project-bootstrap-workflow.md);[ADR](../adr/2026-09-16-software-project-bootstrap-keys.md);[L1 报告](../test-reports/2026-09-16-software-project-bootstrap-test-report.md);[W5a](../test-reports/2026-09-17-w5a-software-bootstrap-ui-pi-test-report.md) | **before**:L1 + UI 仍克隆医疗模板。**after W5a**:catalog 驱动创建、软件不挂医疗 key、docs_only 真 PI 建议 delivery 且不自动激活。**SWBOOT-10 仍 stub**(W5b);本行不升 done | `workflow-design` |
| IAM / 鉴权 | 项目级 API 鉴权 + RBAC;会话/阶段授权 | done | 加固 | [v3 full inventory](../audit/authorization-matrix-v3-full.md);[session 中断](../test-reports/2026-09-16-iam-route-inventory-test-report.md);[fail-closed](../test-reports/2026-09-16-wave1-iam-fail-closed-test-report.md);[410 策略](../audit/2026-09-16-bug11-410-retire-decision.md);[R13](../audit/2026-09-16-r13-data-safety-checklist.md) | 全路由 inventory + session 中断负例 + 410 冻结 + R13 基线已签 | `authz` |
| 文档治理 | 法定文档生命周期 + 租约 + 受控正文读取 | done | non_blocker | [docgov](../test-reports/2026-09-08-docgov-lifecycle-and-claiming-framework-test-report.md);[正文 UI](../test-reports/2026-09-14-controlled-content-ui-acceptance.md);[canonical hash](../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md) | 项目 143 只读;不终止 | `docgov` |
@@ -67,6 +70,8 @@
| Artifact 同 digest 晋升 | 候选 commit 一次构建、按 digest 晋升、promotion receipt | done | 加固 | [计划 PU5B](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md);[Wave2B](../test-reports/2026-09-16-wave2b-nightly-promotion-receipt-test-report.md);[Wave2C](../test-reports/2026-09-16-wave2c-same-image-digest-test-report.md) | **关闭**:same-image pin(`candidate-images-*` + `PINNED_IMAGE_MODE` + promote `--require-digests`)。**声明**:单机 retag/digest pin;远程 registry 推送另立任务 | `infra` |
| 可靠事件核心 | PG dispatcher、notify/advance/projection live、生产闭包 hook 退出、Phase2 选择性解耦已合入 | done | non_blocker | [E0A–E2](../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md) 等;[复盘](../ops/research/2026-09-15-track-e-retrospective.md);[shared live](../test-reports/2026-09-15-event-notify-shared-live-test-report.md);[phase2 closeout](../test-reports/2026-09-15-phase2-closeout-test-report.md) | **before**:与 FAV off 混成 partial → **after**:FAV 独立行。选择性后续解耦按收益触发 | `architecture-docs` / `events` |
| Final Artifact Vault(FAV) | 不可变终态制品库;`FAV_DEGRADED_READ=false` | partial | deferred_enhancement | [Track E 复盘](../ops/research/2026-09-15-track-e-retrospective.md);[U7 报告](../test-reports/2026-09-16-fav-u7-incremental-test-report.md);[W6 shadow](../test-reports/2026-09-17-w6-fav-subscriber-shadow-test-report.md);[short-term](../ops/short-term/2026-09-17-w6-fav-subscriber-shadow.md) | **after W6**:subscriber `ObserveShadow` 只计算 intended outcome,不写副作用。仍**禁止**整支 merge;`FAV_DEGRADED_READ` 默认 false;**live 未放量**(staging→artifact→publication 各 ≥7 天观察窗) | `events` |
| 系统管理台 | 全屏系统级管理视图(总览/KB/特性开关/系统设置/工作流/角色/用户/文档 8 分组);`/api/v1/admin/system/*`;`system_settings` 白名单可写;吸收下线 AdminSettingsModal | done | non_blocker | [short-term](../ops/short-term/2026-09-17-system-admin-console.md);[测试报告](../test-reports/2026-09-17-system-admin-console-test-report.md);commit `f1404d5`/`0eaca61`、merge `dc7c31e`(dev);dev 冒烟 schema 49 + 四端点 + 写读回环 PASS | 二期:Playwright 实跑、细粒度 `system:*` 权限、设置审计日志、KB 运维动作、白名单项接消费方 | `web` + `sysadmin` |
| 个人工程中控台(已移出) | 原本地只读看板与后来的 Control Center 都不再属于本仓库 | removed | 进度管理改由独立项目承担 | [历史设计](../archive/design/2026-09-17-personal-engineering-control-center-plan.md);[历史报告](../test-reports/2026-09-17-engineering-dashboard-test-report.md) | 2026-09-19 删除 `cmd/control-center`、`internal/controlcenter`、`control-center/web`、`deploy/control-center`。不恢复 `engineering-dashboard` | — |
---
@@ -77,7 +82,7 @@
| Intent L1 | partial(混入 U9–U12) | done | U9–U12 → 多意图扩面 | 是(双标签 + 分流 + U1–U3) |
| Chat/ctxmgr | partial(混入语义摘要 D5 误标) | done | D3 摘要行;D7 治理行 | 是(B3 项目 6359) |
| Document revision | partial(混入完整 PI 叙事) | done | PI change-report 叙事行 | 是(Round20;fallback 为声明行为) |
| Frontend workbench | partial(缺口栏已空) | done | 其他 409 信封复用 → backlog | 是(B4 项目 6363) |
| Frontend workbench | partial(缺口栏已空) | done | Wave 3 已收口 projectMembers/freeformDoc/taskRuns/chatSessions 结构化错误信封复用 | 是(B4 项目 6363) |
| 可靠事件 | partial(与 FAV 混行) | done | FAV 独立 deferred | 是(E0–E2 + shared live) |
---
@@ -88,3 +93,11 @@
2. 同一 `mutex` 同时仅一个 Agent `in_progress`(见 CURRENT)
3. 新能力行:复制 [../ops/templates/feature-matrix-row.md](../ops/templates/feature-matrix-row.md)
4. 拆行/收口须保留 before/after 与义务迁移(见上表);禁止缩口径假完成
## 2026-09-17 首次加载性能专项
首次加载与重启首访性能优化:**partial**(U2 静态交付已验收;U3 只做了登录壳拆包,未关闭)。[审计](../audit/2026-09-17-initial-load-performance-audit.md) · [方案](../remediation/2026-09-17-initial-load-performance-plan.md) · [U2 报告](../test-reports/2026-09-17-initial-load-perf-u2-test-report.md)。U2:自托管字体 + br/gzip。U3 进展(`fix/audit-remainder-closeout`):导出、预览、管理台、块编辑器、Mermaid/公式改为点击或出现时再加载。入口包 `index-*.js` 由 2.83 MB / br 626 KB 降到 737 kB / br 170 KB(`index-j0BIrjIR.js`,包内无 katex)。公式在气泡或正文里出现时才加载,富文本复制同样延后。U3 的浏览器资源瀑布还没测,本行不关。U5:`/auth/me` 复用本请求已核过的用户,不再第二次解析会话;会话与用户状态合成一次 JOIN。没有锁等待证据,所以不节流 `last_seen`。`TestAuthMe_LogoutNextRequestIs401`。U1、U6、U7 未做。U4 进展:登录不再按项目数拉成员名册,只同步当前项目;其他项目先种入当前用户以保持会话可见,完整名册在打开成员面板时取。会话列表不再因项目数组变化而重拉,迟到响应用代次丢弃,同一项目的在途成员请求合并。`src/data/initFanout.test.ts`。2026-09-19 浏览器证据(`e2e/initial-load-performance.spec.ts`,n=20,本仓 Vite `:3100` 代理 `:8080`):每次登录成员项目数 1、会话列表 GET 1,匿名与登录后资源路径均无 katex/mermaid/docx。同一探针在重建后的 `:8080`(`index-DOO0-Yh7.js`,schema 53,n=5)成员项目 1、会话列表 GET 1,匿名 JS 传输 172,417 B,首屏路径无 katex/mermaid/docx。重建前旧包 n=1 曾是 704/30。慢网 n=3、CPU 4 倍:10 Mbps 表单可见 558–604 ms,2 Mbps 1279–1296 ms,样本不足 20,U1 不关。U6 不加索引:测到的瓶颈是已消失的成员扇出,没有慢 SQL 证据。U7 已测未关:[报告](../test-reports/2026-09-19-initial-load-u7-restart-test-report.md)。Vite 监听约 0.3 s;314 个模块冷/热 1.45/1.11 s,不是历史十几秒。postgres+app 到 `/ready` 1.0–1.2 s。无头浏览器缺系统库,登录表单可见未测;不宣称较基线下降 50%。mutex `web + static-delivery`(U2 done)/ `loading-performance-audit`。
## 2026-09-17 文档编制人兼任方案
新增能力 **done(U1–U6,已合入 `dev@09a9921`)**:[方案](../remediation/2026-09-17-document-author-only-plan.md) · [源码核查](../audit/2026-09-17-document-author-only-analysis.md) · [U6 验收](../test-reports/2026-09-17-document-author-only-u6-test-report.md) · [收口交接](../ops/handoffs/2026-09-17-document-author-only-closeout.md)。任务归档:`archive/ops/2026-09-17-document-author-only-u{1..6}.md`。总开关默认 off;test/main 晋升与开放授权另授。变更提案 HTTP 仍缺([audit](../audit/2026-09-17-docgov-modification-proposal-http-gap.md))。mutex `document-duty-policy`。
+6
View File
@@ -138,6 +138,12 @@
---
### 8. 个人中控台(已移出本仓库)
项目开发进度由独立的统一管理系统负责,不再是本仓库功能。本仓库只保留智能体系统。旧只读工程中控台的历史设计仍在 [../archive/design/2026-09-17-personal-engineering-control-center-plan.md](../archive/design/2026-09-17-personal-engineering-control-center-plan.md),代码不恢复。
---
## 🏗️ 在整体架构中的位置
```
+10 -1
View File
@@ -90,6 +90,7 @@ imports:
- taskrun
- workflowdef
- workspace
- sysadmin
app/chatflow:
- coordinator
- ctxmgr
@@ -147,6 +148,7 @@ imports:
httpx: []
intent:
- maturity
- squad
kb:
- config
maturity: []
@@ -202,6 +204,7 @@ imports:
- workflowdef
- workspace
- artifactvault
- sysadmin
squad:
- agent
- config
@@ -209,6 +212,7 @@ imports:
- stream
- template
- workspace
- workflowdef
storage: []
stream: []
stream/transport:
@@ -223,7 +227,8 @@ imports:
- projectworkflow
- stream
- workspace
template: []
template:
- workflowdef
upload: []
workflow: []
workflow/runtime:
@@ -244,6 +249,8 @@ imports:
dataset:
- artifactvault
- app/uow
sysadmin:
- config
table_owners:
document_records:
@@ -326,6 +333,8 @@ table_owners:
- app/intentflow
intent_plan_shadow:
- app/intentflow
system_settings:
- sysadmin
path_owners:
output.md:
@@ -0,0 +1,254 @@
# 07 研发工作流(rdev)接入——设计与实施计划
- **版本**: v1.1(四项关键决策已由用户确认,2026-09-17;见 §8)
- **日期**: 2026-09-17
- **来源**: 用户需求「在系统中加入研发工作流」;参考项目调研见 [research/2026-09-17-rdev-workflow-reference-analysis.md](../../ops/research/2026-09-17-rdev-workflow-reference-analysis.md)
- **范围**: 在现有 5 个正式工作流(医疗三 + 软件两)之外,新增医疗第 4 工作流「**研发设计控制流程**」(key: `rdev`,**13 阶段 / 60 文档任务一次到位**,ISO 13485 DHF/DMR 设计控制链);并随后对现有工作流任务键做统一命名空间化(D12,P4)
- **分支建议**: `feature/rdev-workflow`(从 dev 切出);键名空间化独立分支 `feature/workflow-key-namespace`
---
## 1. 结论摘要
参考项目的 rdev 工作流与本系统的「workflowdef 版本化定义 + projectinstance 冻结实例 + bizdev/squad 执行链」架构高度同构,接入以**数据与配置为主、代码为辅**:
1. **一个新 manifest**(`rdev.v2.json`,13 stage × 60 doc task)+ **60 份模板** + **一个通用执行器键** `squad.rdev_doc.v1` + **一个数据驱动的 rdev 任务目录表**(squad 包内)即可跑通主链;
2. **两处前置修复**:docgov 文档 Stage 字段去硬编码(现为写死 `V0.5_feasibility`);rdev 启动前置门禁(main 实例 completed,即 CDO 已批准)按 test_manager 先例做**执行器级 precheck**,不恢复流程级依赖(遵循 [WF-DEF-06 整改](../../remediation/2026-09-12-three-workflows-strict-governance-remediation.md));
3. **一个关键命名决策**:60 个任务键统一加 `rd_` 前缀(含模板文件名),避免与既有任务键 `system_reqs` 在 doc_id(`doc_proj{id}_{taskKey}`)、模板加载(`GetDocTemplate(taskKey)` 平铺目录)两层冲突;
4. 分四期实施(P0 前置修复 → P1 核心接入 → P2 治理与体验 → P3 真实 PI 验收),预估 2–3 周(单人)。
## 2. 参考项目 rdev 要点(回顾)
见 [调研笔记](../../ops/research/2026-09-17-rdev-workflow-reference-analysis.md)。核心结构:
- **13 phase / 60 stage**:01 策划(2) → 02 策划评审(1) → 03 设计输入(12) → 04 需求评审(1) → 05 输入阶段评审(1) → 06 设计输出(17) → 07 输出评审(1) → 08 验证(12) → 09 验证评审(1) → 10 转换(3) → 11 转换评审(1) → 12 确认(7) → 13 设计确认报告(1);
- **15 个 skippable**(软件 9 + 电气 3 + EMC + 动物试验 + 临床);
- **三种 artifact_kind**:`document` 47 / `review_minutes` 6 / `upload_index` 7;
- **记录归属**:`dhf` 为主,设计输出/转换类 `dhf+dmr`;
- **followon 门禁**:商务对接 CDO 批准后才可启动;启动时拷贝 bizdev 已填字段;
- **质量纪律**:模板写满、结论先行、UR→RS 追溯、缺项「待确认」、不适用须完整理由仍走审批、不编造数据/签字。
## 3. 现系统机制盘点(与本任务相关)
| 机制 | 现状 | 对 rdev 的影响 |
|------|------|----------------|
| 工作流定义 | `internal/workflowdef`:Definition + Version(schema v2 JSONB 快照、definition_hash、published);正式 key 白名单 `catalog_policy.go`;seed 走 `manifests/*.json` 内嵌 + `BootstrapSeeds` 幂等发布 | 新增第 6 个正式 key;manifest/seed/白名单/目录顺序同步 |
| 模板资产 | `templates/docs/*.md` 启动时全量上传(asset_key=文件名);运行时 `template.GetDocTemplate(taskKey)` 平铺读 `templates/docs/<taskKey>.md` | **平铺命名 → 必须无碰撞**;rd_ 前缀方案 |
| 项目实例 | `projectinstance`:planning→live 冻结 ConfigSnapshot;阶段线性 position;`AdvanceStage` 要求全部 blocking doc task approved;末阶段完成 → InstanceDone | 13 stage 线性推进天然匹配 phase 序;depends_on 语义由阶段序覆盖 |
| 执行链 | server `task_run_handlers` → `taskrun.Manager`(单一 Executor = `bizdev.ExecuteTask`)→ `squad.ExecuteTask`(AdaptivePlanner 按 taskKey 出步骤)→ PI Agent Runner | executor_key 目前是**发布校验元数据**,运行时统一走 bizdev;新增任务主要是 squad 侧编排数据 |
| squad 编排 | `SupportedTasks` 白名单(9 个);`DefaultWorkflowSteps`/`DefaultSquadAgents` 按 taskKey **硬编码 switch**;非白名单任务回落 autonomous adhoc | 60 任务若逐个 switch 不可维护 → 改为按 artifact_kind 三套通用编排 + rdev 数据目录表 |
| 文档账本 | docgov:`doc_id = doc_proj{pid}_{taskKey}`;**Stage 字段写死 `V0.5_feasibility`**(bizdev/service.go:483,489 + docgov/repository.go:28 兜底) | **P0 必修**:改为从冻结实例解析 StageKey |
| 前置依赖 | 无流程级依赖(WF-DEF-06 已移除);test_manager 用执行器级 precheck(approved SRS)+ `WorkflowPrerequisiteBanner` | rdev 同模式:precheck「main 实例 completed」 |
| 血缘 stale | `projectworkflow/service.go` MarkDownstreamStale;test_manager 记录单一上游 hash | 首期统一项目上下文注入;精确 depends_on 血缘列二期 |
| 意图 | L1 `extractDocName` 硬编码 9 个文档名;U8 多意图 task-generate 从 live 实例数据驱动 | rd 文档名匹配需增补或实例驱动化 |
| 前端 | `ProjectWorkflowSwitcher`(目录 API 驱动)+ 激活规划 UI + StageAdvance/Prerequisite Banner | 13×60 规划 UI 需折叠分组与批量三权指派 |
## 4. 关键设计决策
### D1 工作流标识与目录
- `OfficialKeyRDev = "rdev"`;对外名称建议 **「研发设计控制流程」**(与「商务对接流程」命名风格一致;备选「研发流程」);
- `product_domains: ["medical_device"]`(软件域不可选);
- `catalog_order = 40`(排在 test_manager 之后、software_bootstrap 之前);`medicalWorkflowKeys` 扩为四个;
- validator 文案「仅允许选择正式工作流(医疗三或软件自举/交付)」同步更新;审计口径「项目选择页只见 N 个工作流」从 5 → 6。
### D2 任务键与模板命名(关键决策)
**问题**:`doc_id`、模板加载、docgov task_key 三层都以 taskKey 平铺命名。rdev 的 `system_reqs`(SR)与现有 PM 任务 `system_reqs` 直接冲突;且未来任何工作流任务键都共享同一命名空间。
**推荐:60 个任务键统一加 `rd_` 前缀**(`rd_proposal`、`rd_design_plan`、`rd_system_reqs`…),模板文件同步 `rd_*.md`:
- 彻底消除 doc_id/模板/任务键三层冲突,跨工作流血缘清晰;
- 转换机械:从参考项目 `rdev.yaml` 逐行映射生成(可写一次性生成脚本,人工复核);
- manifest 中 `title`/`output_doc_title` 保留中文文档名,用户可见名称不变;
- 模板头部「文件编号 RD-…」保留参考项目编号(RD-PROPOSAL 等),不受键名影响。
**备选**:仅 `system_reqs` 一键改名、其余保持原键。缺点:命名空间纪律弱,未来再加工作流仍会踩。
### D3 manifest 结构(rdev.v2.json)
13 个 StageDef 对应 13 个 phase(键名风格沿用本仓库 `V0.1_triage` 惯例)。示例(完整 60 任务 = 参考项目 rdev.yaml 逐行映射):
```json
{
"schema_version": 2,
"workflow_key": "rdev",
"product_domains": ["medical_device"],
"stages": [
{"key": "RD01_planning", "name": "01 设计和开发策划", "position": 10, "optional": false,
"doc_tasks": [
{"key": "rd_proposal", "title": "项目建议书", "default_enabled": true, "creator_configurable": true,
"blocking_when_enabled": true, "executor_key": "squad.rdev_doc.v1", "quality_gate_key": "quality.generic.v1",
"template_asset_key": "rd_proposal", "output_doc_type": "rd_proposal", "output_doc_title": "项目建议书"},
{"key": "rd_design_plan", "title": "设计开发计划任务书", "default_enabled": true, "creator_configurable": true,
"blocking_when_enabled": true, "executor_key": "squad.rdev_doc.v1", "quality_gate_key": "quality.generic.v1",
"template_asset_key": "rd_design_plan", "output_doc_type": "rd_design_plan", "output_doc_title": "设计开发计划任务书"}
]},
{"key": "RD02_planning_review", "name": "02 策划评审", "position": 20,
"doc_tasks": [{"key": "rd_planning_review", "title": "设计和开发策划评审记录", "...": "同上模式"}]},
{"key": "RD03_design_input", "name": "03 设计输入", "position": 30, "doc_tasks": ["12 个任务"]},
{"key": "RD04_requirements_review", "position": 40, "doc_tasks": ["rd_req_review"]},
{"key": "RD05_input_phase_review", "position": 50, "doc_tasks": ["rd_input_phase_review"]},
{"key": "RD06_design_output", "position": 60, "doc_tasks": ["17 个任务"]},
{"key": "RD07_output_review", "position": 70, "doc_tasks": ["rd_output_review"]},
{"key": "RD08_verification", "position": 80, "doc_tasks": ["12 个任务"]},
{"key": "RD09_verification_review", "position": 90, "doc_tasks": ["rd_verification_review"]},
{"key": "RD10_transfer", "position": 100, "doc_tasks": ["3 个任务"]},
{"key": "RD11_transfer_review", "position": 110, "doc_tasks": ["rd_transfer_review"]},
{"key": "RD12_validation", "position": 120, "doc_tasks": ["7 个任务"]},
{"key": "RD13_validation_report", "position": 130, "doc_tasks": ["rd_design_validation_report"]}
]
}
```
- 全部任务 `default_enabled/creator_configurable/blocking_when_enabled = true`(与本仓库 normalize 惯例一致);
- **skippable 语义**:参考项目的 15 个可声明不适用任务与本仓库「激活规划期可关闭」语义等价(creator 在规划时关闭 = 不适用);「生成完整不适用页仍走审批」列为二期增强(D9);
- `output_doc_type` = 任务键(本仓库惯例 doc type = task key)。
### D4 执行器与质量门禁
- 新增唯一执行器键 **`squad.rdev_doc.v1`**(`workflow/registry.go`),运行时仍统一由 bizdev.ExecuteTask 按 taskKey 分派——与 `squad.test_manager.v1` 模式一致,避免 60 个注册项;
- 质量门禁首期 **`quality.generic.v1`**(全部 60 任务);kind 专用门禁列二期(D9)。
### D5 启动前置门禁(followon 语义)
遵循 WF-DEF-06:**不做流程级 RequiredUpstreamWorkflow**,改为执行器级 precheck(先例:test_manager 查 approved SRS):
- `bizdev.ExecuteTask` 对 `rd_` 前缀任务启动前校验:本项目 **main 工作流 live 实例 `completed`**(即 CDO 报价已批准)。查不到/未完成 → 明确错误文案(「请先完成商务对接流程(CDO 报价批准)后再启动研发设计控制流程」);
- 激活 rdev 实例时(planning 允许,运行由 precheck 兜底):`WorkflowPrerequisiteBanner` 增加 rdev 文案;目录推荐逻辑「main 完成后推荐 PM」扩展「main 完成后推荐 rdev」;
- 启动时拷贝 bizdev 字段:现有 `TaskRunRequest` 已带 project 字段(device_type/intended_use/target_market 来自项目实体),无需额外拷贝机制。
### D6 docgov Stage 字段动态化(P0 必修)
- `bizdev/service.go:483/489` 与 `docgov/repository.go:28` 写死 `V0.5_feasibility` → 改为从请求/冻结实例解析 StageKey 传入(`workflow/runtime/orchestrator.go` 的 `TaskResolution.StageKey` 已具备;`server/task_run_request_build` 把 stage key 带进 `bizdev.TaskRunRequest` 新增的 `StageKey` 字段并透传);
- 兜底策略:解析不到时回落 main 三阶段映射,再回落原值(兼容历史数据,不做历史迁移);
- `maturity` 包的 V0.1/V0.5/V1.0 成熟度映射仅对 main 任务生效,rd_ 任务首期跳过成熟度标签。
### D7 squad 编排(数据驱动重构)
新增 `internal/squad/rdev_catalog.go`:60 项任务目录表(taskKey → title/phase/kind/docCode/skippable/描述),生成来源 = 参考项目 rdev.yaml(一次性转换 + 齐套测试锁定):
- `SupportedTasks` 合并 rdev 目录(`isStandardTask` 命中,避免回落 adhoc);
- `DefaultWorkflowSteps`/`DefaultSquadAgents` 增加 `rd_` 前缀分支,**按 artifact_kind 三套通用编排**(对齐参考项目 squads/rdev.yaml 的 default_steps + 覆盖逻辑):
| kind | 步骤 | 小队 |
|------|------|------|
| document(47) | organizer → engineer(可并行)→ regulatory(可选)→ writer → leader | organizer/engineer/writer/leader;regulatory 注入软件/法规风险类(`rd_sw_*`、`rd_regs_stds`、`rd_adverse_events`、`rd_biocompatibility`、`rd_clinical`、`rd_animal_study`、`rd_risk_*`、`rd_emc_safety`) |
| review_minutes(6) | organizer → writer → leader | organizer/writer/leader(对齐参考项目评审阶段三步) |
| upload_index(7) | organizer → engineer → writer → leader | organizer/engineer/writer/leader |
- leader 角色名「研发设计控制负责人」(对应参考项目 rdev_leader);角色提示复用现有 `configs/agents/*.md`(organizer/engineer/writer/leader/regulatory 已有),rdev 语境差异放进步骤 `Accept` 与 TASK 说明;
- 参考项目 overlays 的核心纪律(写满、结论先行、追溯表必填、缺项「待确认」、不编造数据/签字/附件)合并进:a) 三套 kind 步骤的 `Accept`;b) `configs/shared/writing.md` 增补 DHF 纪律段(GetAgentInstruction 已自动附加该文件,rd 任务天然注入)。
### D8 上游文档注入与血缘
- 首期:`bizdev.ExecuteTask` 对 `rd_` 任务注入 **项目上下文快照**(`projectcontext.BuildSnapshot`,先例 test_manager)+ **同项目已批准文档清单**(bizdev 七件 + 已批准 rd_ 文档,作为 prior_docs 全量注入,交小队自行引用);
- 血缘:沿用 test_manager 模式在 finalize 时记录上游 hash(首期摘要级);精确 `depends_on`(如 rd_verification_review ← rd_design_vv + rd_risk_report_v)列二期(见 [backlog](../../backlog/2026-09-17-rdev-phase2-backlog.md));
- `rd_system_reqs` 与 PM `system_reqs` 的关系:PM 输出若已批准,作为 prior doc 优先注入(不强制、不独占)。
### D9 不适用(N/A)与二期增强
- 首期:N/A = 激活规划期关闭任务(creator_configurable),推进语义由 readiness 门禁保证;
- 二期增强(参考项目行为):保留任务但生成「不适用说明页」(完整理由、走审批);UR/RS 结构化门禁(复用 PM `requirements.json` 模式于 rd_user_needs/rd_system_reqs);review_minutes/upload_index 专用确定性门禁。
### D10 意图与聊天
- U8 多意图 task-generate 从 live 实例 doc tasks 数据驱动——rd 任务应自动可用(P2 验证 60 任务名消歧与澄清卡);
- L1 `extractDocName` 硬编码名表:增补 rd 高频文档名(项目建议书、设计开发计划、风险管理计划、设计验证方案、设计确认报告 等),并**评估改为从 live 实例任务标题动态匹配**(推荐,彻底消除硬编码)。
### D11 前端
- `ProjectWorkflowSwitcher`:rdev 名称/顺序/描述来自目录 API(数据驱动)+ 本地 label 常量增补;
- 激活规划 UI:13 阶段 × 60 任务 × 三权指派是大列表——需按阶段折叠分组、三权「按阶段批量指派 / 继承上一阶段」操作、15 个 skippable 任务预设关闭建议;
- 文档工作台:展示 doc Stage 为 RD 阶段键(依赖 D6);`WorkflowPrerequisiteBanner` rdev 文案;
- 前端测试:workflow 相关既有断言(工作流数量/名称)同步更新。
## 5. 资产与代码改动清单
### 5.1 数据/配置资产
| 资产 | 说明 |
|------|------|
| `internal/workflowdef/manifests/rdev.v2.json` | 13 stage / 60 doc task(D3) |
| `templates/docs/rd_*.md` × 60 | 从参考项目 `templates/docs/*.md` 转换:改名 rd_ 前缀、保留 RD 编号/DHF 归属骨架;核对模板变量(`{{project_name}}/{{generated_at}}/{{snapshot_id}}/{{applicability}}/{{na_rationale}}/{{materials}}` 均为 RenderDoc 可用变量,缺失自动「待确认」) |
| `configs/shared/writing.md` 增补 | DHF 设计控制纪律段(rd 任务注入) |
| `internal/squad/rdev_catalog.go` | 60 项任务目录(title/phase/kind/docCode/skippable) |
### 5.2 Go 代码(按包)
| 包 | 改动 |
|------|------|
| `internal/workflowdef` | catalog_policy.go(常量/名称/顺序/域/医疗四键)、manifest_loader.go(V2ManifestFiles)、bootstrap.go(officialSeedMeta)、validator 文案、publish/catalog 测试更新 |
| `internal/workflow` | registry.go 注册 `squad.rdev_doc.v1` |
| `internal/squad` | rdev_catalog.go 新增;service.go SupportedTasks 合并;workspace.go rd_ 分支(按 kind 三套 DefaultWorkflowSteps/DefaultSquadAgents) |
| `internal/bizdev` | TaskRunRequest 增加 StageKey;ExecuteTask:rd_ precheck(main completed)、prior docs 注入、CreateOrGetDocument 传动态 Stage、ListStages/maturity 对 rd_ 的处理 |
| `internal/server` | task_run_request_build 透传 stage key;workflow_catalog_handlers 名称;齐套校验 Go test(60 manifest 任务 ↔ 模板文件存在非空 ↔ 末模板含「签署」,对齐参考 e2e-rdev.sh 断言 + 「rd_ 键与既有任务键集合不相交」断言) |
| `internal/docgov` | repository.go stage 兜底改为入参优先 |
| `internal/intent` | extractDocName 增补/实例驱动(D10) |
| `web/` | D11 各项 |
### 5.3 文档
- `.doc/ops/short-term/2026-09-17-rdev-workflow-integration.md`(任务条目,随本方案创建)
- FEATURE-MATRIX 新增行(planned → done 演进);验收报告归档 `.doc/test-reports/`
## 6. 分期实施计划
| Phase | 内容 | 分支/PR | 验收标准 |
|-------|------|--------|----------|
| **P0 前置修复** | D6 docgov Stage 动态化 + stage key 透传 + 回归 | `fix/docgov-stage-dynamic` | 现有三工作流全链路 PG 回归 PASS;新文档 Stage 字段 = 实例阶段键 |
| **P1 核心接入** | manifest + catalog/seed + registry + 60 模板 + squad 数据目录与 kind 编排 + rd_ precheck + 齐套 Go test + stub PG 全链路(激活 13 阶段 → rd_proposal 生成/审/批 → 推进 → N/A 关闭路径 → precheck 拒绝路径) | `feature/rdev-core` | `go vet`/`go test -short` PASS;PG 集成测试 PASS;齐套断言 60/60;main 未完成时 rd 任务启动被拒且文案正确 |
| **P2 治理与体验** | 前端(规划 UI 折叠分组/批量三权/PrerequisiteBanner/文档 Stage 展示)+ intent 名称匹配 + prior docs 注入与摘要级血缘/stale + web 测试 | `feature/rdev-web-governance` | web `npm test`/`npm run build` PASS;Playwright 抽检激活与推进;聊天「生成项目建议书」命中 rd_proposal |
| **P3 真实验收** | 真实 PI Agent + MiniMax 全链路:rd_proposal(document)+ rd_planning_review(review_minutes)+ rd_sw_plan 软件类 N/A 三样本;报告归档;CI「PI 三工作流」门禁扩为四 | — | `.doc/test-reports/` rdev 真实 PI E2E 报告;CI green receipt |
| **P4 键名空间化**(决策 4 扩展,D12) | main/pm/tm(+软件两)任务键改 `bd_`/`pm_`/`tm_`(`sw_`)前缀:manifest 新版本 + doc_id 归一映射 + 模板 alias + squad 旧键兼容 + 双路径回归 | `feature/workflow-key-namespace`(**独立验收,不与 P1–P3 合并**) | 旧 live 实例(旧键)与新建实例(新键)双路径 stub 全链路 PASS;全工作流任务键集合无交集断言 PASS;存量文档旧 doc_id 仍可读 |
依赖:P0 → P1 → P2 → P3;P1 与 P2 可部分并行(先冻结前后端契约);P4 在 P3 验收后启动(也可与 P2 并行,但合入 dev 须占集成槽串行)。
## 7. 风险与缓解
| 风险 | 影响 | 缓解 |
|------|------|------|
| 60 任务三权指派 UI 负担 | 激活体验差、误配 | 批量指派 + 阶段继承 + 三权默认创建人兜底(现状) |
| generic 质量门禁误杀评审记录/附件清单类 | 任务被错误打回 | P1 用 stub 对 6+7 个 kind 任务逐一回归;必要时豁免清单 |
| U8/意图对 60 文档名消歧 | 生成错任务 | P2 实例驱动匹配 + 澄清卡;高频名称抽检 |
| 命名空间遗漏 | doc_id/模板冲突回归 | 齐套 test 增加「rd_ 键不与既有任务键相交」断言 |
| CI 门禁与审计口径过时 | nightly 误报 | 同步「PI 三工作流」→ 四;审计 checklist 引用本方案 |
| 大 manifest / 冻结快照体积 | 性能 | 60 任务 JSONB 量级小,P1 PG 测试观察即可 |
## 8. 决策记录(已与用户确认,2026-09-17)
| # | 决策 | 结论 |
|---|------|------|
| 1 | 对外名称 | **「研发设计控制流程」**(key: `rdev`) |
| 2 | 首期范围 | **manifest 一次到位 60 任务 / 13 阶段**,不切试点 |
| 3 | N/A 语义 | 首期「激活规划期关闭」;「生成完整不适用页走审批」等二期增强**记入 backlog**:[2026-09-17-rdev-phase2-backlog](../../backlog/2026-09-17-rdev-phase2-backlog.md) |
| 4 | 任务键前缀 | rdev 60 键统一 `rd_` 前缀;且**现有工作流(main/pm/tm)任务键、模板、阶段等同样做键名空间化处理**(见 D12,独立分期 P4,避免与 rdev 接入耦合) |
### D12 现有工作流键名空间化(决策 4 扩展,P4 实施)
**目标**:全系统任务键命名规约统一为 `<工作流前缀>_<任务>`,杜绝跨工作流 doc_id/模板/任务键冲突:
| 工作流 | 现键(9 个) | 新键 |
|--------|-------------|------|
| main(商务对接) | intake / research / feasibility_dev / feasibility_reg / user_requirements / prelim_design / cdo_quote | `bd_intake` / `bd_research` / `bd_feasibility_dev` / `bd_feasibility_reg` / `bd_user_requirements` / `bd_prelim_design` / `bd_cdo_quote` |
| product_manager | system_reqs | `pm_system_reqs` |
| test_manager | test_manager | `tm_system_verification` |
| rdev(新) | — | `rd_*`(P1 落地,60 个) |
| software_* | (另行盘点 `software.doc.v1` 任务键后纳入 `sw_` 前缀,P4 一并处理) |
**兼容策略(alias 兼容式改名,不破坏存量数据)**:
1. **manifest 版本升级**:main/pm/tm manifest 任务键改为新键 → `UpsertPublishedSeed` 按内容 hash 发布新版本;**冻结实例不迁移**——存量 live 实例继续持有旧键直至 completed(冻结快照是 SSOT,禁止改写);
2. **doc_id 兼容**:`bizdev/doc_id.go normalizeDocID` 增加旧→新映射表(`doc_proj{pid}_intake` → `doc_proj{pid}_bd_intake`),读路径旧 ID 自动归一;**文档账本不批量迁移**,新文档用新键,旧文档旧 ID 保留可查(已有 legacy pattern 归一先例);
3. **模板**:`templates/docs/` 文件改名(bd_intake.md 等),template loader 增加旧名→新名 alias(旧 live 实例运行仍按旧 taskKey 取模板→alias 命中新文件);
4. **squad 白名单**:`SupportedTasks`/`DefaultWorkflowSteps`/`DefaultSquadAgents` 增加旧键 alias 分支(存量实例执行路径不动),新键为主实现;
5. **intent/前端**:`extractDocName` 按文档名匹配不涉键名(无改动);前端断言与 label 按新键更新;
6. **回归**:旧 live 实例(旧键)+ 新规划实例(新键)双路径 stub 全链路回归;齐套断言扩展为「全工作流任务键集合无交集 + 各自前缀正确」。
**风险控制**:P4 独立分支 `feature/workflow-key-namespace`、独立验收,**不与 rdev P1–P3 合并**;若 P4 验收发现存量实例兼容缺口,允许只回退 manifest(DB seed 幂等)。
### 二期 backlog(决策 3,随时可续推进)
见 [2026-09-17-rdev-phase2-backlog](../../backlog/2026-09-17-rdev-phase2-backlog.md):N/A 不适用页生成模式、UR/RS 结构化门禁、review_minutes/upload_index 专用确定性门禁、depends_on 精确血缘与 stale 传播、DMR 双记录归档、软件工作流 sw_ 键盘点等。
@@ -0,0 +1,59 @@
# rdev 模板写作规范
> 适用范围:`templates/docs/rd_*.md`(研发设计控制 / ISO 13485 DHF)
> 更新日期:2026-09-17
## 1. 分工红线(强制)
| 层 | 负责 | 不负责 |
| --- | --- | --- |
| **模板**(`templates/docs/rd_*.md`) | 章节结构、表头、逐节写作指令、示例「待确认」行、治理骨架(编号/适用性/追溯/签署) | 运行时角色口吻、模型选择、粒度下限的强制执行 |
| **overlay / 运行时**(`configs/agents/*`、`configs/shared/writing.md`、未来 overlays) | 写作纪律、DHF 粒度下限、禁止编造、角色边界 | 替代模板定义专业章节结构 |
一句话:**模板管结构与占位;overlay/运行时管写作纪律与粒度下限。**
## 2. 八条基准(源自商务模板实践)
1. **结论先行**:文首结论句完整;后文不得与结论打架。
2. **四段式展开**:结论句 → 表格或列表 → 解读段落 → 出处/支撑;禁止通篇只有列表。
3. **括号指令可执行**:每节括号内写清覆盖范围、缺项规则、禁止项;禁止只写「按本阶段专业结构写」。
4. **表不交空壳**:至少一行「待确认」示例行;禁止空表头。
5. **缺项显式**:统一标「待确认」,并在「待确认清单」汇总。
6. **不做疗效宣称**:设计控制文档禁止疗效/临床效果绝对化用语。
7. **禁止残留提示**:终稿不得留下括号写作提示原文。
8. **追溯可填**:`| RD-` 行存在;上游/下游未知写「待确认」不留空白无说明。
## 3. 治理骨架(每份 rd_ 模板保留)
- 文首元数据:项目 / 生成时间 / 快照 / 文件编号 / 记录归属:DHF / 版本 / 阶段
- `## 结论` / `## 适用性`
- 专业正文各节(≥4 个 `## ` 专业或治理章节合计满足 lint)
- `## 追溯`(含 `| RD-` 行)
- `## 已有材料摘要` / `## 待确认清单` / `## 签署` / `## 说明`
## 4. 补强清单与批次
| 批次 | 范围 | 状态 |
| --- | --- | --- |
| S0 样例 | `rd_design_input_spec` | 本轮 |
| S1 批 1 | `rd_proposal` / `rd_design_input_list` / `rd_system_design` / `rd_regs_stds` / `rd_adverse_events` | 本轮 |
| S1 批 2 | `rd_sw_plan` / `rd_sw_reqs` / `rd_sw_config` / `rd_risk_plan` | 本轮 |
| S1 批 3 | `rd_design_plan` / `rd_user_needs` / `rd_hazard_analysis` / `rd_system_reqs`(SRS 深度移植) | 本轮 |
| S1 续批批1 | 评审记录 6 份(`rd_planning_review` 等) | done |
| S1 续批批2 | 阶段06 硬件/工艺 8 份 | done |
| S1 续批批3 | 阶段06 软件/检验/技术要求+清单 9 份 | done |
| S1 续批批4 | 阶段08 验证 12 份 | done |
| S1 续批批5 | 阶段10–13 转换/确认 11 份 | done |
| S1 续批合计 | 剩余 46 份全部同等深度;allowlist 60/60;真 PI 抽样 PASS | done([报告](../../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md)) |
| S2 / S3 | per-stage 步骤、overlay 机制、专用门禁 | follow-up |
## 5. Lint 门禁
`internal/workflowdef/rdev_template_lint_test.go` 对「已补强 allowlist」断言:
- 不含「按本阶段专业结构写」
- 正文 `## ` 章节 ≥ 4
- 含追溯表行 `| RD-`
- 含 `## 待确认清单` 与 `## 签署`
未列入 allowlist 的模板不参与断言;随批次增长扩大 allowlist。
@@ -0,0 +1,37 @@
# docgov 变更提案 HTTP 测试报告
## 一、 测试背景 (Background)
- 引擎已有 Propose/Decide,但缺少 propose HTTP;前端 pendingProposal 为本地模拟。
- author-only 收口后补齐变更提案闭环。
## 二、 测试目标 (Test Objectives)
- `POST /api/v1/docgov/proposal` 写库成功
- `POST /api/v1/docgov/proposal/decide` 批准写库
- 前端 client 单测覆盖路径
## 三、 测试方案与环境 (Test Plan & Environment)
- OS: Linux;后端:agent-dev `:8080` schema 52;真实 `pi-agent` 环境(本用例不触发任务跑批)
- 层级:Go handler 单测 + 前端 client 单测 + 真实 HTTP
## 四、 预期结果 (Expected Results)
- claim 已认领文档 → propose → status=`pending_author_approval` → decide approve → `approved_by_author`
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### TC-HTTP-01 claim → propose → decide
- **测试输入**: doc `doc_proj6425_rd_design_input_spec`(author=admin/9,已认领)
- **实际输出**: 见 assets `01`–`05`;proposal `prop_rd_design_input_spec_1789654256551680649` → `approved_by_author`
- **评价判定**: PASS
- **性能与耗时**: 全链路 <1s(不含 rebuild)
### TC-UNIT-01
- `go test -run TestServer_DocGovProposeAndDecideHTTP ./internal/server/` PASS
- `node --test web/src/api/docgov.test.ts` 6/6 PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
- 合入后冒烟:`go vet ./...`;`go test -short ./internal/server/ ./internal/docgov/` PASS
- `./scripts/env-service.sh dev rebuild`;`GET /health` → status=ok schema=52
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 达到合入/推送标准;**未**晋升 test/main
- 后续:批准后自动应用受控正文 diff(非本期)
@@ -0,0 +1,128 @@
# 文档编制人兼任 U6 多职责动作与真实闭环 测试报告
## 一、 测试背景 (Background)
U1–U5 已落地管理员总开关、逐文档 `duty_policy=author_only`、ABAC 门禁与设置页 UI。交付验收时发现两处前端缺口:
1. 审批动作条从未调用已存在的 `docgov` HTTP(claim / submit-review / review-decision / approver-decision),仅本地改 `lifecycleState`;
2. `resolveCurrentDocRole` 的 author-first 短路使 A/A/A 用户永远只解析为 `author`,审核/批准按钮与快捷指令不可见。
U6 修复可见性与真实 API 接入,使编制人兼任完整闭环第一次可验收。
## 二、 测试目标 (Test Objectives)
- author_only(三职同一人)下 A 可见送审/审核/批准动作;非 A 不可见且直连接口 403;
- 点击认领→送审→审核通过→终审批准走真实后端,写 `document_records` / `document_audit_logs`(含 `duty_policy`);
- 动作条展示「编制人兼任」徽标;`duty_policy` 从 summary 透传到 AST;
- 前端单测与 `tsc --noEmit` 回归通过。
## 三、 测试方案与环境 (Test Plan & Environment)
| 项 | 值 |
|---|---|
| OS | Linux |
| 环境 | dev `:8080`(feature worktree rebuild,`schema_version=52`,`agent_backend=pi-agent`) |
| 前端 | worktree Vite `:5173` 代理 API |
| 被测文档 | `doc_proj6425_rd_design_input_spec`(项目 6425,`rdev-s0-fresh-*`,既有真实 PI 生成正文) |
| 配置 | 实例快照 `duty_policy=author_only`,有效职责 A/A/A(user_id=9 系统管理员) |
| 负例用户 | `lizhuguan`(id=11) |
分层:
1. 前端单元:`docGovActionVisibility` + `docgov` API client;
2. HTTP 真实闭环:claim → submit → review → approve;
3. HTTP 负例:非职责人 403;
4. 浏览器:Playwright(官方 image)打开 Vite,断言徽标与送审按钮。
## 四、 预期结果 (Expected Results)
| 用例 | 预期 |
|---|---|
| AE-UI | A 打开 author_only 文档见「编制人兼任」+ 送审按钮 |
| AE-API | A 依次 claim/submit/review/approve → `current_state=approved`,审计含 `duty_policy=author_only` |
| AE-NEG | 李主管 review/approve → `DOC_DUTY_FORBIDDEN` HTTP 403 |
| AE-UNIT | author_only 三动作对 A 全 true、对非 A 全 false;分离三人矩阵不变 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 前端单元
**输入**:`npm test` + `npx tsc --noEmit`(worktree `web/`)
**实际输出**:`ℹ tests 390` / `pass 390` / `fail 0`;含 `docgov lifecycle API client` 4 例与 `docGovActionVisibility` author_only 矩阵;`tsc --noEmit` 无错误。
**判定**:PASS
### 5.2 HTTP 真实闭环(author_only)
**输入**:admin Bearer 调用四接口(证据:`assets/2026-09-17-document-author-only-u6/api-lifecycle-author-only.txt`)
**实际输出(摘要)**:
- `POST /docgov/review-decision` → HTTP 200,`current_state=approving`,`duty_policy=author_only`
- `POST /docgov/approver-decision` → HTTP 200,`current_state=approved`
- 审计:`submit_review` / `review_approve` / `approver_approve` 的 `details.duty_policy=author_only`(`db-final-author-only.txt`)
**判定**:PASS
### 5.3 HTTP 负例
**输入**:`lizhuguan` 对同一文档 review/approve(`api-negative.txt`)
**实际输出**:
```text
{"error":"DOC_DUTY_FORBIDDEN","message":"当前用户不是该文档的对应职责人"}
HTTP 403
```
(审核与批准各一次)
**判定**:PASS
### 5.4 浏览器(Vite + Playwright)
**输入**:注入 admin 会话 → 打开 `rdev-s0-6425` → 《设计输入规格书》
**实际输出**:
- `browser-visibility.json`:`hasBadge=true`,`hasClaim=true`,`hasSubmit=true`
- 截图 `screenshots/04-action-bar.png`:明确显示「编制人兼任」徽标与「提交送审」按钮
**判定**:PASS(可见性与徽标);按钮逐级点击以 API 闭环为准(浏览器侧状态机与网络时序未作为唯一证据)。
### 5.5 性能与耗时
| 步骤 | 耗时量级 |
|---|---|
| Vite npm test | ~2s |
| tsc --noEmit | ~3s |
| API 四步闭环 | <1s |
| Playwright 全流程 | ~25s(含容器内 npm i playwright) |
## 六、 自动化测试套件汇总 (Test Suite Execution)
```text
web: npm test → 390 pass / 0 fail
web: npx tsc --noEmit → clean
```
Go 侧 U1–U4 既有矩阵本轮未重跑全量;dev 容器已含 `allow_author_only_approval` 二进制与 goose 00050–00052。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
**结论**:U6 达到合并前验收标准——author_only 多职责动作可见、真实 docgov 闭环与负例 403、兼任徽标透传均有证据。回链 U1–U6 与 FEATURE-MATRIX。
**限制说明**:
- 本轮闭环基于已激活实例快照补丁为 `author_only` + 既有 PI 生成文档;管理员总开关→创建者设置→激活的产品配置链路由 U1–U5 覆盖,本报告不重复。
- 变更提案 HTTP 路由仍缺失(独立缺口,见 audit 笔记),不在 U6 范围。
**后续**:合入 `dev` 后按集成槽位正式冒烟;可补 Playwright 选择器精化使浏览器点击与 DB 状态强一致。
## 相关链接
- Remediation: `.doc/remediation/2026-09-17-document-author-only-plan.md` U6
- Short-term: `.doc/ops/short-term/2026-09-17-document-author-only-u6.md`
- Assets: `.doc/test-reports/assets/2026-09-17-document-author-only-u6/`
- 变更提案缺口: `.doc/audit/2026-09-17-docgov-modification-proposal-http-gap.md`
@@ -0,0 +1,109 @@
# 个人工程中控台(engineering-dashboard)测试报告
## 一、 测试背景 (Background)
仓库需要独立于产品后台的本地只读工程中控台,避免把文档 `done` 误读为已合并或已部署。方案见 [设计](../archive/design/2026-09-17-personal-engineering-control-center-plan.md)。本报告验收一期 `serve` / `export` 实现。
## 二、 测试目标 (Test Objectives)
- 实时 HTML、离线 HTML、JSON 共用 `generation_id` / `revision_id`
- 计划 / Git 实施 / 验证 / 实装四轴独立
- rdev、dev ahead、main events 分叉样本(单元夹具)按方案输出
- 单源失败可 degraded;loopback / token / Host / 只读方法防护生效
- 导出 HTML `0600`、可离线阅读 Markdown、不嵌 assets
## 三、 测试方案与环境 (Test Plan & Environment)
- OS: Linux;Go module `chat-agent-system`
- 工作树:`.worktrees/feature-engineering-dashboard`(`feature/engineering-dashboard`)
- 层级:包单元/集成测试 + CLI 真实 `serve`/`export` 冒烟(只读观察,未启停共享 compose)
## 四、 预期结果 (Expected Results)
| 用例 | 预期 |
|------|------|
| 模型四轴 | doc done 不改 Git/部署 facets |
| rdev 夹具 | planned / unclaimed / 实装 unknown |
| dev ahead | ahead>0 且备注含未确认远端 |
| main fork | readiness ok + containers partial + conflict |
| HTTP | POST 405;无 token 401;坏 Host 403;非 loopback bind 拒绝 |
| export | 权限 0600;含 identity;无 script breakout |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 单元与包测试
- **测试输入**: `go test ./internal/engineeringdashboard/ ./cmd/engineering-dashboard/ -count=1`
- **实际输出**:
```text
ok chat-agent-system/internal/engineeringdashboard 0.009s
? chat-agent-system/cmd/engineering-dashboard [no test files]
```
- **判定**: PASS
- **耗时**: ~0.01s(包测)
### 5.2 go vet
- **测试输入**: `go vet ./internal/engineeringdashboard/... ./cmd/engineering-dashboard/...`
- **实际输出**: (无输出)
- **判定**: PASS
### 5.3 真实 export
- **测试输入**: `go run ./cmd/engineering-dashboard export --repo <worktree> --output /tmp/engdash-export.html`
- **实际输出**: 文件权限 `600`;体积可离线打开;含 CSP 与 snapshot identity
- **判定**: PASS(`stat -c '%a'` → `600`)
### 5.4 真实 serve 冒烟
- **测试输入**: `engineering-dashboard serve --repo <worktree> --addr 127.0.0.1:8799`,随后 curl
- **实际输出**:
```text
{"ok":true}
generation gen_1
revision rev_3378ee42f645c4ab1af69cf691c00103
tasks 50
docs 452
sources [('docs', 'ok', 'fresh'), ('git', 'ok', 'fresh'), ('runtime', 'ok', 'fresh')]
POST_reject HTTPError 405
no_token=401
bad_host=403
```
- **判定**: PASS(HTML/JSON 同源 identity;安全负例符合预期)
- **说明**: 工作树上尚未合入未跟踪的 rdev 文档树;rdev/dev-ahead/main-events **样本契约由包内 fixture 单测覆盖**(`TestModel_*` / `TestReconcile_*`)。
### 5.5 夹具验收样本(单元)
| 样本 | 测试 | 判定 |
|------|------|------|
| rdev 已计划未实施 | `TestReconcile_RDevPlannedUnclaimed` / `TestModel_AcceptanceSamplesAxes` | PASS |
| local ahead origin | `TestReconcile_DevAheadSample` / `TestGit_AheadDoesNotClaimRemoteAvailable` | PASS |
| main ready vs events restarting | `TestReconcile_MainEventsForkConflict` / `TestRuntime_ReadyOKAndEventsRestarting` | PASS |
| Herdr vs 产品 PI Runner | `TestModel_ClaimedWithoutRuntimeKeepsActivityUnknown` | PASS |
## 六、 自动化测试套件汇总 (Test Suite Execution)
对本工具包:
```text
go test ./internal/engineeringdashboard/ ./cmd/engineering-dashboard/ -count=1
# ok engineeringdashboard
go test -short ./internal/engineeringdashboard/... ./cmd/engineering-dashboard/... -count=1
# ok
go vet ./internal/engineeringdashboard/... ./cmd/engineering-dashboard/...
# clean
git diff --check
# clean
```
全仓 `go test -short ./...` 在合入 `dev` 占槽时于主仓执行(本工具未改产品包)。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- **结论**: 一期达到合并标准(独立 CLI、同源快照、四轴、安全边界、导出)。
- **后续**: 跨快照历史、远端 CI/Gitea、受限 Markdown/Mermaid、Agent 查询 API(设计附录已列,不在本期)。
## 相关链接
- 任务: [../archive/ops/short-term/2026-09-17-engineering-dashboard.md](../archive/ops/short-term/2026-09-17-engineering-dashboard.md)
- 设计: [../archive/design/2026-09-17-personal-engineering-control-center-plan.md](../archive/design/2026-09-17-personal-engineering-control-center-plan.md)
@@ -0,0 +1,113 @@
# 首次加载 U2:字体自托管与静态资源交付 测试报告
## 一、 测试背景 (Background)
诊断确认 8080 登录页下载约 2.82 MB 未压缩 JS,且 Google Fonts 外链 CSS 可阻塞首屏;Go `serveSPA` 无压缩协商、无明确缓存头,且缺失 `/assets` 会回退 HTML。本轮实施 U2(自托管字体、构建期预压缩、静态交付协商与 404 修复),不包含 U3 拆包。
## 二、 测试目标 (Test Objectives)
- 登录页无 `fonts.googleapis.com` / `fonts.gstatic.com` 请求;阻断该域名仍可出现登录表单
- 主 JS 响应带 `Content-Encoding: br` 或 `gzip`,传输体积显著下降
- `/assets/missing.js` → 404 且 body 非 HTML
- HTML `Cache-Control: no-cache`;`/assets`/`/fonts` `immutable`;API 无 public 长缓存
- 单元测试与 `go test -short` / `npm test` 通过
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;Go 1.27.1;dev 容器 `shuimu-agent-app-dev`(镜像 `agent-dev-app@sha256:2d74fe18…`)
- 入口:`http://127.0.0.1:8080`(构建产物)
- 层级:Go 单元测试(`static_assets_test.go`)、前端断言、curl 协商验收、Playwright Docker(`mcr.microsoft.com/playwright:v1.63.0-noble`)浏览器探针
- 代码:`dev@bc01781`(merge `feature/initial-load-perf-u2`);无缓存重建后镜像含 `/fonts` 与 `.br/.gz`
## 四、 预期结果 (Expected Results)
| 场景 | 预期 |
|------|------|
| `Accept-Encoding: gzip, br` | `Content-Encoding: br`,主 JS ~624 KiB |
| 仅 `gzip` | `Content-Encoding: gzip` |
| identity / `gzip;q=0` | 无 `Content-Encoding`,原始体积 |
| `/assets/missing-hash.js` | 404,非 HTML |
| HTML / SPA fallback | `Cache-Control: no-cache` |
| 字体域名阻断 | 登录输入框仍可见 |
| API 未认证 | 401,无 `immutable` |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 单元测试
- **Input**: `go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding'`
- **Actual**: `ok`
- **Verdict**: PASS
- **Duration**: ~0.66 s
- **Input**: `npx tsx --test src/styles/noExternalFonts.test.ts`;`npm test`
- **Actual**: 字体断言 2/2 PASS;前端套件 380 + vitest 32 PASS
- **Verdict**: PASS
### 5.2 curl 协商(8080,无缓存重建后)
证据:`.doc/test-reports/assets/2026-09-17-initial-load-perf-u2/after-curl-nocache.txt`
| 检查项 | 实际 | 判定 |
|--------|------|------|
| HTML | `Cache-Control: no-cache`,`Vary: Accept-Encoding`,无 Google Fonts | PASS |
| JS + `gzip, br` | `Content-Encoding: br`,下载 **623,898 B**(原 2,820,055 B,−77.9%) | PASS |
| JS + `gzip` | `Content-Encoding: gzip`,`immutable` | PASS |
| JS identity | 无 encoding,`Content-Length: 2820055`,仍有 `Vary` | PASS |
| `/assets/missing-hash.js` | **404** `404 page not found` | PASS |
| `/fonts/inter-v20-latin.woff2` | 200,`immutable`,48256 B,无 Content-Encoding | PASS |
| `/sessions/demo` | 200 + index,`no-cache` | PASS |
| `/api/v1/chat/sessions` | 401 JSON,无 immutable | PASS |
### 5.3 浏览器探针
证据:`assets/2026-09-17-initial-load-perf-u2/browser-u2.json`
| 场景 | 登录可见 | transferBytes | 外链字体请求 | 判定 |
|------|----------:|------------:|-------------:|------|
| login-cold | **205 ms** | **681,964** | 0 | PASS |
| login-font-domain-blocked | **213 ms** | 681,964 | 0 | PASS |
对比诊断 before(同机冷缓存登录页):可见 ~662 ms,transferSize 2,857,761 B;主 JS 未压缩 2,820,055 B。本轮未登录首屏传输量下降约 **76%**。
主 JS Resource Timing:`transferSize=624198`,`decodedBodySize=2820055`(确认浏览器实际收到 br 变体)。
### 5.4 重启时间线(U7 起点证据,非 U7 完成)
| 事件 | 时刻 (UTC) |
|------|------------|
| 容器 StartedAt | 2026-09-17T08:22:48.548Z |
| goose no migrations / kb online | 08:22:48.660–.676 |
| 日志「监听地址」 | ~08:22:48.7 |
| health=200 | ≤08:22:50(重建后首次探测) |
app restart → listen ≈ **150–200 ms**(DB 已就绪、无迁移)。**不能**据此宣称用户「整机重启十几秒」已解决。
首次 `env-service.sh dev rebuild` 曾因并行 Agent 切走工作树导致镜像装入旧 `web/`;随后在 `dev` 上 `docker compose build --no-cache app` 后验收通过。证据见 `rebuild-nocache-log.txt`。
### 5.5 SSE
未认证 `GET /api/v1/chat/stream` 立即 401 JSON;静态压缩路径不触及 API/SSE。PASS(静态层无缓冲回归迹象)。
## 六、 自动化测试套件汇总 (Test Suite Execution)
```text
go test -short ./internal/server/ -run 'TestStaticAssets_|TestParseAcceptEncoding' → ok
npm test (web) → 380 + 32 PASS
npm run build → precompress 49 .br / 49 .gz
```
未在本报告将 stub 输出当作交付证据;浏览器与 curl 均打真实 8080 容器。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- **U2 达到合并/dev 验收标准**:字体去阻塞、压缩协商、缓存头、assets 404 均有真实证据。
- **不宣称** Success Criteria 全表达标(U1 登录态套件未建;U3 拆包未做,首屏 JS 解码体仍约 2.8 MB)。
- 后续:U3 懒加载;U1/U7 补齐重启与登录态预算;并行 Agent 占用主仓时,合入容器重建须 `--no-cache` 或锁定工作树以免 BuildKit 读到脏上下文。
### 提交与环境
- 分支:`feature/initial-load-perf-u2` → 已 `merge --no-ff` 入 `dev@bc01781`
- 镜像:`agent-dev-app` sha256:2d74fe184585ec0d0d24a051cd6bbc0cfb5b2ef050a376a32027c8e442703cd1
- 资源:`/assets/index-Bu0CqZB_.js` + `.br`
- 未推送、未晋升 test/main
@@ -0,0 +1,49 @@
---
title: "首次加载性能诊断测量(非优化验收)"
status: done
created: 2026-09-17
updated: 2026-09-17
---
# 诊断测量报告
## 范围与结论
只读未登录浏览器基线、静态资源响应与受控网络实验完成;没有业务代码修改,不是优化 PASS 或完整重启验收。用户补充现象为 3100/8080/8081 系统重启后第一次进入约十数秒。
[审计](../audit/2026-09-17-initial-load-performance-audit.md) 包含数值、因果链、源码定位和限制;[方案](../remediation/2026-09-17-initial-load-performance-plan.md) 含重启矩阵、性能预算与治理回归。
## 环境与步骤
- 2026-09-17;源码读取主仓 `feature/rdev-core@52f0fbc`,文档 worktree 基线 `dev@d0ef696`。
- 实际 app-dev image `sha256:355ec1af39c5233ac7e710c6c4300779681edd96d5da85258a9dde71a1698af2`;app-test `sha256:ee7df995c59eb0faf8e26160113d36fcdb57844b4e96989709f8b6edc2f00395`。未证明这些镜像与源码 commit 相同。
- 主 JS hash 分别为 8080 `index-BLnmtk_3.js`、8081 `index-Dk3TnkZv.js`、8000 `index-BT80OB_W.js`。
- 浏览器采用现有 `mcr.microsoft.com/playwright:v1.63.0-noble`、headless Chromium;不登录、不调用写接口、无截图/正文保存。基线未加 CPU 限速。
- 宿主 Playwright 因缺 libatk 启动失败;隔离浏览器容器成功,不安装/修改宿主库。
- 新 context 冷缓存 → 同 context 第二次导航;页面 input 可见后等 1.5 秒采集 Resource Timing。每场景 n=1,未报告分位数。
- 受控场景包括 CDP 10/2 Mbps + 80ms、字体立即失败、字体延迟 5 秒后失败。CDP document RTT 未精确达到设置值,因此是带宽敏感性实验,不是公网仿真认证。
- 3199 隔离 Vite 使用主仓源码、独立 `/tmp` 空 cacheDir,不清理原有 3100 依赖缓存,不更改 Vite 配置;结束后停止临时实例。
- 日志仅提取启动时间和固定事件标记,不保存原始日志。现有 app start→打印监听 dev 166 ms/test 142 ms,不等同真正 ready 或整机重启耗时。
## 结果
| 检查 | 结果 | 限制 |
|---|---|---|
| 三容器主 JS 未压缩 | 确认,约 2.80–2.82 MB | 用户上游代理压缩未知 |
| 8080 冷/热差异 | 662/62 ms | n=1,本机未登录 |
| 带宽敏感性 | 10 Mbps 2.64 s;2 Mbps 11.78 s | 模拟,不是用户网络 |
| 外部 CSS 阻塞 | 人为延迟5s → 登录5.16s | 不能称自然延迟5s |
| 3100资源成本 | 207 请求/12.24 MB | 当时 Vite 服务已运行 |
| 隔离 Vite 空缓存 | 首访1.58s/再次171ms,首访14.45MB | 启动早于浏览器连接,非完整冷启动总耗时 |
| 登录态/整机重启 | 未覆盖 | U1/U7必须补齐 |
| 功能/真实PI/优化收益验收 | 未执行 | 本轮无实现 |
## 原始数据与复现
证据目录:[assets](assets/2026-09-17-initial-load-performance/)。`browser.json`、`controlled.json`、`vite-cold.json` 为浏览器结果;`assets.json` 为静态头/体积摘要。对应 `*.cjs` 是诊断探针,不是业务测试。
复现普通浏览器基线可使用已有 Playwright 镜像,挂载本仓到 `/repo:ro`、证据临时输出目录到 `/out`,执行 `/out/probe.cjs`。脚本假设 `/repo/web/node_modules/playwright` 存在;运行前复制脚本到临时输出目录,不覆盖既有证据。字体拦截会禁用该 context 缓存,不得拿其 warm 结果与正常 warm 作性能比较。
## 交付状态
方案及证据仅在独立本地 worktree,未合 dev、未 push;无共享服务重启/镜像重建。后续实施按 CURRENT 认领与集成槽规约执行。
@@ -0,0 +1,51 @@
# 晋升 optional-duty null FK → test(rc-v1.0.0-beta.4)
## 一、 测试背景 (Background)
dev 已验证 `CreateOrGetDocument` 可选职责 `reviewer_id=0` FK 修复。同一缺陷会波及 test;需合入 `test` 并重建服务。
## 二、 测试目标 (Test Objectives)
- 本地 `test` 合入含修复的 `dev`,tag `rc-v1.0.0-beta.4`
- `./scripts/env-service.sh test rebuild` 后 `:8081` 健康,二进制含 `DOC_LEDGER_ERROR`
## 三、 测试方案与环境 (Test Plan & Environment)
| 项 | 值 |
|---|---|
| 合入 | `git checkout test && git merge --no-ff dev`(手工;跳过缺 receipt 的 `promote-to-test.sh`) |
| Tag | `rc-v1.0.0-beta.4` |
| HEAD | `d73d2e8` |
## 四、 预期结果 (Expected Results)
- health/ready:`env=test`、`schema_version=48`
- `/app/server` 含 `DOC_LEDGER_ERROR` / 「文档职责账本写入失败」
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 合入与 tag
- **输入**: merge `dev` → `test`;annotated tag
- **输出**: `test@d73d2e8`;`rc-v1.0.0-beta.4`
- **判定**: PASS
### rebuild + 冒烟
- **输入**: `./scripts/env-service.sh test rebuild`;`curl :8081/health` `/ready`;`:8089/health`
- **输出**:
```json
{"status":"ok","env":"test","schema_version":48,"schema_ready":true,"task_store_ready":true}
```
`FIX_PRESENT=yes`(`grep -a DOC_LEDGER_ERROR /app/server`)。events:`{"env":"test","status":"ok"}`。
- **判定**: PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
本波为环境晋升冒烟;根因修复证据见 [2026-09-17-docgov-optional-duty-null-fk-test-report.md](./2026-09-17-docgov-optional-duty-null-fk-test-report.md)。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
test 已更新至 `rc-v1.0.0-beta.4` 并 rebuild。未推远端、未合 `main`。
@@ -0,0 +1,93 @@
# rdev 模板深度补强 S1 续批(剩余 46 份)测试报告
## 一、 测试背景 (Background)
S0+S1 首批已将阶段 01–05 共 14 份 `rd_*` 模板补强并合入;剩余 46 份(评审记录、阶段 06–13 硬件/软件/检验/验证/转换确认)仍为占位或中等档深度。本轮按用户确认范围全部按技术类同等深度补强,并抽样真 PI 打样收口。
## 二、 测试目标 (Test Objectives)
- 46 份模板按写作规范补强:四段式章节、ID 表、「待确认」、`| RD-` 追溯、签署骨架;无「按本阶段专业结构写」
- `rdevTemplateDepthAllowlist` 扩至全 60 份;`TestRDevTemplateDepthLint` PASS
- 真 PI 抽样:评审记录类 `rd_planning_review` + 验证协议类 `rd_design_vv` 终稿实质论证、无占位残留
- `go vet ./...` 与 `go test -short ./...` 全绿
- 附带修复:`UpsertPlanningInstance` 分配下一 `instance_no`(避免 main 已完成后无法再存 rdev 计划)
## 三、 测试方案与环境 (Test Plan & Environment)
| 项 | 值 |
|---|---|
| OS | Linux |
| 分支 / worktree | `feature/rdev-template-depth-s1-continued` / `.worktrees/feature-rdev-template-depth-s1-continued` |
| 后端 | `pi-agent` + MiniMax-M2.7-highspeed(shuimu-pi-agent-dev) |
| HTTP | `http://127.0.0.1:8080`(agent-dev) |
| 层级 | 模板 lint + 包回归 short + 真 PI 抽样 E2E |
资产目录:[assets/2026-09-17-rdev-template-depth-s1-continued/](./assets/2026-09-17-rdev-template-depth-s1-continued/)
### 用例矩阵
| 批 | 范围 | 份数 | 验证 |
|---|---|---|---|
| 1 | 评审记录 | 6 | lint |
| 2 | 阶段06 硬件/工艺 | 8 | lint |
| 3 | 阶段06 软件/检验/清单 | 9 | lint |
| 4 | 阶段08 验证 | 12 | lint + 真 PI `rd_design_vv` |
| 5 | 阶段10–13 转换/确认 | 11 | lint |
| 抽样 | 评审记录 | 1 | 真 PI `rd_planning_review` |
## 四、 预期结果 (Expected Results)
| 用例 | 预期 |
|------|------|
| lint 全量 | 60 key allowlist 无占位、章节≥4、含追溯/待确认/签署 |
| `rd_planning_review` | 完成态;含「评审范围与对象 / 问题与决议 / 评审结论」;无占位;chars>400 |
| `rd_design_vv` | 完成态;含「目的与范围 / 方法与判定标准 / 风险与残余风险关联」;无占位;chars>400 |
| short 回归 | 全绿 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 模板 lint(全 60 份 allowlist)
- **测试输入**:`go test ./internal/workflowdef/ -run TestRDevTemplateDepthLint -v -count=1`
- **实际输出**:`--- PASS: TestRDevTemplateDepthLint (0.00s)`
- **评价判定**:PASS
- **性能与耗时**:<1s
### 5.2 真 PI — `rd_planning_review`(评审记录类)
- **测试输入**:项目 `6446`(`rdev-s1c-pi-1789657210`),rdev 实例 `313`,阶段 `RD02_planning_review`,backend=`pi-agent`
- **实际输出**(摘自 [summary-s1-continued.json](./assets/2026-09-17-rdev-template-depth-s1-continued/summary-s1-continued.json) / [console.log](./assets/2026-09-17-rdev-template-depth-s1-continued/console.log)):
- `status=completed`,elapsed≈290s,chars=7958
- `no_placeholder=true`,`has_review_sections=true`
- **终稿取样**:[rd_planning_review-final.md](./assets/2026-09-17-rdev-template-depth-s1-continued/rd_planning_review-final.md)
- **评价判定**:PASS
- **性能与耗时**:约 290s
### 5.3 真 PI — `rd_design_vv`(验证协议类)
- **测试输入**:同项目推进至 `RD08_verification` 后启动
- **实际输出**:
- `status=completed`,chars=10970
- `no_placeholder=true`,`has_protocol_sections=true`
- **终稿取样**:[rd_design_vv-final.md](./assets/2026-09-17-rdev-template-depth-s1-continued/rd_design_vv-final.md)
- **评价判定**:PASS
- **性能与耗时**:整段抽样脚本约 704s(含评审审批与阶段推进)
### 5.4 运行时修复备注
worktree 重建后若缺少根 `.env`,会导致 `MINIMAX_API_KEY` / `PI_AGENT_RUNNER_AUTH_TOKEN` 为空,表现为 PI 空跑或 `typed result rejected`。本轮通过 symlink 根 `.env` 并 `--force-recreate` app/pi-agent 恢复;另提交 `instance_no` 递增修复以支持 main 完成后另存 rdev 计划。
## 六、 自动化测试套件汇总 (Test Suite Execution)
```text
go test ./internal/workflowdef/ -run TestRDevTemplateDepthLint -v -count=1
--- PASS: TestRDevTemplateDepthLint (0.00s)
go test -short ./...
# 全包 PASS(含 internal/server、workflowdef、projectinstance 等)
```
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- **结论**:S1 续批达到合入标准——46 份模板深度补强完成,lint 覆盖 60/60,真 PI 双抽样 PASS。
- **后续**:S2(per-stage 编排/配置化)、S3(overlay/专用门禁)、P2 前端、P3 三样本全量 E2E、P4 键名空间化仍属 backlog;本轮**不晋升** test/main。
@@ -0,0 +1,118 @@
# rdev 模板深度补强(S0 + S1 首批)测试报告
## 一、 测试背景 (Background)
`rdev` 60 份模板多数仍含「按本阶段专业结构写」通用占位;且 `rdevLeaderAgent` 虽注册了角色,但 `buildSubWorkspaces` 按角色名加载 `configs/agents/leader.md`,导致研发终审全部回落商务口吻。本轮按计划交付 B1 leader 注入修复、阶段 01–05 共 14 份模板专业章节补强,并以 dev 真实 PI 打样收口。
## 二、 测试目标 (Test Objectives)
- rdev leader 子工作区 `AGENTS.md` 含「设计控制 / 研发设计控制负责人」,且不含「商务对接负责人」「CDO」
- intake leader 回归仍含「商务对接负责人」
- 14 份已补强模板 lint 绿灯(无通用占位、章节≥4、含追溯/待确认/签署)
- 真实 PI:`rd_design_input_spec` 终稿五节有实质论证;账本 `stage=RD03_design_input`
- `go vet ./...` 与 `go test -short` 全绿
## 三、 测试方案与环境 (Test Plan & Environment)
| 项 | 值 |
|---|---|
| OS | Linux |
| 分支 / worktree | `feature/rdev-template-depth` / `.worktrees/feature-rdev-template-depth` |
| 后端 | `pi-agent` + MiniMax(shuimu-pi-agent-dev) |
| HTTP | `http://127.0.0.1:8080`(agent-dev) |
| 层级 | 单元(prompt 注入 / lint)+ 包回归 short + 真 PI 端到端 |
资产目录:[assets/2026-09-17-rdev-template-depth/](./assets/2026-09-17-rdev-template-depth/)
## 四、 预期结果 (Expected Results)
| 用例 | 预期 |
|------|------|
| S0.1 PrepareWorkspace(rd_design_input_spec) | leader AGENTS 设计控制口径,无商务串味 |
| S0.1 PrepareWorkspace(intake) | leader AGENTS 仍含商务对接负责人 |
| S0.2 / S1 lint allowlist 14 份 | 无「按本阶段专业结构写」;`## `≥4;含 `\| RD-`、待确认、签署 |
| S0.3 main-only intake | 真 PI completed;文档 `stage=V0.1_triage`;实例 completed |
| S0.3 rdev-only DI | 真 PI completed;五节实质;`stage=RD03_design_input`;leader 无商务串味 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 S0.1 leader prompt 注入(单元)
- **测试输入**: `go test -short ./internal/squad/ -run 'RDevLeader|LeaderPrompt|InstructionsFile' -count=1`(及全包 short)
- **实际输出**: `ok chat-agent-system/internal/squad`(见第六节汇总)
- **判定**: PASS — `GetAgentInstructionFile` + `InstructionsFile` 优先注入已覆盖;商务回归保留
### 5.2 模板 lint(S0.2 + S1 14 份)
- **测试输入**: `go test -short ./internal/workflowdef/ -run RDevTemplateLint -count=1`
- **判定**: PASS — allowlist 覆盖 `rd_design_input_spec` + 批 1/2/3 共 14 份
### 5.3 真实 PI:main 仅 intake(项目 6424)
- **测试输入**: 新建 medical_device 项目;规划期仅保留 `intake`;`backend=pi-agent`;异步 `POST /api/v1/tasks/runs`
- **实际输出**(摘自 [pi-intake-meta.json](./assets/2026-09-17-rdev-template-depth/pi-intake-meta.json)):
```text
run_id=run_1789635054471569201
Status=completed
WorkflowStageKey=V0.1_triage
WorkspaceID=/app/data/workspaces/bizdev/intake_1789635054485631143
duration_ms=220109
```
- 终稿取样:[intake-final.md](./assets/2026-09-17-rdev-template-depth/intake-final.md)
- intake leader(商务回归):[intake-leader-AGENTS.md](./assets/2026-09-17-rdev-template-depth/intake-leader-AGENTS.md) 含「商务对接负责人」
- 实例推进至 completed:[main-instance-final.json](./assets/2026-09-17-rdev-template-depth/main-instance-final.json)
- **判定**: PASS
- **耗时**: ~220 s
### 5.4 真实 PI:rdev 仅 rd_design_input_spec(项目 6425)
- **测试输入**: 激活 `rdev`;规划期仅保留 `rd_design_input_spec`;推进至 RD03;同项目插入 completed `main` 实例以满足硬 precheck;真 PI 生成
- **实际输出**(摘自 [summary-rdev.json](./assets/2026-09-17-rdev-template-depth/summary-rdev.json) / [pi-rd_design_input_spec-meta.json](./assets/2026-09-17-rdev-template-depth/pi-rd_design_input_spec-meta.json)):
```text
run_id=run_1789635960880707641
Status=completed
WorkflowStageKey=RD03_design_input
di_chars≈15988
has_five_sections=true(## 一、功能要求 … ## 五、法规与标准符合性)
no_placeholder=true
agents_ok=true(研发设计控制负责人)
no_business_in_agents=true
no_business_in_final=true
wall≈450s(09:06–09:13Z)
```
- 终稿:[rd_design_input_spec-final.md](./assets/2026-09-17-rdev-template-depth/rd_design_input_spec-final.md)
- leader AGENTS:[rdev-leader-AGENTS.md](./assets/2026-09-17-rdev-template-depth/rdev-leader-AGENTS.md) 开篇为「研发/设计控制小队的负责人…不做报价核算与商务承诺」
- 账本 stage:[rd_design_input_spec-docgov.json](./assets/2026-09-17-rdev-template-depth/rd_design_input_spec-docgov.json) → `"stage":"RD03_design_input"`
- **判定**: PASS(五节均有结论句 + 事实表 + 缺口标注;无通用占位;无商务/CDO 串味)
- **耗时**: ~450 s(小队墙钟);squad 产出约 5 min(organize→review)
- **备注**: 终稿章节标题为「## 一、功能要求」等形式(带中文序号),语义覆盖模板五节。
## 六、 自动化测试套件汇总 (Test Suite Execution)
```text
$ go vet ./...
(无输出,exit 0)
$ env -u DATA_DIR go test -short ./internal/squad/ ./internal/template/ ./internal/workflowdef/
ok chat-agent-system/internal/squad 0.030s
ok chat-agent-system/internal/template 0.810s
ok chat-agent-system/internal/workflowdef 0.004s
$ env -u DATA_DIR go test -short ./...
# 全包 PASS(exit 0;约 59s)。说明:宿主若 export 了 DATA_DIR=./data/dev,
# 会覆盖 bizdev-cli 测试 -env 内的临时目录,导致相对路径读不到 squad.json;门禁以 unset DATA_DIR 为准。
# 另:本分支自带的 engineeringdashboard 包已补入 module-boundaries.yaml allowlist(随 rebase 丢弃 eng-dashboard 重复提交后可再收敛)。
```
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- **结论**: S0 + S1 首批达到合并候选标准(代码+真 PI 取样+门禁)。leader 错配已修;14/60 模板已补强。
- **后续**(见 [backlog](../backlog/2026-09-17-rdev-phase2-backlog.md)):
- S1 续批:阶段 06–13 剩余模板 + 中等档补指令
- S2:per-stage 步骤 / regulatory×complexity_tier / 模型去硬编码 / manifest hint
- S3:轻量 overlay + R2/R3 门禁 + P3 三样本 E2E
- **合 dev 提示**: 依赖 `feature/rdev-core`;合入前对 rdev-core `rebase dev`,丢弃已进 dev 的 engineering-dashboard 重复提交。
@@ -0,0 +1,87 @@
# 系统管理台(System Admin Console)一期 测试报告
## 一、 测试背景 (Background)
系统级管理能力此前散落在 `AdminSettingsModal`(用户/审批/策略/角色/工作流/状态六 tab 模态框),且系统状态、KB、特性开关无统一查看入口;feature flag 全部 env 驱动、无 DB 持久化设置。本任务落地独立的系统管理界面:后端新包 `internal/sysadmin`(薄聚合层)+ `/api/v1/admin/system/*` + `system_settings` 表(goose 00049);前端全屏 `AdminConsoleView`(八分组),吸收并下线旧模态。
- 分支:`feature/system-admin-console`;merge commit:`dc7c31e`(dev)
- 代码 commit:`f1404d5`(后端)、`0eaca61`(前端)
## 二、 测试目标 (Test Objectives)
1. admin 可从 LeftRail 入口进入全屏管理台,八分组可用;
2. `/api/v1/admin/system/{overview,kb,features,settings}` 契约正确、脱敏、仅 admin 可访问;
3. 白名单设置 PUT 写后读生效,未知 key 400,匿名 401;
4. goose 00049 在 dev 容器自动迁移(schema_version 48→49);
5. `go vet` / `go test -short` / archtest / `web npm test` / `npm run build` 全绿。
## 三、 测试方案与环境 (Test Plan & Environment)
- 环境:Linux,dev 容器栈(`env-service.sh dev rebuild` 后),app `agent-backend=pi-agent`(真实 PI Runner 容器在线),PG `:5433`,共享 KB `:5432`
- 层级:
- Go 单元/集成:`internal/sysadmin`(读优先级、写校验、聚合、脱敏)+ `internal/server`(真实 mux + 内存 IAM 的 401/403/200/400/503)
- 前端:`npm test`(node:test 378 + vitest 32)+ `npm run build`
- 容器冒烟:health、四个 GET 端点、PUT 写读回环、负例(匿名 401、未知 key 400)
- 架构约束:`go test ./internal/archtest/...`(module-boundaries.yaml 已登记 sysadmin)
## 四、 预期结果 (Expected Results)
- health `schema_version=49`;overview 字段 camelCase 且与 health 信号一致;kb 响应不含任何密码字段;features 覆盖主要功能开关;settings 6 项白名单;PUT 后 GET 持久化;匿名 401;非 admin 403(单测覆盖);未知 key 400。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:dev 容器冒烟(rebuild 后真实环境)
- **Input**:`./scripts/env-service.sh dev rebuild` → `curl /health`
- **Actual Output**:
```json
{"status":"ok","env":"dev","agent_backend":"pi-agent","kb_ready":true,"database_ready":true,"schema_version":49,"schema_ready":true,"task_store_ready":true}
```
- **Verdict**:PASS(goose 00049 实跑,48→49)
### 用例 2:admin 四端点契约
- **Input**:admin 登录(compose 默认种子账号)→ Bearer 调四端点
- **Actual Output**:
```
overview: {"status":"ok","env":"dev","agentBackend":"pi-agent","databaseReady":true,"schemaVersion":49,"taskStoreReady":true,"kbOnline":true,"uptimeSeconds":170}
kb: {"online":true,"host":"shuimu-kb-shared","port":5432,"database":"regulations","user":"regkb","embeddingModel":"bge-m3","rerankerEnabled":true,"sslMode":"disable"}
features: 22 项;groups=[agent, artifact-vault, auth, ctxmgr, docrevision, intent, intentflow, system]
settings: 6 项 [ui.maintenance_notice, ui.read_only_mode, chat.default_session_role, tasks.default_auto_repair, kb.default_search_limit, notifications.stage_advance_reminder]
```
- **Verdict**:PASS(kb 无密码字段,单测另断言响应体不含 "assword")
### 用例 3:设置写读回环 + 负例
- **Input**:`PUT settings/ui.maintenance_notice {"value":"slot-smoke-2026-09-17"}` → GET → `PUT no.such.key` → 匿名 GET overview → 复位为空
- **Actual Output**:
```
PUT 200 → value= slot-smoke-2026-09-17 updatedBy= 9
GET 持久化 → persisted value= slot-smoke-2026-09-17
PUT no.such.key → 400
匿名 overview → 401
复位 → reset-ok
```
- **Verdict**:PASS
### 用例 4:非 admin 403
- **Actual**:`internal/server/admin_system_handlers_test.go` 真实 mux + 内存 IAM:普通注册用户访问全部 5 端点 → 403;未认证 → 401。PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
- `go vet ./...`:通过
- `go test -short ./...`:全部 ok(含 `internal/sysadmin` 12 用例、`internal/server` 新增 6 用例;PG 用例 TEST_DATABASE_URL 守卫 skip)
- `go test ./internal/archtest/...`:ok
- `cd web && npm test`:node:test 378/378 + vitest 32/32 通过
- `cd web && npm run build`:✓ built in 7.58s(仅既有 chunk 体积警告)
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
一期达到合并/验收标准:管理台骨架与八个分组、system_settings 写读机制、权限门禁、迁移实跑均验证通过。
后续(二期候选):
1. Playwright 冒烟 `web/e2e/admin-console.spec.ts` 需真实 dev 栈 + `RUN_UI_ACCEPTANCE=1` + ADMIN 凭据执行(本次未跑,默认 skip);
2. 细粒度 `system:view`/`system:manage` 权限与设置变更审计日志;
3. KB 运维动作(连接测试/重建索引);白名单设置项接入真实消费方;
4. 403 自动退回工作台(当前为提示 + 手动返回,便于验收截图)。
@@ -0,0 +1,135 @@
# Wave 0 P0 Bug 修复测试报告
## 一、 测试背景 (Background)
系统体检(2026-09-17)确认 SSE 聊天/任务流被全局 `WriteTimeout=120s` 强杀、`run/stream` 畸形 body 误启任务与 Flush 后失败、前端会话窗口缓存 key 不一致、IndexedDB 恢复覆盖新增交付物。本波次按整改方案 Wave 0 实施 B-1~B-6。
## 二、 测试目标 (Test Objectives)
- B-1/B-2:`handleChatStream` / `handleRunTaskStream` 心跳 + `extendSSEWriteDeadline`,长静默不因 WriteTimeout 断流
- B-3:畸形 JSON → HTTP 400,不开 SSE
- B-4:`CreateAndStart`/`Subscribe` 在 Flush 前;失败为普通 JSON 错误
- B-5:`saveSessionWindowCache` 一律带 `userId`;LRU 驱逐完整 cache key
- B-6:`applyRestoredFileRaw` 函数式合并,不丢 mount 后新增 deliverable
- 质量门禁:`go vet` / `go test -short` / `npm test` / `npm run build` 全绿;dev rebuild + health/ready
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;Go 模块全量 `-short`;前端 `tsx --test` + vitest
- 后端 Stub 单测 + 真实 dev 容器(`pi-agent` + MiniMax-M2.7-highspeed)
- 分支:`fix/wave0-p0-sse-chat-cache-bugs` → 合入本地 `dev@810fb96`(后随 docs 再合)
- 资产:`.doc/test-reports/assets/2026-09-18-wave0-p0-bug-fixes/`
## 四、 预期结果 (Expected Results)
| 用例 | 预期 |
|------|------|
| 畸形 run/stream body | 400,非 `text/event-stream` |
| CreateAndStart 注入失败 | 非 SSE Content-Type,正文含 start failure |
| 短 WriteTimeout + 心跳 | 流时长 > WriteTimeout 仍可读到 done |
| 缓存写路径 | 全部调用含 `userId`;超 LRU 驱逐带前缀 key |
| restore 合并 | prev 新增条目保留,仅补丁 fileRaw |
| 真实 PI 聊天 | 静默生成期出现 `: heartbeat`,最终 `event: done` |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 后端单测(`internal/server/sse_wave0_test.go`)
**测试输入**:`go test -short -count=1 ./internal/server/ -run 'TestRunTaskStream_InvalidJSON|TestRunTaskStream_CreateAndStartFails|TestSSEHeartbeat_Helpers|TestRunTaskStream_ValidBody' -v`
**实际输出(摘要)**:
```
--- PASS: TestRunTaskStream_InvalidJSON_Returns400 (0.14s)
--- PASS: TestRunTaskStream_CreateAndStartFails_BeforeSSEFlush (0.12s)
--- PASS: TestSSEHeartbeat_HelpersSurviveShortWriteTimeout (0.70s)
--- PASS: TestRunTaskStream_ValidBody_OpensSSEWithHeartbeatPath (0.17s)
PASS
```
**评价判定**:PASS
**性能与耗时**:约 1.1s 包级
### 5.2 前端单测
**测试输入**:
```
npx tsx --test src/hooks/useChatWindow.cacheKey.test.ts \
src/data/storage.windowCache.test.ts src/data/fileStore.test.ts
```
**实际输出**:
```
✔ applyRestoredFileRaw: 以 prev 为权威…
✔ applyRestoredFileRaw: 无可用 fileRaw 时返回同一引用
✔ window cache LRU: 驱逐带 userId 前缀的完整 cache key…
✔ window cache: 读写同一 userId 前缀,跨用户不串读
✔ useChatWindow: 所有 saveSessionWindowCache 调用必须传入 userId
ℹ tests 5 / pass 5
```
**评价判定**:PASS
### 5.3 全量回归
| 命令 | 结果 |
|------|------|
| `go vet ./...` | PASS |
| `go test -short -count=1 ./...` | 全包 ok(含 server) |
| `cd web && npm test` | 397 + 32 vitest PASS |
| `cd web && npm run build` | PASS(含 precompress) |
### 5.4 dev 容器冒烟
**测试输入**:`./scripts/env-service.sh dev rebuild`;`curl -sf http://127.0.0.1:8080/health` 与 `/ready`
**实际输出**:
```json
{"status":"ok","env":"dev","agent_backend":"pi-agent","schema_version":52,"schema_ready":true,...}
```
**评价判定**:PASS
### 5.5 真实 PI 聊天 SSE(心跳接线证据)
**测试输入**:admin 登录后 `POST /api/v1/chat/stream`,长合规分析提示词;资产见 `assets/2026-09-18-wave0-p0-bug-fixes/chat-stream-long.sse.txt`
**实际输出(关键片段)**:
```
event: phase
...
: heartbeat 1789663534
: heartbeat 1789663549
: heartbeat 1789663564
: heartbeat 1789663579
event: delta
...
event: done
data: {...,"done":{"duration_ms":70164,"status":"completed",...}}
```
**评价判定**:PASS(真 PI 回合约 70s;静默生成期 4 次心跳,流完整收尾)。
**说明**:绝对墙钟 >120s 的真 PI 未再压测(二次加长提示触发 `SECURITY_FORBIDDEN` 快速返回);WriteTimeout 跨越由 `TestSSEHeartbeat_HelpersSurviveShortWriteTimeout`(WriteTimeout=200ms,流 700ms)覆盖,与线上心跳机制同源。
## 六、 自动化测试套件汇总 (Test Suite Execution)
- Go:`go vet ./...` + `go test -short -count=1 ./...` → 全绿
- Web:`npm test`(397 node:test + 32 vitest)+ `npm run build` → 全绿
- 新增:`sse_wave0_test.go`、`useChatWindow.cacheKey.test.ts`、`storage.windowCache.test.ts`、`fileStore.test.ts`
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- Wave 0(B-1~B-6)达到合入与冒烟标准,可关闭 short-term 任务。
- 后续:Wave 1(E-1 main ENV)仍待决策;可选补一次刻意 >120s 的受控长任务(例如阻塞 executor 的 task run events)作为额外证据。
- 红线未触碰:FAV / MULTI_INTENT_PLAN_TIER / SEMANTIC_SUMMARY_REPLACE / 项目 143。
## 相关链接
- Audit: [../audit/2026-09-17-system-health-check.md](../audit/2026-09-17-system-health-check.md)
- Remediation: [../remediation/2026-09-17-system-health-remediation-plan.md](../remediation/2026-09-17-system-health-remediation-plan.md)
- Short-term: [../ops/short-term/2026-09-18-wave0-p0-bug-fixes.md](../ops/short-term/2026-09-18-wave0-p0-bug-fixes.md)
- Assets: [./assets/2026-09-18-wave0-p0-bug-fixes/](./assets/2026-09-18-wave0-p0-bug-fixes/)
@@ -0,0 +1,100 @@
# Wave 1:main 环境 ENV/schema 修正测试报告
## 一、 测试背景 (Background)
体检确认 main 环境 app `ENV=prod` 与 events `ENV=main` 不一致(E-1 critical),schema 落后且晋升缺强制顺序(E-2),以及 `Env==""` 视同 dev 放开导入端点(E-5)。
## 二、 测试目标 (Test Objectives)
- app/events health 均报 `env=main`
- events 先 healthy 后启 app;goose 迁移后 `schema_ready=true`(实测 schema_version=52)
- `event_consumer_modes` 中 main 四行仍为 `off`
- 空 Env 导入端点 403;compose app/events ENV 一致单测 PASS
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支:`fix/wave1-main-env-fix` → 合入本地 `dev`
- 真实 main:`./scripts/env-service.sh main rebuild`(注意:执行前须清掉 shell 内残留的 `source .env.dev` 覆盖变量,否则端口会串到 8080/18865)
- 单测:`internal/config/compose_env_consistency_test.go`、`TestServer_ChatWindow_ImportGuard_EmptyEnvFailsClosed`
## 四、 预期结果 (Expected Results)
| 项 | 预期 |
|----|------|
| events `/health` | `env=main` |
| app `/health` `/ready` | `env=main`,`schema_ready=true` |
| consumer modes | main 四行 `off` |
| settings / projects | HTTP 200,无 SQL 缺列错误 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 单测
```
--- PASS: TestComposeAppEventsENVAligned
--- PASS: TestComposeMainAppDependsOnEventsHealthy
--- PASS: TestServer_ChatWindow_ImportGuard
--- PASS: TestServer_ChatWindow_ImportGuard_EmptyEnvFailsClosed
```
**判定**:PASS
### 5.2 main rebuild 启动顺序
日志摘要(`/tmp/wave1-main-rebuild3.txt`):
```
Container shuimu-agent-events-main Started
Container shuimu-agent-events-main Waiting
Container shuimu-agent-events-main Healthy
Container shuimu-agent-app-main Starting
Container shuimu-agent-app-main Started
```
**判定**:PASS(E-2 depends_on 生效)
### 5.3 health / schema / modes
**events**:`{"env":"main","owner":"events-1","status":"ok"}`
**app**:`{"status":"ok","env":"main",...,"schema_version":52,"schema_ready":true}`
**modes**:main 的 fav/notify/projection/workflow_advance 均为 `off` revision=1
**goose**:`version_id=52`
资产:`.doc/test-reports/assets/2026-09-18-wave1-main-env-fix/`
**判定**:PASS(E-1 对齐;schema 由 47 升至 52;红线未改 mode)
### 5.4 冒烟
| 调用 | 结果 |
|------|------|
| POST `/api/v1/auth/login` | login_ok |
| GET `/api/v1/admin/system/settings` | 200(system_settings 可读) |
| GET `/api/v1/projects` | 200 `[]` |
| GET `/api/v1/admin/system/overview` | 200,`env=main`,`schemaVersion=52` |
**判定**:PASS
### 5.5 附带修复说明
main `events` 在 `ENV=main` 下原先因 `validateProductionSecrets` 缺 KB/admin 口令而持续 Restarting(Wave 1 前已存在)。为使 `depends_on events healthy` 可落地,向 events 注入 `POSTGRES_SHARED_KB_DSN` / `ADMIN_PASSWORD` / `ALLOW_IN_MEMORY=false` 并挂入 `shared-net`。
## 六、 自动化测试套件汇总 (Test Suite Execution)
- `go vet ./...` PASS
- `go test -short ./internal/config/`、`./internal/server/` Wave 1 相关用例 PASS
- 全量 `go test -short ./...`:`cmd/bizdev-cli` 因本机 `mkdir data/dev/data: permission denied` 失败(环境权限,与本波次无关);其余包 ok
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
Wave 1(E-1/E-2/E-5)达到关闭标准。建议后续:
1. Wave 2 配置声明对齐
2. `env-service.sh` 在调用 compose 前 unset 易串扰的端口类变量,避免 shell 污染
3. 评估是否把 events 的生产密钥注入同步到文档 checklist
## 相关链接
- Short-term: [../ops/short-term/2026-09-18-wave1-main-env-fix.md](../ops/short-term/2026-09-18-wave1-main-env-fix.md)
- Remediation: [../remediation/2026-09-17-system-health-remediation-plan.md](../remediation/2026-09-17-system-health-remediation-plan.md)
- Assets: [./assets/2026-09-18-wave1-main-env-fix/](./assets/2026-09-18-wave1-main-env-fix/)
@@ -0,0 +1,104 @@
# Wave 2:配置与灰度入口对齐测试报告
## 一、 测试背景 (Background)
体检确认封存 flag(`MULTI_INTENT_PLAN_TIER`、U9–U12、SHADOW/NARRATIVE)未写入 compose `environment`,`--env-file` 无法传入容器(E-3);`CURSOR_RUNNER_URL`/cursor-agent 零消费占位(E-4);main 未显式关闭 demo 播种(E-6);`INTENT_V2_DECISION_TIER` 非法值激进回退 `query`(E-7);main initdb 与 test 脚本形态差异需评估(E-9)。
## 二、 测试目标 (Test Objectives)
- 三环境 compose 渲染与容器 env 均可见目标 flag,默认 `legacy`/`false`
- `CURSOR_RUNNER*` 与 `cursor-agent` 容器消失
- main `SEED_DEMO_USERS=false`
- 非法 `INTENT_V2_DECISION_TIER` fail-closed 到 `none`
- E-9:记录评估结论,不改 initdb
- `go vet` / `go test -short` 全绿;dev/test/main health+ready PASS
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支:`fix/wave2-config-flag-align`(自本地 `dev@e35f106`)
- 单测:`internal/config/compose_flag_declaration_test.go`、`TestUnknownV2DecisionTierFailsClosedToNone`
- 真实环境:`./scripts/env-service.sh {dev,test,main} rebuild`(执行前 unset shell 泄漏端口变量)
- 证据目录:`.doc/test-reports/assets/2026-09-18-wave2-config-flag-align/`
## 四、 预期结果 (Expected Results)
| 项 | 预期 |
|----|------|
| compose config | 三环境 `MULTI_INTENT_PLAN_TIER=legacy` + U9–U12/SHADOW/NARRATIVE=false;无 CURSOR_RUNNER |
| 容器 env | 同上;main 另有 `SEED_DEMO_USERS=false` |
| cursor-agent | `docker ps` 无匹配 |
| health/ready | 三环境 ok,schema_ready=true |
| 行为 | 不升 tier、不接线 REPLACE、不改 FAV |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 单测
```
ok chat-agent-system/internal/intent
ok chat-agent-system/internal/config
--- PASS: TestComposeAppDeclaresMultiIntentPlanTierAndExpansionFlags
--- PASS: TestComposeAppDeclaresSemanticSummaryAndNarrativeShadowFlags
--- PASS: TestComposeMainSeedDemoUsersExplicitFalse
--- PASS: TestComposeNoDeadCursorRunnerConfig
--- PASS: TestUnknownV2DecisionTierFailsClosedToNone
```
**判定**:PASS
### 5.2 compose config 渲染
见 `assets/.../compose-config-flags.txt`。三环境均含目标 flag;`CURSOR_RUNNER` 零匹配。
**判定**:PASS
### 5.3 容器 env 抽检
| 环境 | 关键输出 | 判定 |
|------|----------|------|
| dev | `MULTI_INTENT_PLAN_TIER=legacy` … `SEMANTIC_SUMMARY_SHADOW=false`(无 CURSOR_RUNNER) | PASS |
| test | 同上 + `SEED_DEMO_USERS=false` | PASS |
| main | 同上 + `SEED_DEMO_USERS=false` | PASS |
### 5.4 冒烟 health/ready
| 环境 | health | ready | 判定 |
|------|--------|-------|------|
| dev `:8080` | env=dev schema=52 | ok | PASS |
| test `:8081` | env=test schema=52 | ok | PASS |
| main `:8000` | env=main schema=52 | ok | PASS |
main rebuild 日志确认 `events` Healthy 后才 Starting `app`(E-2 依赖仍生效)。
### 5.5 cursor-agent 清理
```
cursor-agent 容器已清理,符合预期
```
**判定**:PASS
### 5.6 E-9 评估结论(本波次不改代码)
| 环境 | initdb 挂载 | 结论 |
|------|-------------|------|
| dev | `deploy/postgres/context_init.sql` | 与 main baseline 内容一致(仅差 goose 头注释) |
| test | `deploy/postgres/extensions_init.sql` | 仅扩展,表全靠 goose |
| main | `deploy/postgres/goose/00001_baseline.sql` | 与 dev 实质一致;无「落后」 |
**决策**:不收敛 initdb(零行为变化波次);双文件漂移风险记入后续 backlog,需空卷冷启动专项验证后再改。
**判定**:评估完成 / 不改代码 — PASS(按计划)
## 六、 自动化测试套件汇总 (Test Suite Execution)
```
go vet ./... # 通过
go test -short -count=1 ./... # 全绿(见 assets/go-test-short.txt)
```
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- Wave 2 达到合并标准:声明对齐完成,默认行为不变。
- 下一波 Wave 3:测试债与盲区(S-1/S-2/S-4/S-5)。
- E-9 结构性收敛(dev/main → extensions-only)另开任务。
@@ -0,0 +1,82 @@
# Wave 3:测试债与盲区测试报告
## 一、 测试背景 (Background)
体检确认 `TestReconcile_LegacyRepair_PG` 从未在隔离 PG 上执行(S-1);两处永久跳过(S-2);E2E 9 个 spec 仅 1 个有 npm 脚本且存在 `DOCREV_E2E_BASE_URL` 双口径(S-4);前端多处 API 对 409/结构化错误裸抛 Error(S-5)。
## 二、 测试目标 (Test Objectives)
- 隔离 PG(5436) 跑通 LegacyRepair 一次并归档
- 删除死跳过;plan_owner 重定向说明补齐
- `playwright test --list` = 29 tests / 8 files;每 spec 有脚本
- projectMembers/freeformDoc/taskRuns/chatSessions 复用 `projectSettingsError` 并有负例单测
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支:`fix/wave3-test-debt-blindspots` ← 本地 `dev@423f7e7`
- 隔离 PG:`pgvector/pgvector:pg16` 映射 5436,测完销毁并 `unset TEST_DATABASE_URL`
- 前端:`npm test` / `npm run build` / `npx playwright test --list`
- 证据:`.doc/test-reports/assets/2026-09-18-wave3-test-debt-blindspots/`
## 四、 预期结果 (Expected Results)
| 项 | 预期 |
|----|------|
| S-1 | goose→52 + `PASS: TestReconcile_LegacyRepair_PG` |
| S-2 | TaskStream 3 PASS 0 SKIP;plan_owner 仍 SKIP 但注释说明导入环 |
| S-4 | 29 tests / 8 files;无 `DOCREV_E2E_BASE_URL` |
| S-5 | 相关 API 单测 PASS;`npm test` 全绿 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 S-1 隔离 PG
见 `assets/.../go-test-reconcile-pg.txt`:
```
goose: successfully migrated database to version: 52
--- PASS: TestReconcile_LegacyRepair_PG (0.37s)
```
**判定**:PASS
### 5.2 S-2
```
--- SKIP: TestTaskGenerateRealPIStopGate(redirect 说明已补)
--- PASS: TestTaskStream_TransientInjection_DeadPiAgent
--- PASS: TestTaskStream_SoftFailure_ClassifiedResumable
--- PASS: TestTaskStream_MaterialsInjection
```
**判定**:PASS
### 5.3 S-4
```
Total: 29 tests in 8 files
```
**判定**:PASS(退役 `document-revision.spec.ts`)
### 5.4 S-5
`npm test`:402 pass + vitest 32 pass;含 DOC_BUSY / CONCURRENCY_CONFLICT / members / chatSessions 负例。
**判定**:PASS
### 5.5 全量回归
`go vet ./...` + `go test -short ./...` 全绿(见 `go-test-short.txt`)。
## 六、 自动化测试套件汇总 (Test Suite Execution)
- Go short:全绿
- Web:`npm test` 全绿;`npm run build` 成功
- Playwright list:29/8
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- Wave 3 达到合并标准;gap-matrix DOC-CONTENT 工程测试债关闭。
- 下一波 Wave 4:隐患加固 R-1~R-8。
- 后端 `error_code`→统一 `httpx.Write` 仍属独立 remediation,不在本波。
@@ -0,0 +1,118 @@
# Wave 4:隐患加固(R-1~R-8)测试报告
## 一、 测试背景 (Background)
系统体检(2026-09-17)确认高风险隐患 R-1~R-8:会话跨用户挂靠、`rows.Err()` 漏检、dispatcher 无锁读、`memTurns` 全局只增不删、JSONB 静默零值化、后台 ticker 无 Shutdown、SSE 401/404 盲目重连与登出未 abort 在途流。Wave 0–3 已合入后按 Sonnet 计划默认决策实施本波。
## 二、 测试目标 (Test Objectives)
- R-1:跨用户 chat / chat/stream / chat/sessions 全部 403;受害者续用 200;Memory + PG 双实现
- R-2:18 文件补齐 `rows.Err()`;B 类 slog.Warn
- R-3:`-race` 下 events 无竞态
- R-4:实例隔离 + TTL/容量淘汰测试 PASS
- R-5:损坏/类型错误 JSONB 显式报错
- R-6:Shutdown 可停止 reminder/vault;Drain 可告警;bizdev 心跳超时
- R-7/R-8:401/404 fail-fast(calls===1);单帧容错;abortAllSessions
- 全量:`go vet` / `go build` / `go test -short` / `npm test` / `npm run build`
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支:`fix/wave4-hardening-r1-r8` ← 本地 tip `32932e4`
- 隔离 PG:`pgvector/pgvector:pg16` → `127.0.0.1:5436`,测完 `unset TEST_DATABASE_URL` + `docker stop wave4-pg`
- OS:Linux;Go 模块本仓;前端 Vite/Node test runner
- 证据:`.doc/test-reports/assets/2026-09-18-wave4-hardening-r1-r8/`
## 四、 预期结果 (Expected Results)
| 项 | 预期 |
|----|------|
| R-1 Memory/PG | attacker 403 SESSION_FORBIDDEN;stream 非 SSE;victim 续用 OK |
| R-2 | `go vet` 绿;18 文件循环后可见 `rows.Err()` |
| R-3 | `go test -race -short ./internal/events/...` 绿 |
| R-4 | ChatTurn 四测 PASS;无全局 `memTurns` 重置 |
| R-5 | hydrate 错误含 `hydrateDocLocked` + `block_map` |
| R-7 | 401/404 各仅 1 次 fetch;畸形帧跳过后仍解析下一帧 |
| 全量 | short/npm/build EXIT:0 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 R-1 跨用户会话挂靠
**输入**:受害者建立 `sess-hijack-*` 后攻击者同 session_id 调 chat / stream / upsert。
**实际输出**(`ownership-pg.txt`):
```
--- PASS: TestChatSessionOwnership_CrossUserHijackDenied_PG
--- PASS: TestChatSessionOwnership_CrossUserHijackDenied_Memory
```
**判定**:PASS(附带清除 NewSession `ProjectID=1` 占位,避免 PG 误走项目鉴权)
### 5.2 R-2 rows.Err()
**实际输出**:`go-vet.txt` EXIT:0;静态补齐 18 文件。
**判定**:PASS
### 5.3 R-3 / R-4 race
**实际输出**(`go-race.txt`):
```
ok chat-agent-system/internal/events
ok chat-agent-system/internal/ctxmgr
EXIT:0
```
含 `TestAcquireChatTurn_StaleEntriesPruned` PASS。
**判定**:PASS
### 5.4 R-5 hydrate JSONB
**实际输出**(`hydrate-corrupt-pg.txt`):
```
--- PASS: TestHydrateDocLocked_CorruptJSONBFailsExplicitly_PG
```
**判定**:PASS
### 5.5 R-6
代码级:`Shutdown` close `reminderStop`/`vaultStop`;vault Drain → `vault_drain_failed`;bizdev 心跳/释放 10s timeout。随 `go test -short ./internal/server/... ./internal/bizdev/...` 回归。
**判定**:PASS
### 5.6 R-7 / R-8 前端
**实际输出**(`npm-test.txt`):tests 406 pass;vitest 32 pass;含 401/404 fail-fast 与畸形帧容错、abortAllSessions。
**判定**:PASS
### 5.7 全量回归
- `go-vet.txt` / `go-build.txt` / `go-test-short.txt`:EXIT:0
- `npm-build.txt`:EXIT:0
**判定**:PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
| 命令 | 结果 |
|------|------|
| `go vet ./...` | PASS |
| `go build ./...` | PASS |
| `go test -short -count=1 ./...` | PASS |
| `go test -race -short ./internal/events/... ./internal/ctxmgr/...` | PASS |
| `cd web && npm test` | PASS(406 + 32) |
| `cd web && npm run build` | PASS |
| 隔离 PG R-1/R-5 | PASS 后销毁容器 |
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- Wave 4 R-1~R-8 达到合入本地 `dev` 标准。
- 未改 D-4/D-5(`handleGetProject` 鉴权、`handleRunTaskStream` 归属);记入后续 backlog。
- 红线自查:未触碰 FAV modes / MULTI_INTENT_PLAN_TIER / SEMANTIC_SUMMARY_REPLACE / 项目 143。
- 下一波:Wave 5 死代码决策(X-1~X-5)。
@@ -0,0 +1,85 @@
# Wave 5 死代码决策(X-1~X-5)测试报告
## 一、 测试背景 (Background)
系统体检整改 Wave 0–4 已合入本地 `dev@a12c947`。Wave 5 对死 flag、封存 REPLACE、00048 三表、system_settings 未接线键、前端死组件做逐项决策并收口。决策落点:[short-term](../ops/short-term/2026-09-18-wave5-deadcode-decisions.md)。
## 二、 测试目标 (Test Objectives)
- X-1:删除 `SEMANTIC_FALLBACK_ENABLED` 且回归测试防复活。
- X-2:`SEMANTIC_SUMMARY_REPLACE` 维持不接线,注释回链决策记录。
- X-3:00048 三表 deferred → SWBOOT-10/W5b(不改 schema)。
- X-4:6 个未接线 system_settings 键保留并注释二期。
- X-5:删除死组件/死 API 后前端构建与测试全绿。
- 门禁:`go vet ./...`、`go test -short ./...`、`cd web && npm test && npm run build`。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;Go `go1.27.1 linux/amd64`;Node `v26.8.2`;npm `11.19.1`。
- 层级:单元/包测试(`-short`)+ 前端 `tsx --test` / vitest + `tsc && vite build`。
- 未做容器 rebuild / 真 PI E2E(本波为死代码删除与注释,无运行时行为变更)。项目 143 只读,未触碰。
- 证据目录:`.doc/test-reports/assets/2026-09-18-wave5-deadcode-decisions/`。
## 四、 预期结果 (Expected Results)
| 项 | 判定 |
|----|------|
| X-1 | compose/代码无 `SEMANTIC_FALLBACK_ENABLED`(回归测试字符串除外);`TestComposeNoDeadSemanticFallbackConfig` PASS |
| X-2 | REPLACE 仍不替换 narrative;diff 仅注释 |
| X-3 | schema 不变;swboot 测试绿 |
| X-4 | 白名单键仍在;sysadmin 测试绿 |
| X-5 | `npm run build`(含 tsc)绿;死符号无引用 |
| 全量 | vet 无输出;`go test -short` 无 FAIL;npm test 0 fail |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 X-1 回归测试
- **测试输入**:`go test -short ./internal/config/...`(含于全量 `-short`)
- **实际输出**:`ok chat-agent-system/internal/config`(见 assets `go-test-short.txt`)
- **评价判定**:PASS。`SEMANTIC_FALLBACK_ENABLED` 仅剩回归测试断言字符串。
- **性能与耗时**:config 包约 0.x s(全量 short 合计约 16s)
### 5.2 X-2 / X-3 / X-4 包测试
- **测试输入**:`go test -short ./internal/ctxmgr/... ./internal/swboot/... ./internal/sysadmin/...`(含于全量)
- **实际输出**:
- `ok chat-agent-system/internal/ctxmgr`(cached/ok)
- `ok chat-agent-system/internal/swboot 0.002s`
- `ok chat-agent-system/internal/sysadmin 0.003s`
- **评价判定**:PASS
- **性能与耗时**:毫秒级
### 5.3 X-5 前端
- **测试输入**:`cd web && npm test && npm run build`
- **实际输出**:
- tsx:`tests 406 / pass 406 / fail 0`(`duration_ms 903.526321`)
- vitest:`Test Files 3 passed (3)` / `Tests 32 passed (32)` / `Duration 533ms`
- build:`tsc && vite build` → `✓ 4123 modules transformed`;`precompress: wrote 49 .br and 49 .gz`
- **评价判定**:PASS
- **性能与耗时**:npm test + build 合计约 18s
### 5.4 全量 Go
- **测试输入**:`go vet ./...`;`go test -short ./...`
- **实际输出**:vet 空文件(exit 0);short 测试 `ok` 计数 56,无 `FAIL`/`panic`
- **评价判定**:PASS
- **性能与耗时**:vet ~2s;short ~16s
## 六、 自动化测试套件汇总 (Test Suite Execution)
| 命令 | 结果 | 证据 |
|------|------|------|
| `go vet ./...` | PASS(exit 0,无输出) | [go-vet.txt](./assets/2026-09-18-wave5-deadcode-decisions/go-vet.txt) |
| `go test -short ./...` | PASS(56 ok,无 FAIL) | [go-test-short.txt](./assets/2026-09-18-wave5-deadcode-decisions/go-test-short.txt) |
| `cd web && npm test` | PASS(406+32,fail 0) | [npm-test.txt](./assets/2026-09-18-wave5-deadcode-decisions/npm-test.txt) |
| `cd web && npm run build` | PASS | [npm-build.txt](./assets/2026-09-18-wave5-deadcode-decisions/npm-build.txt) |
时间:2026-09-18T04:01:27Z。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
达到合入本地 `dev` 标准。红线未触碰:REPLACE 不接线、不升 `MULTI_INTENT_PLAN_TIER`、不改 FAV、项目 143 只读。
后续:Wave 6 文档漂移(D-1~D-6);SWBOOT-10/W5b 与 system_settings 二期接线仍 deferred,不在本波。
@@ -0,0 +1,93 @@
# Wave 6 文档漂移修复(D-1~D-6)测试报告
## 一、 测试背景 (Background)
系统体检审计 [`.doc/audit/2026-09-17-system-health-check.md`](../audit/2026-09-17-system-health-check.md) §1.5 记录文档漂移 D-1~D-6:PU8 契约状态未回标、modular-monolith ADR 仍为提议、INDEX 末行需复核、意图双标签 handoff 正文未回标、backlog D3/D7 滞后、`PROJECT.md` §9「剩余 blocker」与 gap-matrix `production_ready=yes` 矛盾。整改方案 Wave 6 要求逐项回链关闭。基线为本地 `dev@2ce2625`(Wave 5 已合入)。
## 二、 测试目标 (Test Objectives)
- D-1~D-6 逐项关闭,漂移清单可回链。
- `audit/INDEX.md`、`remediation/INDEX.md`、`FEATURE-MATRIX.md` 三方口径一致(D-3 预期零改动)。
- 零代码改动:`go build ./...`、`go vet ./...`、`cd web && npm run build` 全绿。
- 不升 tier、不接线 `SEMANTIC_SUMMARY_REPLACE`、不改 FAV、无新增发布 blocker。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;Go `go1.27.1 linux/amd64`;Node `v26.8.2`;npm `11.19.1`。
- 层级:文档 diff 复核 + 编译/vet/前端构建防误伤。未做容器 rebuild 与真 PI E2E(本波只改 `.doc/**` 与 `PROJECT.md`)。
- 证据目录:`.doc/test-reports/assets/2026-09-18-wave6-doc-drift/`。
- 时间:2026-09-18T04:11:26Z(INDEX 复核)至 2026-09-18T04:11:41Z(go)/ npm build 约 16s。
## 四、 预期结果 (Expected Results)
| 项 | 判定 |
|----|------|
| D-1 | 四份 PU8 契约 `status: done`、`updated: 2026-09-18`;两份 short-term 在 `.doc/archive/ops/` |
| D-2 | ADR「状态」为「已接受」并附 Phase 1/2 证据链接 |
| D-3 | 两个 INDEX 末行保持「U2 已验收,主 JS ~624 KB;U1/U3–U7 待实施」,零改动 |
| D-4 | handoff 末尾追加「回标」小节;历史正文保留;frontmatter 仍 `closed` |
| D-5 | backlog 仅 D3/D7 两行改写并回链 |
| D-6 | `PROJECT.md` §9 写 `production_ready=yes`、无剩余发布 blocker |
| 防误伤 | `go build` / `go vet` / `npm run build` exit 0 |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 D-1 契约回标与归档
- **测试输入**:frontmatter diff;`git mv` 两份已 done short-term。
- **实际输出**:四份契约 `status: done` / `updated: 2026-09-18`。`git` rename 100%:`.doc/archive/ops/2026-09-16-pu8-u9-u12-flags.md`、`.doc/archive/ops/2026-09-17-w4-multi-intent-u9-u12.md`。
- **评价判定**:PASS。正文与 flag 未改。
- **性能与耗时**:文档编辑,可忽略。
### 5.2 D-2 ADR
- **测试输入**:`.doc/adr/2026-09-14-modular-monolith-decoupling.md`「状态」小节。
- **实际输出**:`已接受(2026-09-14 提议;2026-09-18 确认——Phase 1 纵向绞杀与 Phase 2 持久事件交付已落地并验收,见 gap-matrix DOC-RELIABILITY-PILOT PASS…)`。
- **评价判定**:PASS。决策正文未改。
- **性能与耗时**:可忽略。
### 5.3 D-3 INDEX 复核
- **测试输入**:`tail -n 1` audit/INDEX 与 remediation/INDEX。
- **实际输出**(见 [index-last-lines.txt](./assets/2026-09-18-wave6-doc-drift/index-last-lines.txt)):
- audit:`- 2026-09-17:[首次加载性能诊断与改进](2026-09-17-initial-load-performance-audit.md)(三入口重启首访;U2 已验收,主 JS ~624 KB;U1/U3–U7 待实施)。`
- remediation:同表述,指向 `-plan.md`。
- **评价判定**:PASS,无改动。
- **性能与耗时**:可忽略。
### 5.4 D-4 handoff 回标
- **测试输入**:`.doc/ops/handoffs/2026-09-15-conversation-intent-dual-tab.md` 末尾追加。
- **实际输出**:新增「回标(2026-09-18,Wave 6 文档漂移修复)」;「未完成」与认领表原文保留。
- **评价判定**:PASS。
- **性能与耗时**:可忽略。
### 5.5 D-5 backlog
- **测试输入**:`.doc/backlog/chat-agent-p6-backlog.md` D3/D7 两行。
- **实际输出**:D3 标已实现(shadow)并链接 FEATURE-MATRIX / PU6 / W2 报告;D7 链接 ADR 与 W7 盘点,合规签字结论未改。B5/A5/A6/A7/D5 未动。
- **评价判定**:PASS。FEATURE-MATRIX「语义摘要(D3)」为 done、REPLACE 未启用;「对话数据治理(D7)」为 deferred / `pending-compliance-signoff`。交叉检查无矩阵改动。
- **性能与耗时**:可忽略。
### 5.6 D-6 PROJECT.md §9
- **测试输入**:`PROJECT.md` 第 9 节「剩余 blocker」行。
- **实际输出**:改为「发布门禁:`production_ready=yes`……**无剩余发布 blocker**」;历史 P0 报告链接保留为「历史里程碑」。
- **评价判定**:PASS。与 gap-matrix 不再矛盾。
- **性能与耗时**:可忽略。
## 六、 自动化测试套件汇总 (Test Suite Execution)
| 命令 | 结果 | 证据 |
|------|------|------|
| `go build ./...` | PASS(exit 0,无输出) | [go-build.txt](./assets/2026-09-18-wave6-doc-drift/go-build.txt) |
| `go vet ./...` | PASS(exit 0,无输出) | [go-vet.txt](./assets/2026-09-18-wave6-doc-drift/go-vet.txt) |
| `cd web && npm run build` | PASS(`✓ 4123 modules transformed`;`precompress: wrote 49 .br and 49 .gz`) | [npm-build.txt](./assets/2026-09-18-wave6-doc-drift/npm-build.txt) |
时间:2026-09-18T04:11:39Z 起;go build+vet 约 2s(缓存命中);npm build 约 16s。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
D-1~D-6 全部关闭,remediation Wave 6 行与验收勾选已回链,CURRENT 焦点/认领/`doc-drift` mutex 与槽位 idle 一致。达到合入本地 `dev` 标准。无新增 blocker。
后续:Wave 7(SWBOOT-10、FAV live 放量、D7 合规签字)仍 deferred,需独立授权,不在本波。
@@ -0,0 +1,67 @@
# Wave 7 既有 roadmap 编排确认 测试报告
## 一、 测试背景 (Background)
系统体检整改 Wave 7 定义为「既有 roadmap 收口(不改优先级,仅确认编排)」,不是把 deferred 能力做完。基线为本地 `dev@a88ed85`(`merge: docs/wave6-doc-drift`)。Wave 6 的 D-1~D-6 已 PASS,本波跳过步骤 0,不改 backlog。
## 二、 测试目标 (Test Objectives)
- 六条编排确认均含当前状态、关闭条件、是否需授权、下一触发点。
- 零代码:不改 Go/TS/SQL/compose。
- 红线未动:不实施 SWBOOT-10、不升 FAV、不删 D7 数据、不升 `MULTI_INTENT_PLAN_TIER`、不接线 `SEMANTIC_SUMMARY_REPLACE`、不改 FEATURE-MATRIX 状态列、不合并/删除 `feature/control-center-server`。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux。文档波次,无容器、无真 PI、无 stub 验收数据。
- 核验:`git diff --name-only a88ed85..HEAD` 仅 `.doc/**`;人工核对六条确认字段与 remediation/CURRENT 回链。
- 时间:2026-09-18。
## 四、 预期结果 (Expected Results)
| 项 | 判定 |
|----|------|
| 六条确认 | T1/W5、T1/W6、T1/W7、T2、T4、T5/T6/T8 均落盘,且无一项标成已实现 |
| T2 | 只记录双实现事实与建议;分支仍在 |
| 防误伤 | diff 不含 `.go` / `.ts` / `.tsx` / `.sql` / compose |
| SSOT | remediation Wave 7 = done;CURRENT 焦点 Wave 0–7 done;槽位 idle |
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 六条确认落盘
- **测试输入**:short-term `.doc/ops/short-term/2026-09-18-wave7-roadmap-orchestration.md`。
- **实际输出**:六节均含「当前状态 / 关闭条件 / 是否需用户授权 / 建议下一触发点」。T1/W5、T1/W6、T1/W7 标需要授权;T2 标需要用户裁决取舍;T4/T5/T8 不需专项授权但未开工。
- **评价判定**:PASS。
- **性能与耗时**:文档编辑,可忽略。
### 5.2 零代码与红线
- **测试输入**:`git diff --name-only a88ed85..HEAD`(确认提交之后、本报告提交之前)。
- **实际输出**:
```text
.doc/ops/CURRENT.md
.doc/ops/short-term/2026-09-18-wave7-roadmap-orchestration.md
.doc/remediation/2026-09-17-system-health-remediation-plan.md
```
按扩展名过滤 `.go|.ts|.tsx|.sql|.yml|.yaml` 结果为空(`no code files`)。backlog、FEATURE-MATRIX、compose 未出现在 diff 中。
- **评价判定**:PASS。未跑 `go test` / 容器冒烟:本波无代码,容器验证不适用。
- **性能与耗时**:`git diff` < 1s。
### 5.3 Control Center 分支未动
- **测试输入**:`git rev-list --count` 相对 `dev@a88ed85`;`git branch` 仍含 `feature/control-center-server`。
- **实际输出**:merge-base `adb48c8`;落后 136 commits;自身 11 commits;分支未删除、未合并。
- **评价判定**:PASS。仅记录事实与建议。
- **性能与耗时**:可忽略。
## 六、 自动化测试套件汇总 (Test Suite Execution)
未执行 `go test -v ./...`。理由:相对 `a88ed85` 的变更仅三份 Markdown(另加本报告),无编译单元。防误伤证据为上一节 `git diff --name-only` 与扩展名过滤为空。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
达到本波「编排确认」合并标准:文档已落盘,能力状态未伪装完成,红线未动。后续触发点仍是用户授权(SWBOOT-10 / FAV live / D7 签字)或收益认领(T4 U1、T5、T6、T8),不在本波实施。未 push。
2026-09-19 补充:Control Center 取舍已关闭,模块已移出本仓库。本报告 §5.3 只记录当时未合并的事实。
@@ -0,0 +1,77 @@
# 审计整改批 1(后端数据一致性)测试报告
## 一、 测试背景 (Background)
2026-09-19 系统深度审计([.doc/audit/2026-09-19-system-deep-audit.md](../audit/2026-09-19-system-deep-audit.md))发现 4 项后端数据一致性 critical/high:
- C1 docgov 租约/审计持久化 `_, _ = pool.Exec` 静默吞错 + `lease_fencing_token` 列未读回
- C2 Session 全字段数据竞态 + ProjectID 跨项目污染
- C4 工作流 SaveWorkflowPlan upsert/bump 分裂事务竞态 + completed_by 错填为 activated_by
- H10 `context.Background()` 脱离请求生命周期
## 二、 测试目标 (Test Objectives)
- 修复后 `go vet` 零告警、`go test -short ./...` 全量 PASS
- 受影响三包 `go test -race -short` PASS(chat / docgov / projectinstance)
- 不改变既有 API 行为契约(除 completed_by 归属修正)
## 三、 测试方案与环境 (Test Plan & Environment)
- 环境:linux 7.0,Go 1.x,分支 `fix/audit-b1-data-consistency` → 合入 `dev`(worktree `.worktrees/dev-rdev-merge`,merge commit `844f757`)
- 层级:单元测试(受影响包)+ 全量回归 + race 检测
- dev 服务在线 `:8080`(合入前旧二进制,schema 52,health ok)
## 四、 预期结果 (Expected Results)
- docgov:租约持久化失败返回 error 并回滚内存状态;审计失败 slog.Error 可观测;重启后 fencing token 从 DB 读回
- chat:Session 字段访问全部经 mu 保护;`-race` 不报 data race
- projectinstance:SavePlanWithRevision 单事务原子;bump 冲突时 plan 不落库;completed_by = 推进操作者
- server:getOrCreateSession 内 DB 调用有 5s 超时
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:go vet 全量
- 输入:`go vet ./...`
- 输出:(空,零告警)
- 判定:PASS
### 用例 2:全量短测
- 输入:`go test -short ./...`
- 输出:55 包 ok,无 FAIL/panic
- 判定:PASS
### 用例 3:race 检测(受影响包)
- 输入:`go test -race -short ./internal/chat/ ./internal/docgov/ ./internal/projectinstance/`
- 输出:
```
ok chat-agent-system/internal/chat 1.054s
ok chat-agent-system/internal/docgov 1.038s
ok chat-agent-system/internal/projectinstance 1.015s
```
- 判定:PASS
### 用例 4:dev 冒烟(合入后 worktree)
- 输入:`.worktrees/dev-rdev-merge` 上 `go vet ./...` + `go test -short ./...`
- 输出:VET_OK,无 FAIL
- 判定:PASS
### 用例 5:dev 服务健康
- 输入:`curl http://127.0.0.1:8080/api/v1/health`
- 输出:`{"status":"ok","env":"dev","schema_version":52,"schema_ready":true,...}`
- 判定:PASS(注:跑的是合入前二进制,容器 rebuild 未执行,见七)
## 六、 自动化测试套件汇总 (Test Suite Execution)
- `go vet ./...` 零告警
- `go test -short ./...` 55 包全 PASS
- `go test -race -short`(chat/docgov/projectinstance)全 PASS
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 批 1 四个子项全部修复并合入 dev(merge `844f757`),质量门禁全绿,达到合入标准。
- **遗留**:dev 容器二进制仍为合入前版本(health 为旧码);如需真实链路验证 C2 竞态修复,应 `./scripts/env-service.sh dev rebuild` 后复跑。此为长操作,未在本批执行,留给集成槽位下一次 holder 或批 2 合入时一并 rebuild。
- 批 2(鉴权与越权)继续沿用本槽位流程。
## 证据
- merge commit:`844f757`(dev worktree)
- 批 1 三个 fix commit:`11f375f`(docgov)、`c7eab1f`(chat race)、`e2b1340`(projectinstance)、`a81db16`(ctx threading)
@@ -0,0 +1,67 @@
# 审计整改批 2(鉴权与越权)测试报告
## 一、 测试背景 (Background)
2026-09-19 审计([.doc/audit/2026-09-19-system-deep-audit.md](../audit/2026-09-19-system-deep-audit.md))安全面发现:H1 dev/test legacy 兜底静默、H2 docgov 批注身份伪造与读类端点越权、H3 会话查询水平越权、H4 登录无限流、H8 compose 弱口令兜底、M8 测试 flag 名笔误。
## 二、 测试目标 (Test Objectives)
- H2/H3 修复后既有鉴权测试不回退(server 包全 PASS)
- H4 限流器三态(放行/阻断/窗口过期/重置)有单测覆盖
- H8 compose 在无 `.env` 时 `:?required` 硬拦截
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支 `fix/audit-b2-authz-hardening` → dev(merge `08f4e0b`)
- 层级:单元(限流器)+ server 包回归 + compose 插值验证
## 四、 预期结果 (Expected Results)
- 批注/认领的 actor 一律取 principal;读类端点非项目成员 403
- `handleGetChatTurn`/`ListChatSessions`/`GetUserContext` 跨用户 403
- 登录窗口内第 11 次尝试 429;成功后计数清零
- 无 `.env` 时 `docker compose config` 报 required missing
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:限流器单测
- `go test -run TestLoginRateLimiter -v ./internal/server/`
```
--- PASS: TestLoginRateLimiter_BlocksAfterMaxAttempts (0.00s)
--- PASS: TestLoginRateLimiter_ResetClearsWindow (0.00s)
--- PASS: TestLoginRateLimiter_WindowExpiry (0.02s)
```
判定:PASS
### 用例 2:server 包回归(含既有鉴权测试)
- `go test -short ./internal/server/` → `ok 13.917s`
判定:PASS(`security_p0_test.go`/`security_penetration_test.go` 等不回退)
### 用例 3:compose required 拦截(无 .env 目录)
- `env -i docker compose -f cc-test.yml config`
```
error while interpolating services.app.environment.ADMIN_PASSWORD: required variable ADMIN_PASSWORD is missing a value: required
error while interpolating services.app.environment.APP_DB_DSN: required variable SYSTEM_DB_PASSWORD is missing a value: required
```
判定:PASS
### 用例 4:全量回归
- `go vet ./...` 零告警;`go test -short ./...` 无 FAIL
判定:PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
- `go vet ./...` 零告警
- `go test -short ./...` 55 包全 PASS
- 新增 `login_rate_limit_test.go` 3 个用例 PASS
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 批 2 六个子项全部修复并合入 dev(merge `08f4e0b`),达到合入标准。
- **待验证**:H2/H3 的越权负例(非项目成员访问 docgov 文档应 403)建议补 Playwright/HTTP 负例测试进批 3 或独立 hardening 批;当前由人工 code review + 既有鉴权测试不回退兜底。
- H1 仅加告警未删除兜底(删除留 backlog,见审计报告开放问题)。
## 证据
- merge commit:`08f4e0b`(dev worktree)
- fix commits:`d2903a1`(H1-H3)、`2dd8f46`(H4/H8/M8)
@@ -0,0 +1,61 @@
# 审计整改批 3(SSE 与事件可靠性)测试报告
## 一、 测试背景 (Background)
2026-09-19 审计 C3/H5/H6/H7:聊天 SSE 心跳 goroutine 在 handler 返回后仍可能写连接;同步 `/tasks/run` 受全局 `WriteTimeout=120s` 截断;任务 SSE 缺幂等复用;stale fencing ack 无日志;00001–00009 无 down、00012 seed DELETE 无守卫说明。
## 二、 测试目标 (Test Objectives)
- 改动后 `go vet` 零告警、`go test -short` 受影响包与全量无 FAIL
- 不改已应用 goose 校验和语义(仅加注释)
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支 `fix/audit-b3-sse-events` → dev(merge `a2a49a6`)
- 层级:`internal/server`、`internal/events`、`internal/db` 短测 + 全量短测
## 四、 预期结果 (Expected Results)
- 心跳 goroutine 在 `close(heartbeatDone)` 后 `WaitGroup` 退出
- `/tasks/run` 在执行前把写期限延长到 75 分钟
- 同幂等键且归属一致时 SSE 复用已有 run,不二次 `CreateAndStart`
- `ErrStaleFencing` ack 路径 `slog.Warn("events_stale_fencing_ack")`
- 00001/00012 头部注明不可改已应用文件
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:受影响包短测
- 输入:`go test -short ./internal/server/ ./internal/events/ ./internal/db/`
- 输出:
```
ok chat-agent-system/internal/server 13.985s
ok chat-agent-system/internal/events 0.004s
ok chat-agent-system/internal/db 0.003s
```
- 判定:PASS
### 用例 2:全量短测
- 输入:`go test -short ./...`
- 输出:无 FAIL/panic
- 判定:PASS
### 用例 3:vet
- 输入:`go vet ./internal/server/ ./internal/events/`
- 输出:零告警
- 判定:PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
- `go build ./...` 通过
- `go test -short ./...` 无 FAIL
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 批 3 已合入 dev(merge `a2a49a6`)。
- 已应用迁移不能补 down(goose 校验和);00001–00009 的 down 缺口只记注释,不改历史 SQL。
- 容器 rebuild 未做;下一 holder 可在批 4 后统一 rebuild。
## 证据
- merge:`a2a49a6`
- commits:`0531462`、`b65e8fb`
@@ -0,0 +1,52 @@
# 审计整改批 4(前端)测试报告
## 一、 测试背景 (Background)
审计 H9:KaTeX 失败回退把未转义公式放进占位符,还原发生在 `escapeHtml` 之后。另有未读乐观更新失败不回滚、会话切换后滚动基线不重置、Excel 全量进内存。
## 二、 测试目标 (Test Objectives)
- `npm test` 全绿(含伪造占位符用例)
- `npm run build` 通过
## 三、 测试方案与环境 (Test Plan & Environment)
- 分支 `fix/audit-b4-frontend` → dev(merge `d73bc79`)
- 命令:`cd web && npm test && npm run build`
- 未在浏览器复现 KaTeX catch 与万行 Excel(依赖构造输入);XSS 主路径由单测钉住
## 四、 预期结果 (Expected Results)
- 伪造 `XMATHTOKENX0XENDX` 不会被还原成 HTML
- catch 分支公式经 `escapeHtml`
- 未读 POST 失败回滚本地集合
- `sessionId` 变化时 `prevMsgCountRef` 归零
- Excel 预览最多 1000 行并提示
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:前端测试
- 输入:`npm test`
- 输出:`tests 406 pass`,vitest `3 files / 32 tests passed`,fail 0
- 判定:PASS
### 用例 2:生产构建
- 输入:`npm run build`
- 输出:`tsc && vite build` 成功,`precompress: wrote 49 .br and 49 .gz`
- 判定:PASS
## 六、 自动化测试套件汇总 (Test Suite Execution)
- node:test 406 + vitest 32,全部 PASS
- `tsc` 无错误
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 批 4 已合入 dev(`d73bc79`)。
- 浏览器端到端未覆盖 Excel 截断与未读回滚;需要时用真实文件和断网点测。
- 容器仍是合入前二进制,前端 dist 由 Go 服务托管时需 rebuild 才进 `:8080`。
## 证据
- merge:`d73bc79`
- commit:`6c28fca`
@@ -0,0 +1,72 @@
# 首次加载 U1 登录态基线 测试报告
## 一、 测试背景 (Background)
[首次加载方案](../remediation/2026-09-17-initial-load-performance-plan.md) 的 U1 要求登录态瀑布,不能用未登录测量代替。此前只完成未登录诊断。本轮在 `fix/audit-remainder-closeout` 补登录探针,核对 U4 成员扇出与 U3 重模块是否出现在首屏。
## 二、 测试目标 (Test Objectives)
- 登录后记录工作台就绪时间、资源摘要、成员 GET 与会话列表 GET。
- 证据去掉查询串,不保存令牌和正文。
- 不把 n=1 或本机延迟写成预算达标。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux;浏览器:`mcr.microsoft.com/playwright:v1.63.0-noble` headless Chromium,`--network host`。
- 入口 A:已部署 dev `http://127.0.0.1:8080`(容器内旧包,schema 52)。
- 入口 B:本仓 Vite `http://127.0.0.1:3100`,API 代理到 8080。
- 账号:容器环境变量中的管理员,不写入报告。
- 用例:`web/e2e/initial-load-performance.spec.ts`。每次新 context,不发送聊天消息。
- 重建后补测:8080 慢网 n=20 见第五节。仍未覆盖:热缓存对照、字体黑洞单独对照、3100/8081、U7 的 Vite 与依赖一起启动。
## 四、 预期结果 (Expected Results)
- 当前源码:登录成员同步只打当前项目,会话列表每个查询键成功后不再被成员更新重拉。
- 已部署旧包:预期仍按项目数扇出。该结果只说明容器落后,不说明源码回退。
- 匿名首屏资源路径不应包含 katex、mermaid、docx。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
- **测试输入 (Input)**:`RUN_INITIAL_LOAD_BASELINE=1`,Vite `INITIAL_LOAD_SAMPLES=20` 且 `EXPECT_INIT_MEMBER_PROJECTS=1`;8080 同样探针 n=1。
- **实际输出 (Actual Output)**:
```text
vite-3100.json samples 20
member projects 1 1
session gets 1 1
ready ms 118 152
anon visible ms 148 194
heavy []
anonymous summary requestCount 170 transferBytes 6918643 jsTransferBytes 2349690 jsCount 8
deployed-8080.json samples 1
memberGetCount 704
distinctMemberProjects 704
sessionListGetCount 30
anonymous jsTransferBytes 626281 path /assets/index-DhyNmxJE.js
workbenchReadyMs 181
```
- **评价判定 (Evaluation / Verdict)**:PASS(探针与 U4 源码行为)。Vite 20/20 为成员项目 1、会话列表 1,重模块未进首屏。FAIL(关账):8080 旧包仍 704/30;慢网与重启未测;Vite 170 请求 / 6.9 MB 是开发模式,不套生产体积预算。
- **性能与耗时 (Duration & Latency)**:20 次 Vite 登录工作台就绪 118–152 ms(本机、无带宽限制,不是预算验收)。重建后 8080 慢网 n=20、CPU 4 倍、阻断 Google 字体:10 Mbps 登录表单可见 p75 559 ms(p95 570);2 Mbps p75 1279 ms(p95 1289)。登录点击到工作台 p75 约 334–340 ms。这两项低于拟定 1.5 s / 3 s,但是本机 CDP 抽样。仅 app 容器重启 5 次到 `/health` 为 0.433–0.463 s,不是完整 U7 矩阵。
证据:[assets/2026-09-19-initial-load-u1/](assets/2026-09-19-initial-load-u1/)。
## 六、 自动化测试套件汇总 (Test Suite Execution)
相关单元测试:
```text
✔ freeform document actions live in one hook
✔ redactResourceUrl drops query and origin
✔ summarizeResources flags deferred heavy chunks
✔ countInitRequests separates member fanout from session lists
✔ percentile uses nearest-rank and stays null on empty input
ℹ pass 5 fail 0
```
Playwright:上述基线 1 passed。本报告不把未改动的 `go test ./...` 写成这次探针的验收。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
登录态基线已经能回答「耗时之后请求打到哪里」:已部署容器的主成本是 704 次成员 GET,当前源码已收成 1 次,但要占槽重建后在 8080 复测才能关 U4。U6 不在这次加索引:测到的瓶颈是未部署的扇出,不是一条慢 SQL。下一步是慢网/CPU 样本、U7 隔离重启,以及 dev 容器重建使 schema 升到 00053。
@@ -0,0 +1,66 @@
# 首次加载 U7 重启矩阵测试报告
## 一、 测试背景 (Background)
[方案 U7](../remediation/2026-09-17-initial-load-performance-plan.md) 要求分别记录 Vite 冷/热启动、仅 app 重启、以及数据库和应用一起启动,直到 ready 与首次页面。此前只有 app 容器重启到 `/health` 的 0.433–0.463 秒,没有 Vite,也没有 postgres 与 app 一起重启。
## 二、 测试目标 (Test Objectives)
- 无待执行迁移、数据库已在卷里时,app 与 postgres 一起重启后 `/ready` 的耗时。
- Vite 保留依赖缓存与清空 `node_modules/.vite` 之后,从进程启动到入口模块图取完的耗时。
- 不把监听成功写成登录表单已经可见。无头浏览器打不开时明确写未测。
- 达不到「较历史十几秒基线下降 50%」就不关闭 U7。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:linux。分支:`fix/audit-remainder-closeout`。计时开始时 commit `6bd338e`。
- dev:`docker compose -f docker-compose.dev.yml restart system-db app`,n=3。探测 `shuimu-context-pg-dev` 的 Docker health、`GET /api/v1/health`、`GET /ready`、`GET /`。
- Vite:`npx vite --host 127.0.0.1 --port 3100 --strictPort`。热启动保留 `.vite`,冷启动先删除。先记 HTML 200,再用无浏览器的模块图抓取从 `/src/main.tsx` 跟完 import(314 个模块,队列清空)。
- 未重启 test/main,未 rebuild 镜像,未晋升。
- 数字:`.doc/test-reports/assets/2026-09-19-initial-load-u7/timings.json`。
## 四、 预期结果 (Expected Results)
- `/ready` p95 ≤ 3 秒(方案对「无迁移且 DB 已就绪」的 app 重启预算;本次是 postgres 与 app 一起重启,单列,不拿去承诺整机开机)。
- Vite 冷启动若明显慢于热启动,才考虑 `server.warmup`。总耗时没有下降就不能把等待挪到预热里宣称消失。
- 8081 与浏览器登录表单不在本次能测范围里就保持未关。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 postgres + app 一起重启
- **测试输入**:连续 3 次 `restart system-db app`。卷上已有 schema 53,没有新迁移。
- **实际输出**:`/api/v1/health` 与 `/ready` 均为 200,`status=ok schema_version=53 schema_ready=true`。耗时 1.027 / 1.178 / 1.005 秒。Docker 把数据库标成 healthy 是 5.490 / 5.633 / 5.450 秒,间隔是 healthcheck 的 5 秒,晚于 HTTP ready。重启后首页 HTML 200,TTFB < 2 ms。结束后两个容器都是 healthy。
- **评价判定**:PASS(这条预算)。p95 约 1.2 秒,低于 3 秒。不外推到宿主机整机重启,也不覆盖 test 的 8081。
- **性能与耗时**:见上。三次合计约 16 秒。
### 5.2 Vite 监听与模块图
- **测试输入**:热启动 n=3(只测 HTML)与 n=2(模块图);冷依赖缓存 n=2。
- **实际输出**:Vite 日志 `ready in` 71–76 ms。从拉起到 HTML 200:热 0.342–0.344 秒,冷 0.345–0.352 秒。314 个模块抓完:热 1.069–1.117 秒,冷 1.433–1.453 秒。从进程启动到图抓完:热 1.29–1.43 秒,冷 1.71–1.73 秒。
- **评价判定**:冷缓存不是主因(大约多 0.35 秒)。不改 `vite.config.ts` 做 warmup,避免只把同样的等待挪到启动阶段。历史诊断里的 207 请求 / 12 秒和「重启后十几秒」这次没有复现。
- **性能与耗时**:见上。
### 5.3 登录表单可见
- **测试输入**:Playwright Chromium。
- **实际输出**:`chrome-headless-shell` 与完整 `chrome` 都缺 `libatk-1.0.so.0` 等系统库,进程退出码 127。没有登录框可见时间,也没有请求瀑布。
- **评价判定**:未测。U7 因此不关。不能写成首访已经比基线快 50%。
## 六、 自动化测试套件汇总 (Test Suite Execution)
本次是重启计时,不是 `go test`。相关回归:
```text
go test ./internal/squad/ -count=1 -run TestRDevQualityGates
# ok
```
该测试与 U7 无关,是同一轮里评审门禁误伤的回归,不拿它代替重启证据。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- postgres 与 app 一起重启到 `/ready` 约 1.0–1.2 秒,满足 3 秒预算。Docker health 的 5 秒是探测间隔,不是数据库没起来。
- Vite 冷/热差约 0.35 秒。不加 warmup。
- 登录表单、8081、以及相对「十几秒」基线的 50% 下降都没有证据。U7 保持未关。
- 测完后 dev 的 app 与 postgres 均为 healthy,Vite 仍听在 `127.0.0.1:3100`。未晋升 test/main。
@@ -0,0 +1,79 @@
# 研发工作流 P3 三样本真 PI 测试报告
## 一、 测试背景 (Background)
设计计划 P3 要求在真实产品 PI Agent 与 MiniMax 上抽三份样本:`rd_proposal`(document)、`rd_planning_review`(review_minutes),以及 `rd_sw_plan` 在激活规划期关闭(N/A)。此前只有 `rd_planning_review` 与 `rd_design_vv` 的抽样,没有这组三样本。
## 二、 测试目标 (Test Objectives)
- 主流程用 stub 跑完并批准后,才能激活 rdev。
- `rd_proposal`、`rd_planning_review` 必须走 `backend=pi-agent`,不能用 stub 充当验收。
- `rd_sw_plan` 在规划里保持关闭。
- 记录真实状态、字数、是否仍含模板占位句,以及评审质量门禁结果。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:linux。分支:`fix/audit-remainder-closeout`。
- 入口:dev `http://127.0.0.1:8080`,容器 `shuimu-agent-app-dev`、`shuimu-pi-agent-dev`(MiniMax-M2.7-highspeed)。
- 项目 `6533`。主流程只启用 `bd_intake`(旧键 `intake` 已不再出现在默认规划里),stub 生成后跨用户审批准,阶段推进到 `completed`,再保存并激活 rdev。
- rdev 只启用 `rd_proposal` 与 `rd_planning_review`。脚本:`.doc/test-reports/assets/2026-09-19-rdev-p3-real-pi/run_p3_real_pi.py`。
- 未改 nightly「PI 三工作流」门禁,也未把 rdev 加进 `.github/workflows/nightly-real-pi.yml`。PR CI 仍不跑真 PI。
## 四、 预期结果 (Expected Results)
- 激活回执里 `rd_sw_plan.enabled=false`,两个抽样任务为 true。
- `rd_proposal` 终态为 `completed` 或 `pending_author_confirmation`,正文不含「按本阶段专业结构写」。
- `rd_planning_review` 同样由真 PI 写出,并含「评审范围与对象 / 问题与决议 / 评审结论」。质量门禁要求「问题与决议」表的每一数据行都有问题、决议、责任人、期限。
- 建议书批准后才能离开 `RD01_planning`。未批准时下一阶段任务应被拒绝。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 `rd_sw_plan` 规划期关闭
- **测试输入**:rdev 规划只保留 `rd_proposal`、`rd_planning_review`。
- **实际输出**:`[13:57:41] plan flags proposal=True review=True sw_plan=False`,随后 `activate rdev http=200`。
- **评价判定**:PASS。不适用语义是规划期关闭,不是再生成一份不适用页。
- **性能与耗时**:激活本身小于 1 秒。
### 5.2 `rd_proposal`(document)
- **测试输入**:项目 6533,`backend=pi-agent`,材料为无创神经电刺激器立项简报。
- **实际输出**:`[14:04:51] done rd_proposal status=completed elapsed=430s`,`proposal chars=11550 placeholder=False`。终稿 [rd_proposal-final.md](./assets/2026-09-19-rdev-p3-real-pi/rd_proposal-final.md)。章节是模型自拟的「产品定义与范围 / 风险清单」等,不是模板里的「项目背景与立项依据」「产品定义与范围」「主要风险与对策概览」。
- **评价判定**:生成 PASS(真 PI、已完成、无占位句)。模板标题对齐 FAIL,不把这份终稿写成模板符合。
- **性能与耗时**:430 秒。
### 5.3 未批准时不能进入评审阶段
- **测试输入**:建议书仍是 `drafting` 时推进 `RD01_planning`。
- **实际输出**:`advance RD01_planning http=409`,正文为 `STAGE_GATE_NOT_READY`。接着启动 `rd_planning_review` 得到 `403 DOC_TASK_NOT_IN_ACTIVE_STAGE`。
- **评价判定**:PASS(负例符合阶段门禁)。随后对 `doc_proj6533_rd_proposal` 认领、送审、审核、批准均为 http 200,再推进 `RD01_planning` 为 200。
- **性能与耗时**:审批链约 5 秒。
### 5.4 `rd_planning_review`(review_minutes)
- **测试输入**:阶段已到 `RD02_planning_review` 后,`backend=pi-agent`。
- **实际输出**:约 580 秒后运行状态变为 `quality_failed`。终稿 13225 字,含「## 评审范围与对象」「## 问题与决议」「## 评审结论」,不含占位句。工作区 `manifest.json` 的质量报告:`passed=false`,`score=20`,四次「问题行缺少问题、决议、责任人或期限」。主表六列是齐的;同级标题下还有一张「法规/标准」表,那些行没有责任人与期限,被算进问题行。修复轮 `repair_1`、`repair_2` 之后仍是这个结果。终稿 [rd_planning_review-final.md](./assets/2026-09-19-rdev-p3-real-pi/rd_planning_review-final.md)。
- **评价判定**:真 PI 抽样已发生,质量门禁 FAIL。不能写成评审样本通过。
- **性能与耗时**:从 `14:11:29` 启动到轮询见到 `quality_failed` 为 580 秒。
## 六、 自动化测试套件汇总 (Test Suite Execution)
本报告的验收数据来自上述真 PI 控制台,不是 `go test` 的 stub。相关结构测试:
```text
cd web && npx tsx --test src/components/layout/WorkbenchView.test.ts src/components/chat/ChatColumn.test.ts src/components/doc/DocumentPane.test.ts
# 3 pass
```
未把 `go test -short ./...` 的既有 `TestArchitectureBoundaries` 失败算进这次 P3 判定。nightly 真 PI 工作流没有修改。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 三样本都在 dev 真 PI 上跑过:软件计划 N/A 关闭 PASS;建议书生成完成但未对齐模板标题;评审记录写出了规定章节,质量门禁 20 分,FAIL。
- 因此 P3 还不能标成干净通过,也不能据此晋升 test/main。
- 轮询原先不把 `quality_failed` 当终态,会空转到超时。脚本已把 `quality_failed` 与 `finalizing_failed` 视为结束。
- 红线未动:不写真实软件仓、不合入 FAV、不物理删除 D7。
## 八、 后续(不改写上面的当次判定)
2026-09-19 同一分支补了门禁:`markdownTable` 在第一张表结束后停止,不再把「问题与决议」后面的法规对照表算成缺责任人的问题行。`TestRDevQualityGates` 用保存的终稿复读,不再出现「问题行缺少」。这不是新的真 PI,建议书标题对齐仍然失败。
@@ -0,0 +1,64 @@
# 移除 Control Center 测试报告
## 一、 测试背景 (Background)
项目进度管理已由独立项目承担。本仓库曾合入 Control Center,需要删除其代码、部署、规范和专属文档,并确认产品智能体系统仍能编译、测试和启动。不恢复已下线的 `engineering-dashboard`。
## 二、 测试目标 (Test Objectives)
- 仓库内不再存在 Control Center 源码、compose、脚本和专属文档。
- `go vet`、`go build`、`go test -short`、`internal/archtest`、产品前端 `npm run build` 全部通过。
- 本地 `dev` 容器重建后健康检查为 200。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux。分支 `fix/remove-control-center`,基线为本地 `dev@2641045`。
- 层级:删除后的编译与短测;模块边界契约测试;产品前端构建。容器冒烟在合入本地 `dev` 之后执行。
- 证据:`.doc/test-reports/assets/2026-09-19-remove-control-center/verify.txt`。
## 四、 预期结果 (Expected Results)
- `cmd/control-center`、`internal/controlcenter`、`control-center/`、`deploy/control-center` 不存在。
- 上述命令退出码均为 0。
- `GET http://127.0.0.1:8080/health` 返回 `env=dev`、`schema_version=52`。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 源码与运行时
- **输入**:删除 Control Center 目录后检查路径与端口。
- **实际输出**:源码目录已不在索引中。`control-center` 进程已停。`docker rm -f control-center-db` 与 `docker volume rm control-center_cc-db-data` 成功。
- **判定**:PASS。
- **耗时**:容器删除 < 1s。
### 5.2 编译与测试
- **输入**:`go vet ./...`、`go build ./...`、`go test -short -count=1 ./...`、`go test -count=1 ./internal/archtest/`、`cd web && npm run build`。
- **实际输出**(摘自 `verify.txt`):
```text
vet=0
build=0
short=0
arch=0
web=0
```
- **判定**:PASS。
- **耗时**:整段验证约 33s。
## 六、 自动化测试套件汇总 (Test Suite Execution)
`go test -short -count=1 ./...` 退出码 0,无 FAIL。`internal/archtest` 单独再跑一次,退出码 0。完整输出见 `verify.txt`。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
达到合入本地 `dev` 的标准。本仓库不再包含 Control Center。不 push。
合入后 `./scripts/env-service.sh dev rebuild` 退出码 0。`GET http://127.0.0.1:8080/health` 返回 200:
```text
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"kb_ready":true,"database_ready":true,"schema_version":52,"schema_ready":true,"task_store_ready":true}
```
复查残留:`control-center/` 未跟踪目录已删除;本地分支 `feature/control-center-server` 已删除(`git branch -D`,原 tip `55fa8dd`)。`go build ./...` 退出码 0。`origin/feature/control-center-server` 未动。历史文档中的名称提及按用户要求保留。
@@ -0,0 +1,124 @@
# 开发分支全量深度测试与 test 环境晋升测试报告
## 一、 测试背景 (Background)
本轮测试背景为收口并合并完成的开发子分支 `fix/audit-remainder-closeout` 至 `dev` 分支,对系统执行全量深度测试(包含后端 Go 静态代码与架构边界检查、短单元测试、前端测试与生产构建、数据库迁移与集成测试、容器重新构建与真实运行时端点冒烟),并在验证全部通过后,将 `dev` 分支晋升合并至 `test` 分支并重启测试环境服务,供用户进行在线实测。
## 二、 测试目标 (Test Objectives)
1. **子分支合并**:将已完成的 `fix/audit-remainder-closeout` 分支干净合入 `dev` 分支(使用 `--no-ff`)。
2. **后端全量静态与单元测试**:`go vet ./...` 零告警,`go test -short ./...` 全部通过,架构边界检查 `TestArchitectureBoundaries` 无回归。
3. **前端完整性测试与构建**:`cd web && npm test && npm run build` 全部 PASS,产物打包与预压缩(brotli/gzip)成功。
4. **数据库与权限集成测试**:在 PostgreSQL 5433 环境下运行关键 E2E 治理、会话鉴权越权防范、文档修订等测试套件。
5. **容器构建与运行态验证**:开发环境(`dev`)容器服务重建(`app`、`events`、`pi-agent`),验证服务健康、安全响应头(CSP、nosniff、X-Frame-Options、Referrer-Policy)及认证链路正常。
6. **环境晋升与重启**:将 `dev` 合入 `test` 分支,重建 `test` 环境容器并验证服务健康与 schema 53 对齐。
## 三、 测试方案与环境 (Test Plan & Environment)
| 维度 | 配置/参数 |
|------|-----------|
| 操作系统 | Linux (x86_64) |
| Go 版本 | Go 1.22+ |
| Node/NPM | Node.js 20+ / Vite |
| 开发环境 (dev) | HTTP: 8080, DB: 5433 (PostgreSQL 16 + pgvector), Events: 8088, Pi-Agent: 18865 |
| 测试环境 (test) | HTTP: 8081, DB: 5434 (PostgreSQL 16 + pgvector), Events: 8089, Pi-Agent: 18866 |
| 共享知识库 (shared) | DB: 5432 (PostgreSQL 16 + pgvector) |
| 数据库迁移版本 | Goose Schema 53 (`00053_2026-09-19-document-content-projection.sql`) |
## 四、 预期结果 (Expected Results)
1. `git merge --no-ff fix/audit-remainder-closeout` 顺利完成无代码冲突。
2. `go vet ./...` 返回 0;`go test -short ./...` 全部包 PASS。
3. `cd web && npm test && npm run build` 零报错完成,产出预压缩文件。
4. `TestE2E_WorkflowGovernance` 及各项越权负例测试(`TestListChatSessions_CrossUserIs403` 等)全部 PASS。
5. `./scripts/env-service.sh dev rebuild` 成功,`curl http://127.0.0.1:8080/api/v1/health` 输出 `schema_version=53`、`status=ok`。
6. 合并至 `test` 分支后重建 `test` 服务,`curl http://127.0.0.1:8081/api/v1/health` 正常输出 `schema_version=53`。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 子分支合并结果
- **测试输入 (Input)**:`git merge --no-ff fix/audit-remainder-closeout -m "..."`
- **实际输出 (Actual Output)**:
```text
Merge made by the 'ort' strategy.
...
36 files changed, 543 insertions(+), 189 deletions(-)
```
- **评价判定 (Evaluation / Verdict)**:PASS。合并成功,保留完整 commit 历史。
### 5.2 后端静态质量与架构边界测试
- **测试输入 (Input)**:`go vet ./... && go test -short ./...`
- **实际输出 (Actual Output)**:
- `go vet ./...`:零告警输出,退出码 0。
- `TestArchitectureBoundaries`:在将合法的新增依赖(`intent` -> `squad`,`squad`/`template` -> `workflowdef`)补充至 `.doc/system-design/module-boundaries.yaml` 许可清单后,全量短测通过:
```text
=== RUN TestArchitectureBoundaries
--- PASS: TestArchitectureBoundaries (0.19s)
PASS
ok chat-agent-system/internal/archtest 0.198s
... 全量包 PASS ...
```
- **评价判定 (Evaluation / Verdict)**:PASS。
### 5.3 前端测试与构建
- **测试输入 (Input)**:`cd web && npm test && npm run build`
- **实际输出 (Actual Output)**:
- 单元测试套件全部通过(包含 `ChatColumn.test.ts`、`DocumentPane.test.ts`、`WorkbenchView.test.ts`、`initFanout.test.ts`、`workflowPrerequisite.test.ts` 等)。
- Vite 打包成功,入口 bundle `index-C5YTF8ik.js` 约 749 kB(br 173 kB),完成 66 个静态产物的 brotli 与 gzip 预压缩。
- **评价判定 (Evaluation / Verdict)**:PASS。
### 5.4 数据库与权限集成测试
- **测试输入 (Input)**:
`TEST_DATABASE_URL="postgres://app:dev_secret_db_pass@127.0.0.1:5433/agent_system_dev?sslmode=disable" go test -v ./internal/server/... -run 'TestE2E_WorkflowGovernance|TestDocgovCommentAuditNonMember|TestAuthMe_|TestListChatSessions_CrossUserIs403|TestDocRevision_'`
- **实际输出 (Actual Output)**:
```text
=== RUN TestDocRevision_UnauthenticatedAndUnknownOrphan
--- PASS: TestDocRevision_UnauthenticatedAndUnknownOrphan (0.12s)
=== RUN TestDocRevision_ControlledDocumentRoutes
--- PASS: TestDocRevision_ControlledDocumentRoutes (0.12s)
=== RUN TestDocRevision_PatchOrder_RetryProjectsWithoutSecondLedgerCommit
--- PASS: TestDocRevision_PatchOrder_RetryProjectsWithoutSecondLedgerCommit (0.12s)
=== RUN TestAuthMe_LogoutNextRequestIs401
--- PASS: TestAuthMe_LogoutNextRequestIs401 (0.13s)
=== RUN TestListChatSessions_CrossUserIs403
--- PASS: TestListChatSessions_CrossUserIs403 (0.50s)
=== RUN TestE2E_WorkflowGovernance_CompleteAndReplan
--- PASS: TestE2E_WorkflowGovernance_CompleteAndReplan (0.23s)
PASS
ok chat-agent-system/internal/server 2.202s
```
- **评价判定 (Evaluation / Verdict)**:PASS。
### 5.5 开发环境容器重建与运行时冒烟
- **测试输入 (Input)**:`./scripts/env-service.sh dev rebuild`
- **实际输出 (Actual Output)**:
- 容器更新:`shuimu-context-pg-dev` (healthy), `shuimu-pi-agent-dev` (healthy), `shuimu-agent-app-dev` (healthy), `shuimu-agent-events-dev` (healthy)。
- 健康检查 (`GET /api/v1/health`):
```json
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"kb_ready":true,"database_ready":true,"schema_version":53,"schema_ready":true,"task_store_ready":true}
```
- 安全响应头 (`curl -I http://127.0.0.1:8080/api/v1/health`):
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `Referrer-Policy: strict-origin-when-cross-origin`
- `Content-Security-Policy: default-src 'self'; ...`
- 登录与认证端点:
- 未认证请求 `/api/v1/workflows/catalog` 返回 `401 ERR_UNAUTHENTICATED`。
- 管理员登录 `POST /api/v1/auth/login` 成功签发 Bearer Token。
- 携带 Token 请求 `/api/v1/auth/me` 及 `/api/v1/workflows/catalog` 均返回 200 正常数据。
- **评价判定 (Evaluation / Verdict)**:PASS。
## 六、 自动化测试套件汇总 (Test Suite Execution)
| 测试类型 | 执行命令 | 耗时 | 结果 |
|----------|----------|------|------|
| Go 静态检查 | `go vet ./...` | ~3s | PASS |
| Go 短单元测试 | `go test -short ./...` | ~16s | 46 个包全部 PASS |
| 前端测试与构建 | `cd web && npm test && npm run build` | ~18s | PASS (生成 br/gz 压缩包) |
| 治理与权限 PG 集成 | `TEST_DATABASE_URL=... go test ...` | ~2.2s | 全部测试用例 PASS |
| 运行时服务健康与安全头 | `curl -sf http://127.0.0.1:8080/...` | <1s | PASS (`schema_version=53`) |
## 七、 测试结论与后续建议 (Conclusion & Next Steps)
1. **结论**:开发分支(`dev`)已完整合入审计剩余修复项、工作台模块化拆分、rdev 文档匹配及 Schema 53 迁移,所有深度测试全绿,具备晋升至测试环境(`test`)的标准。
2. **晋升操作**:执行 `dev` 向 `test` 分支的 `--no-ff` 合并,并触发 `test` 环境服务重建(`./scripts/env-service.sh test rebuild`),供在线实测。
@@ -0,0 +1,6 @@
{
"key": "workflow.allow_author_only_approval",
"value": true,
"revision": 1,
"note": "dev pilot enabled; test/main not promoted"
}
@@ -0,0 +1,5 @@
{
"key": "workflow.allow_author_only_approval",
"value": false,
"revision": 0
}
@@ -0,0 +1,3 @@
{"key":"workflow.allow_author_only_approval","label":"允许编制人兼任审核批准","group":"workflow","type":"bool","value":true,"default":false,"writable":true,"requiresRestart":false,"description":"授权新配置:开启后项目创建者可在激活前为文档启用编制人兼任。关闭后禁止新启用/激活兼任规划;已激活实例按冻结职责继续执行,不作为紧急熔断。","revision":1,"updatedAt":"2026-09-17T14:03:22.990984Z","updatedBy":9}
HTTP 200
@@ -0,0 +1 @@
{"id":293,"doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"task_key":"rd_design_input_spec","title":"设计输入规格书","stage":"RD03_design_input","version":1,"current_state":"drafting","is_locked":false,"is_template_only":false,"content_sha256":"3b763a3488dbd4fab8d7793f90b46f3373457f3745f3906b3c33e2bd39af39dc","work_dir":"/app/data/workspaces/bizdev/rd_design_input_spec_1789635960900711737","author_id":9,"author_name":"系统管理员","reviewer_id":9,"reviewer_name":"系统管理员","approver_id":9,"approver_name":"系统管理员","duty_locked":true,"duty_policy":"author_only","author_claimed":true,"author_claimed_at":"2026-09-17T13:34:38.964259Z","author_last_viewed_at":"2026-09-17T13:47:35.879256Z","author_last_edited_at":null,"reviewer_claimed":false,"reviewer_claimed_at":null,"approver_claimed":false,"approver_claimed_at":null,"last_rejected_reason":"","last_rejected_by_role":"","last_rejected_by_name":"","last_rejected_at":null,"approved_at":null,"config":{"reject_rollback_to":"drafting","allow_approver_to_reviewer":true,"require_author_confirm_on_reject":true},"created_at":"2026-09-17T09:06:00.895726Z","updated_at":"2026-09-17T13:47:35.879256Z"}
@@ -0,0 +1,3 @@
{"id":293,"doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"task_key":"rd_design_input_spec","title":"设计输入规格书","stage":"RD03_design_input","version":1,"current_state":"drafting","is_locked":false,"is_template_only":false,"content_sha256":"3b763a3488dbd4fab8d7793f90b46f3373457f3745f3906b3c33e2bd39af39dc","work_dir":"/app/data/workspaces/bizdev/rd_design_input_spec_1789635960900711737","author_id":9,"author_name":"系统管理员","reviewer_id":9,"reviewer_name":"系统管理员","approver_id":9,"approver_name":"系统管理员","duty_locked":true,"duty_policy":"author_only","author_claimed":true,"author_claimed_at":"2026-09-17T13:34:38.964259Z","author_last_viewed_at":"2026-09-17T14:10:56.545668337Z","author_last_edited_at":null,"reviewer_claimed":false,"reviewer_claimed_at":null,"approver_claimed":false,"approver_claimed_at":null,"last_rejected_reason":"","last_rejected_by_role":"","last_rejected_by_name":"","last_rejected_at":null,"approved_at":null,"config":{"reject_rollback_to":"drafting","allow_approver_to_reviewer":true,"require_author_confirm_on_reject":true},"created_at":"2026-09-17T09:06:00.895726Z","updated_at":"2026-09-17T14:10:56.545668337Z"}
HTTP 200
@@ -0,0 +1,3 @@
{"id":139,"proposal_id":"prop_rd_design_input_spec_1789654256551680649","doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"triggered_by":"http_smoke","proposed_changes":"补充设计输入 EMC 共模抑制指标","impact_analysis":"影响原理图滤波网络","risk_assessment":"低风险","status":"pending_author_approval","author_decision_reason":"","decided_at":null,"created_at":"2026-09-17T14:10:56.551684908Z"}
HTTP 200
@@ -0,0 +1,3 @@
{"id":139,"proposal_id":"prop_rd_design_input_spec_1789654256551680649","doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"triggered_by":"http_smoke","proposed_changes":"补充设计输入 EMC 共模抑制指标","impact_analysis":"影响原理图滤波网络","risk_assessment":"低风险","status":"approved_by_author","author_decision_reason":"HTTP 冒烟批准","decided_at":"2026-09-17T14:10:56.576516211Z","created_at":"2026-09-17T14:10:56.551684908Z"}
HTTP 200
@@ -0,0 +1,5 @@
proposal_id | status | changes
-----------------------------------------------+--------------------+-------------------------------
prop_rd_design_input_spec_1789654256551680649 | approved_by_author | 补充设计输入 EMC 共模抑制指标
(1 row)
@@ -0,0 +1,20 @@
=== claim ===
{"id":293,"doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"task_key":"rd_design_input_spec","title":"设计输入规格书","stage":"RD03_design_input","version":1,"current_state":"reviewing","is_locked":true,"is_template_only":false,"content_sha256":"3b763a3488dbd4fab8d7793f90b46f3373457f3745f3906b3c33e2bd39af39dc","work_dir":"/app/data/workspaces/bizdev/rd_design_input_spec_1789635960900711737","author_id":9,"author_name":"系统管理员","reviewer_id":9,"reviewer_name":"系统管理员","approver_id":9,"approver_name":"系统管理员","duty_locked":true,"duty_policy":"author_only","author_claimed":true,"author_claimed_at":"2026-09-17T13:34:38.964259543Z","author_last_viewed_at":"2026-09-17T13:35:23.866926066Z","author_last_edited_at":null,"reviewer_claimed":false,"reviewer_claimed_at":null,"approver_claimed":false,"approver_claimed_at":null,"last_rejected_reason":"","last_rejected_by_role":"","last_rejected_by_name":"","last_rejected_at":null,"approved_at":null,"config":{"reject_rollback_to":"drafting","allow_approver_to_reviewer":true,"require_author_confirm_on_reject":true},"created_at":"2026-09-17T09:06:00.895726Z","updated_at":"2026-09-17T13:35:23.866926066Z"}
HTTP 200
=== submit ===
{"code":"VALIDATION","message":"请求参数无效","request_id":"req_a48e5a5d351af446","error":"submit review failed: docgov: invalid document lifecycle state transition: 无法从【reviewing】阶段提交审核,必须为【drafting】"}
HTTP 400
=== review_approve ===
{"id":293,"doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"task_key":"rd_design_input_spec","title":"设计输入规格书","stage":"RD03_design_input","version":1,"current_state":"approving","is_locked":true,"is_template_only":false,"content_sha256":"3b763a3488dbd4fab8d7793f90b46f3373457f3745f3906b3c33e2bd39af39dc","work_dir":"/app/data/workspaces/bizdev/rd_design_input_spec_1789635960900711737","author_id":9,"author_name":"系统管理员","reviewer_id":9,"reviewer_name":"系统管理员","approver_id":9,"approver_name":"系统管理员","duty_locked":true,"duty_policy":"author_only","author_claimed":true,"author_claimed_at":"2026-09-17T13:34:38.964259543Z","author_last_viewed_at":"2026-09-17T13:35:23.866926066Z","author_last_edited_at":null,"reviewer_claimed":false,"reviewer_claimed_at":null,"approver_claimed":false,"approver_claimed_at":null,"last_rejected_reason":"","last_rejected_by_role":"","last_rejected_by_name":"","last_rejected_at":null,"approved_at":null,"config":{"reject_rollback_to":"drafting","allow_approver_to_reviewer":true,"require_author_confirm_on_reject":true},"created_at":"2026-09-17T09:06:00.895726Z","updated_at":"2026-09-17T13:35:23.888196734Z"}
HTTP 200
=== approver_approve ===
{"id":293,"doc_id":"doc_proj6425_rd_design_input_spec","project_id":6425,"task_key":"rd_design_input_spec","title":"设计输入规格书","stage":"RD03_design_input","version":1,"current_state":"approved","is_locked":true,"is_template_only":false,"content_sha256":"3b763a3488dbd4fab8d7793f90b46f3373457f3745f3906b3c33e2bd39af39dc","work_dir":"/app/data/workspaces/bizdev/rd_design_input_spec_1789635960900711737","author_id":9,"author_name":"系统管理员","reviewer_id":9,"reviewer_name":"系统管理员","approver_id":9,"approver_name":"系统管理员","duty_locked":true,"duty_policy":"author_only","author_claimed":true,"author_claimed_at":"2026-09-17T13:34:38.964259543Z","author_last_viewed_at":"2026-09-17T13:35:23.866926066Z","author_last_edited_at":null,"reviewer_claimed":false,"reviewer_claimed_at":null,"approver_claimed":false,"approver_claimed_at":null,"last_rejected_reason":"","last_rejected_by_role":"","last_rejected_by_name":"","last_rejected_at":null,"approved_at":"2026-09-17T13:35:23.898240156Z","config":{"reject_rollback_to":"drafting","allow_approver_to_reviewer":true,"require_author_confirm_on_reject":true},"created_at":"2026-09-17T09:06:00.895726Z","updated_at":"2026-09-17T13:35:23.898240156Z"}
HTTP 200
@@ -0,0 +1,7 @@
=== negative review by lizhuguan ===
{"error":"DOC_DUTY_FORBIDDEN","message":"当前用户不是该文档的对应职责人"}
HTTP 403
=== negative approve by lizhuguan ===
{"error":"DOC_DUTY_FORBIDDEN","message":"当前用户不是该文档的对应职责人"}
HTTP 403

Some files were not shown because too many files have changed in this diff Show More