Compare commits

...

167 Commits

Author SHA1 Message Date
081706f735 quick fix 2026-04-15 07:14:36 +01:00
zhi
3e9f91f54b chore: update HarborForge.Test submodule pointer to main head 2026-04-05 22:18:03 +00:00
zhi
671db14797 chore: update HarborForge submodule pointers 2026-04-05 22:14:41 +00:00
h z
afb190003e Merge pull request 'dev-2026-03-29' (#7) from dev-2026-03-29 into main
Reviewed-on: #7
2026-04-05 22:11:44 +00:00
72d08a3c56 chore: bump HarborForge component pointers for code-first indexing 2026-04-03 16:25:48 +00:00
zhi
1efd77f07a TEST-CLI-CAL-001 TEST-CLI-PR-001 complete CLI test tasks 2026-04-01 12:03:37 +00:00
zhi
9fc0b4934e TEST-FE-PR-001: Mark task as completed
- Essential 列表与表单 ✓
- Accept milestone 选择 ✓
- story 创建入口限制 ✓
2026-04-01 11:41:56 +00:00
zhi
d5d0fa3223 TEST-FE-CAL-001 complete calendar frontend test coverage 2026-04-01 11:06:05 +00:00
zhi
e30a65b8b5 TEST-BE-CAL-001 record calendar backend test completion 2026-04-01 10:35:57 +00:00
zhi
f984a81f86 TEST-BE-PR-001 verify backend proposal tests 2026-04-01 10:04:50 +00:00
zhi
4a51fb10f7 PLG-CAL-004: Mark task as complete - ScheduledGatewayRestart handling
- Update submodule to include state persistence and restart handling
- Mark PLG-CAL-004 tasks as complete in TASKLIST.md
2026-04-01 09:41:24 +00:00
zhi
9aa385db8c PLG-CAL-003 complete plugin deferred replanning 2026-04-01 08:52:16 +00:00
zhi
fea3c05999 PLG-CAL-002: Mark task as complete
- Update TASKLIST.md to mark PLG-CAL-002 as completed
- Plugin submodule updated with scheduler implementation
2026-04-01 08:45:38 +00:00
zhi
f3f85a4b32 chore: mark PLG-CAL-001 complete in TASKLIST.md
- PLG-CAL-001: Calendar heartbeat format — all 3 sub-items completed:
  claw_identifier 传递方式 / agent_id 传递方式 / slot 列表结构
- Spec documented in HarborForge.OpenclawPlugin/docs/PLG-CAL-001-calendar-heartbeat-format.md
2026-04-01 07:52:39 +00:00
zhi
7ca3bbb668 feat(OpenclawPlugin): PLG-CAL-001: Calendar heartbeat format — submodule update
Update HarborForge.OpenclawPlugin to commit 55d7d11:
- plugin/calendar/types.ts: heartbeat request/response TypeScript types
- plugin/calendar/calendar-bridge.ts: CalendarBridgeClient HTTP client
- plugin/calendar/index.ts: module exports
- docs/PLG-CAL-001-calendar-heartbeat-format.md: full format specification
- plugin/openclaw.plugin.json: calendar config options

Ref: HarborForge.NEXT_WAVE_DEV_DIRECTION.md §6, PLG-CAL-001
2026-04-01 07:52:07 +00:00
zhi
54c416c01d CLI-CAL-001/002/003/004/005/006/007/008/009/010: Calendar CLI commands 2026-04-01 07:02:47 +00:00
zhi
087e477395 CLI-PR-001/002/003/004: Proposal rename, Essential commands, story restriction 2026-04-01 06:56:30 +00:00
zhi
113b2757ee FE-CAL-004/005: Calendar create/edit/cancel + status warnings 2026-04-01 06:50:11 +00:00
zhi
0418ce7f0b FE-CAL-001/002/003: Calendar page skeleton with slot list and plans view 2026-04-01 06:48:22 +00:00
zhi
88a5d94d12 Update Frontend submodule: FE-PR-005 story restriction 2026-04-01 06:46:27 +00:00
zhi
ce84a5387a FE-PR-003/004/005: Mark existing Essential forms & Accept modal done; remove story from task creation
- FE-PR-003: Essential create/edit modal with type selector and partial refresh already implemented in ProposalDetailPage
- FE-PR-004: Accept modal with milestone selector and generated tasks display already implemented
- FE-PR-005: Remove 'story' from TASK_TYPES in CreateTaskPage and CreateTaskModal - all story/* must come from Proposal Accept workflow
2026-04-01 06:46:01 +00:00
zhi
ad0d1675b0 FE-PR-002: Mark task as completed in TASKLIST.md 2026-04-01 06:28:52 +00:00
zhi
0596043b47 FE-PR-002: Update Frontend submodule for Essential list feature 2026-04-01 06:25:54 +00:00
zhi
a8d40134af FE-PR-001: Update Frontend submodule - Propose -> Proposal rename 2026-04-01 04:46:50 +00:00
zhi
c40774199e BE-AGT-004 complete exhausted recovery parsing 2026-04-01 04:18:48 +00:00
zhi
1c87e24ea9 BE-AGT-003: mark task complete, update Backend submodule ref 2026-04-01 02:50:20 +00:00
zhi
e758f977fc BE-AGT-002: mark task complete, update Backend submodule ref 2026-04-01 00:46:23 +00:00
zhi
c4d2b836ca BE-AGT-001: mark task complete, update backend submodule 2026-03-31 23:01:52 +00:00
zhi
6bcea047db BE-CAL-API-007: update submodule ref and mark task complete 2026-03-31 20:46:53 +00:00
zhi
13d13a0f5e BE-CAL-API-006: implement plan-edit and plan-cancel API endpoints
- PATCH /calendar/plans/{plan_id}: edit a recurring schedule plan
  - Validates period-parameter hierarchy after merge
  - Rejects edits to inactive (cancelled) plans
  - Detaches future materialized slots so they keep old data
  - Past materialized slots remain untouched

- POST /calendar/plans/{plan_id}/cancel: cancel (soft-delete) a plan
  - Sets is_active=False
  - Detaches future materialized slots (plan_id -> NULL)
  - Preserves past materialized slots, returns their IDs

- Added SchedulePlanEdit and SchedulePlanCancelResponse schemas
- Imported guard_plan_edit/cancel_no_past_retroaction from slot_immutability
2026-03-31 16:46:22 +00:00
zhi
3a65c94764 Update Backend submodule: BE-CAL-API-005 2026-03-31 14:47:21 +00:00
zhi
b5163d5e0f BE-CAL-API-005: implement plan-schedule / plan-list API
- Add SchedulePlanCreate, SchedulePlanResponse, SchedulePlanListResponse schemas
- Add DayOfWeekEnum, MonthOfYearEnum schema enums
- Add POST /calendar/plans endpoint (create plan with hierarchy validation)
- Add GET /calendar/plans endpoint (list plans, optional include_inactive)
- Add GET /calendar/plans/{plan_id} endpoint (get single plan)
- Mark BE-CAL-API-005 complete in TASKLIST.md
2026-03-31 14:46:45 +00:00
zhi
16bcd94027 BE-CAL-API-004: Implement Calendar cancel API for real and virtual slots
- Add POST /calendar/slots/{slot_id}/cancel for real slot cancellation
- Add POST /calendar/slots/virtual/{virtual_id}/cancel for virtual slot cancellation
- Virtual cancel materializes the slot first, then marks as Skipped
- Both endpoints enforce past-slot immutability guard
- Both endpoints detach from plan (set plan_id=NULL)
- Status set to SlotStatus.SKIPPED on cancel
- Add TimeSlotCancelResponse schema
- Import guard_cancel_real_slot and guard_cancel_virtual_slot
2026-03-31 12:47:56 +00:00
zhi
e561298c97 BE-CAL-API-003: implement Calendar edit API for real and virtual slots
- Add TimeSlotEdit schema (partial update, all fields optional)
- Add TimeSlotEditResponse schema
- Add PATCH /calendar/slots/{slot_id} for editing real slots
- Add PATCH /calendar/slots/virtual/{virtual_id} for editing virtual slots
  - Triggers materialization before applying edits
  - Detaches from plan after edit
- Both endpoints enforce:
  - Past-slot immutability guard
  - Overlap detection (excluding self)
  - Plan detachment on edit
  - Workload warnings in response
2026-03-31 10:46:19 +00:00
zhi
7e3acf80ce BE-CAL-API-002: Implement calendar day-view query API
- Add GET /calendar/day endpoint with optional ?date= query param
- Returns unified CalendarDayResponse merging real slots + virtual plan slots
- New CalendarSlotItem schema supports both real (id) and virtual (virtual_id) slots
- Excludes inactive slots (skipped/aborted) from results
- All slots sorted by scheduled_at ascending
2026-03-31 07:19:01 +00:00
zhi
77d8f6098f BE-CAL-API-001: Update submodule ref + mark task complete 2026-03-31 05:46:03 +00:00
zhi
18e50156df BE-CAL-API-001: Implement single slot creation API
- Add TimeSlotCreate, TimeSlotResponse, TimeSlotCreateResponse schemas
- Add SlotConflictItem, SlotTypeEnum, EventTypeEnum, SlotStatusEnum to schemas
- Add POST /calendar/slots endpoint with:
  - Overlap detection (409 on conflict)
  - Workload warning computation (advisory, returned in response)
  - Support for event_type + event_data (job/system/entertainment)
  - Default date to today if not provided
- Add _slot_to_response helper for ORM -> schema conversion
2026-03-31 05:45:51 +00:00
zhi
bc1a427f22 BE-CAL-007 + BE-CAL-008: mark completed, update Backend submodule 2026-03-31 04:16:58 +00:00
zhi
5b9d2618ad BE-CAL-006: mark overlap detection task complete in TASKLIST 2026-03-31 01:18:01 +00:00
zhi
eece0773cb Update Backend submodule: BE-CAL-005 plan virtual-slot materialization 2026-03-30 23:47:15 +00:00
zhi
3e1fe5cc79 BE-CAL-005: Implement plan virtual-slot identification and materialization
- Virtual slot ID: plan-{plan_id}-{YYYY-MM-DD} format with parse/make helpers
- Plan-date matching: on_month/on_week/on_day hierarchy with week_of_month calc
- Materialization: convert virtual slot to real TimeSlot row, copy plan template
- Detach: clear plan_id after edit/cancel to break plan association
- Bulk materialization: materialize_all_for_date for daily pre-compute
- 23 tests covering all paths (matching, virtual gen, materialize, detach, bulk)
2026-03-30 23:46:51 +00:00
zhi
d12a46b2a3 BE-CAL-004: update submodule pointer + mark task complete in TASKLIST 2026-03-30 22:27:15 +00:00
zhi
c01881ade0 BE-CAL-003: Agent model with status/heartbeat/exhausted fields (backend submodule) 2026-03-30 20:47:56 +00:00
zhi
35045a9490 Mark BE-CAL-002 complete in TASKLIST.md 2026-03-30 19:16:33 +00:00
zhi
ea9f12b9b1 BE-CAL-001: Mark TimeSlot model task complete, update Backend submodule 2026-03-30 17:45:22 +00:00
zhi
2d5e055fc8 BE-PR-011: Mark Proposal/Essential/Story restricted tests complete
- Updated HarborForge.Backend submodule (test infra fix + 29 passing tests)
- Marked BE-PR-011 complete in TASKLIST.md
2026-03-30 16:17:16 +00:00
zhi
52530486d1 BE-PR-010: clean up feat_task_id semantics — deprecate with read-only compat
Decision: retain DB column, mark DEPRECATED. Existing rows still return
feat_task_id via API. New accept flow (BE-PR-007) does not write it.
Clients should migrate to generated_tasks / Task.source_proposal_id.

- Backend: model/schema/router deprecation comments updated
- Backend: added docs/BE-PR-010-feat-task-id-deprecation.md
- Tests: updated to work with Essential-based accept flow
- Tests: all 21 proposal tests pass
- TASKLIST: BE-PR-010 marked complete
2026-03-30 12:50:14 +00:00
zhi
f61b5ee17f BE-PR-009: restrict all story/* task types + fix test conftest imports 2026-03-30 11:46:28 +00:00
zhi
93fe52750c Mark BE-PR-008 complete in TASKLIST.md 2026-03-30 10:46:38 +00:00
zhi
051183bbe7 Update Backend submodule: BE-PR-008 tracking fields 2026-03-30 10:46:28 +00:00
zhi
988cfcec4d BE-PR-007: mark task complete, update Backend submodule ref 2026-03-30 07:46:28 +00:00
zhi
6493e72d80 Update Backend submodule ref for BE-PR-006 2026-03-30 07:16:34 +00:00
zhi
23052db117 BE-PR-006: Add Essential CRUD API under Proposals
- New router: /projects/{project_id}/proposals/{proposal_id}/essentials
  - GET    (list)   - list all essentials under a proposal
  - POST   (create) - create essential with auto-generated EssentialCode
  - GET    /{id}    - get single essential by id or essential_code
  - PATCH  /{id}    - update essential (title, type, description)
  - DELETE /{id}    - delete essential
- All mutations restricted to open proposals only
- Permission: creator, project owner, or global admin
- Registered essentials router in main.py
- Updated GET /proposals/{id} to return ProposalDetailResponse with
  embedded essentials list
- Activity logging on all CRUD operations
2026-03-30 07:16:21 +00:00
zhi
5be0f11aac Update Backend submodule ref for BE-PR-005 2026-03-30 06:45:30 +00:00
zhi
5d20df11e9 BE-PR-005: Add Essential schema definitions (create/update/response) and ProposalDetailResponse with nested essentials 2026-03-30 06:45:06 +00:00
zhi
b688ebd35d BE-PR-004: implement EssentialCode encoding rules (submodule update) 2026-03-30 06:16:05 +00:00
zhi
1cdd05d554 BE-PR-003: Update Backend submodule ref + mark task complete 2026-03-29 16:33:10 +00:00
zhi
5ee79e5c5e BE-PR-003: Add Essential SQLAlchemy model
- New app/models/essential.py with Essential model and EssentialType enum
  (feature, improvement, refactor)
- Fields: id, essential_code (unique), proposal_id (FK to proposes),
  type, title, description, created_by_id (FK to users), created_at, updated_at
- Added essentials relationship to Proposal model (cascade delete-orphan)
- Added essentials table auto-migration in main.py _migrate_schema()
- Registered essential module import in startup()
2026-03-29 16:32:40 +00:00
zhi
598900650d chore: update Backend submodule pointer (BE-PR-002) 2026-03-29 16:02:22 +00:00
zhi
ac585b09b1 BE-PR-002: Proposal model naming & field adjustments
- Add comprehensive docstring to Proposal model documenting all relationships
- Add column comments for all fields (title, description, status, project_id, etc.)
- Mark feat_task_id as DEPRECATED (will be replaced by Essential→task mapping in BE-PR-008)
- Add proposal_code hybrid property as preferred alias for DB column propose_code
- Update ProposalResponse schema to include proposal_code alongside propose_code
- Update serializer to emit both proposal_code and propose_code for backward compat
- No DB migration needed — only Python-level changes
2026-03-29 16:02:07 +00:00
zhi
55ac776462 BE-PR-001: Rename Propose -> Proposal across backend
- Backend: new canonical Proposal model + /proposals router
- Backward-compat shims for old Propose imports and /proposes API
- Tests updated to use /proposals, legacy compat tests added
- Impact checklist: docs/BE-PR-001-rename-impact.md
- TASKLIST.md: BE-PR-001 marked complete

All 21 proposal tests pass.
2026-03-29 15:35:59 +00:00
zhi
339f9aa126 DOC-003: 整理 Calendar 验收清单
- 后端验收项: 数据模型、Slot ID 策略与物化、验证规则、不可变性、Calendar API、Agent/心跳协作
- 前端验收项: 页面骨架、日程展示、计划展示、操作交互、状态提示、权限
- CLI 验收项: 命令组、日程/计划操作命令、输出格式、用户创建扩展
- 插件联动验收项: 心跳请求、唤醒逻辑、状态管理、ScheduledGatewayRestart
- 跨模块集成验收项
2026-03-29 15:01:35 +00:00
zhi
c2b11248d7 DOC-002: Proposal/Essential/Story restricted migration guide
- Document Propose → Proposal naming changes across all layers
- Document Proposal Accept semantic change (single task → Essential-based batch)
- Document story/* restricted expansion and impact analysis
- Document feat_task_id deprecation and backward compatibility strategy
- Document migration execution order and rollback plan
2026-03-29 14:32:23 +00:00
zhi
d6ed523731 DOC-001: 整理本波开发范围说明
- 明确 Calendar 为独立功能线,Proposal/Essential 为项目结构调整线
- 明确两条线交叉点仅限 event_data / Agent 调度引用层
- 区分必须本波完成 vs 仅设计保留内容
- 新增 docs/wave-2026-03-scope.md
2026-03-29 14:01:10 +00:00
d7029a1cc7 Merge pull request 'chore/archive-plans-and-next-wave-doc' (#6) from chore/archive-plans-and-next-wave-doc into main
Reviewed-on: #6
2026-03-29 11:45:01 +00:00
nav
8d7ca51649 docs: refine tasklist by module boundaries 2026-03-29 11:43:17 +00:00
nav
05185c9b21 docs: move tasklist under plans 2026-03-29 11:34:12 +00:00
nav
b416c60ae7 docs: move plans into archive and place next wave doc under plans 2026-03-29 11:19:33 +00:00
nav
c2b9242aca docs: archive completed plans and rename next wave doc 2026-03-29 11:17:48 +00:00
nav
27696c70f9 feat: add Agent Exhausted state machine & ScheduledGatewayRestart SystemEvent to calendar design 2026-03-23 22:38:02 +00:00
nav
1e7c772f68 docs: add Calendar system design document 2026-03-22 23:40:26 +00:00
zhi
ca15ab2593 Update submodules to latest main commits 2026-03-22 14:21:28 +00:00
5176d1357d Merge pull request 'Merge dev-2026-03-22 into main' (#5) from dev-2026-03-22 into main
Reviewed-on: #5
2026-03-22 14:18:47 +00:00
zhi
8289a56019 Update Backend + Frontend submodules for milestones fix, acc-mgr, reset-apikey 2026-03-22 05:39:15 +00:00
zhi
62ac7453a5 docs: finalize cross-project planning items
- Mark MVP scope as finalized
- Define release order across submodules
- Document rollback/degradation strategy
- Close CLI contribution note item
- Close repo-config-safe note
2026-03-22 01:38:17 +00:00
zhi
44f5d50261 feat: complete plugin↔monitor bridge integration
- Update submodule refs for Monitor and Plugin
- Mark plugin↔monitor bridge TODO items as complete in cross-project todo
- Sections 4.6, 5.1-5.4, Phase A/E bridge items all done
2026-03-22 01:37:25 +00:00
zhi
e24b317ce5 chore: mark sections 3.4, 3.5 complete; update Frontend submodule
- Section 3.4: monitor UI identifier display confirmed clean
- Section 3.5: copyable resource codes added to all detail pages
- Phase tracking items updated to reflect actual completion state
2026-03-22 00:22:44 +00:00
zhi
38884a7555 chore: mark completed TODO items (sections 2.5, 3.2, 3.3) and update submodule pointers
- Section 2.5: code-based detail endpoints confirmed complete
- Section 3.2: user/role UX alignment confirmed complete
- Section 3.3: meeting/support UI wired and complete
- Update Frontend submodule: meeting/support detail pages + routes
- Update Backend submodule: general /supports list endpoint
2026-03-22 00:18:01 +00:00
zhi
5a3edb763b chore: update submodules and mark completed TODO items
- Backend: remove legacy Python CLI, update docs
- Frontend: code-first navigation across all pages
- TODO: mark sections 2.2, 2.3, 2.6, 3.1 as completed
2026-03-21 21:38:29 +00:00
zhi
d6312c15c8 Update HarborForge.Cli release packaging status 2026-03-21 20:32:31 +00:00
zhi
d70774f325 Update Backend + Frontend submodules (code-first migration) 2026-03-21 20:28:48 +00:00
zhi
3d9ddfad00 docs: sync harbor-forge plugin planning notes 2026-03-21 19:52:09 +00:00
zhi
f0a267b6f2 Advance plugin monitor_port alignment 2026-03-21 19:23:01 +00:00
zhi
044a0a3368 feat: meetings code-based API + TODO updates
- Backend: added meetings router with code-first CRUD + attend/participant model
- TODO: mark meeting-code API and attend route as completed
2026-03-21 19:18:32 +00:00
zhi
ff47b1c971 Document HarborForge.Cli install flow 2026-03-21 18:44:26 +00:00
zhi
a111411fd1 Update support API todo progress 2026-03-21 18:17:15 +00:00
zhi
90e92da4f2 docs: update TODO - mark completed code-first API items 2026-03-21 18:12:30 +00:00
zhi
99be72d603 chore: update Backend submodule (code-first API support) 2026-03-21 18:12:11 +00:00
zhi
ace119a446 Sync CLI progress and contracts 2026-03-21 17:39:40 +00:00
zhi
41299063c8 Update HarborForge.Cli comment/worklog support 2026-03-21 17:11:30 +00:00
zhi
1cfbf03a7b Update HarborForge.Cli nested help coverage 2026-03-21 16:37:51 +00:00
zhi
c33d9e4ed3 Update HarborForge submodules for CLI and monitor work 2026-03-21 16:07:16 +00:00
zhi
55bc99c67d Update HarborForge.Cli leaf help output 2026-03-21 15:37:17 +00:00
zhi
a27428a685 chore: update submodule pointers for CLI commands, plugin rename, and monitor port
- HarborForge.Cli: meeting, support, propose, monitor command groups
- HarborForge.OpenclawPlugin: renamed to harbor-forge, removed sidecar, --install-cli
- HarborForge.Monitor: MONITOR_PORT env var and config field
2026-03-21 15:25:31 +00:00
zhi
707a0787e6 Update HarborForge.Cli role API alignment 2026-03-21 15:07:05 +00:00
zhi
5e677d77d7 chore: update HarborForge.Cli submodule (role/project/milestone/task commands) 2026-03-21 14:50:52 +00:00
zhi
72aa3dce2e Update HarborForge.Cli permission-aware help 2026-03-21 14:37:46 +00:00
zhi
daaf738c33 chore: update Backend and Cli submodule refs (dev-2026-03-21)
Backend: username-based user lookup + permission introspection endpoint
Cli: implement all user commands (list, get, create, update, activate, deactivate, delete)
2026-03-21 14:22:28 +00:00
zhi
56dc5ef3d6 docs: settle hf permission introspection strategy 2026-03-21 14:14:10 +00:00
zhi
6e531f9117 Update HarborForge.Cli help stubs 2026-03-21 14:05:59 +00:00
zhi
47260f82c2 chore: update Cli and OpenclawPlugin submodule refs (dev-2026-03-21) 2026-03-21 13:50:48 +00:00
zhi
1758db5d27 chore: update HarborForge.Cli submodule 2026-03-21 13:34:52 +00:00
zhi
8c90169289 docs: add cross-project hf implementation todo list 2026-03-21 12:07:23 +00:00
zhi
c3a61b198f docs: require code-first identifiers for hf and UI 2026-03-21 12:01:48 +00:00
zhi
b413bc119a docs: plan retirement of legacy backend python cli 2026-03-21 11:53:48 +00:00
zhi
17206e2df9 docs: define hf skill guidance for plugin install 2026-03-21 11:49:36 +00:00
zhi
b0ee1b2450 docs: gate hf skill install behind --install-cli 2026-03-21 11:48:11 +00:00
zhi
a1cbfd3053 docs: add hf plugin and monitor integration requirements 2026-03-21 11:46:00 +00:00
zhi
8086797a72 docs: expand hf CLI plan and command specification 2026-03-21 11:15:20 +00:00
zhi
fd7298e476 chore: update HarborForge.Test after frontend test runner cleanup 2026-03-21 10:11:00 +00:00
zhi
3d533186a5 chore: archive completed checklist and add CLI go plan
- archive completed ZHI_TASKS checklist
- move HarborForge CLI planning into main repository
- update backend/frontend submodules for account role changes
2026-03-21 08:44:28 +00:00
zhi
9be87fa1bd feat: add HarborForge.Cli submodule 2026-03-21 07:32:14 +00:00
zhi
7aebc86cca chore: update HarborForge.Test after propose e2e fixes 2026-03-20 11:38:13 +00:00
zhi
549b97848c chore: update HarborForge.Test submodule for frontend test defaults 2026-03-20 11:26:15 +00:00
zhi
27c2016616 chore: update HarborForge.Monitor submodule after author fix 2026-03-20 11:01:29 +00:00
zhi
1779955ba3 chore: update user management submodule refs 2026-03-20 10:56:13 +00:00
zhi
00e69bdc18 chore: update HarborForge.Monitor submodule to Docker-first runtime 2026-03-20 10:13:34 +00:00
zhi
574f2887c4 feat: add HarborForge.Monitor telemetry submodule
- add Go-based HarborForge.Monitor submodule
- update backend to store nginx telemetry fields
- update frontend to display nginx status and sites-enabled list
2026-03-20 10:04:14 +00:00
zhi
f72bfdb758 chore: update submodules to latest main
- move backend/frontend/plugin/test submodules to latest main
- include backend test repo .gitignore through HarborForge.Test
- align local workspace with merged PR state
2026-03-20 09:49:27 +00:00
76ddb9e1d0 Merge pull request 'feat: sync monitor API key integration across submodules' (#4) from feat/milestone-propose-state-machine into main
Reviewed-on: #4
2026-03-20 09:19:12 +00:00
6e77ace55e Merge branch 'main' into feat/milestone-propose-state-machine 2026-03-20 09:18:49 +00:00
zhi
db2fa7a710 chore: update monitor implementation docs and submodule refs
- Track API key-only monitor flow
- Update backend/frontend/plugin submodules to latest monitor fixes
- Include frontend API key UI branch pointer
2026-03-20 08:05:23 +00:00
zhi
0a3529a5ee chore: update OpenclawPlugin submodule with reorganized structure 2026-03-19 13:51:32 +00:00
0007a74395 Merge pull request 'feat/milestone-propose-state-machine' (#3) from feat/milestone-propose-state-machine into main
Reviewed-on: #3
2026-03-19 13:40:08 +00:00
67526ce757 Merge branch 'main' into feat/milestone-propose-state-machine 2026-03-19 13:39:57 +00:00
zhi
282029cae0 chore: update OpenclawPlugin submodule with Monitor plugin implementation 2026-03-19 13:37:25 +00:00
zhi
684e945202 chore: update Backend and Test submodules
- Backend: 67c648d (tests moved to Backend.Test)
- Test: 5a45a72 (Backend.Test with 134 tests, Frontend.Test propose tests)
2026-03-19 12:45:01 +00:00
zhi
3615197daa chore: update Backend and Test submodules with new tests
- Backend: 403d66e (8 new test files, 64 tests)
- Test: Frontend.Test propose E2E tests
2026-03-19 12:38:51 +00:00
zhi
c030077ec0 chore: update Test submodule to ba3909e (Frontend.Test task type fix) 2026-03-19 12:25:15 +00:00
zhi
03d3f9c94a chore: update Backend and Frontend submodules to main
- Backend: 0b1e47e (includes enum fix, milestone/propose state machine)
- Frontend: bdeb064 (includes modal editors, propose UI, task type fixes)
2026-03-19 12:24:07 +00:00
26be017158 Merge pull request 'feat: milestone state machine + propose flow (full stack)' (#2) from feat/milestone-propose-state-machine into main
Reviewed-on: #2
2026-03-19 11:13:57 +00:00
zhi
2b0e527982 docs(P14.3): final status review — mark all P0-P13.3 complete, update ZHI_TASKS.md 2026-03-18 06:03:54 +00:00
zhi
5f665d1501 docs: update dev status — round 29, P13.3 propose tests (19 tests, 70 total) 2026-03-18 05:02:33 +00:00
zhi
c193805b0f docs: add round 28 dev status — P13.2 task tests 34 passing 2026-03-18 04:03:05 +00:00
zhi
5ea3bdb6fd docs: add round 27 dev status — P13.1 test infrastructure + 17 milestone tests 2026-03-18 03:08:42 +00:00
zhi
faad8158ed test(P13.1): milestone state machine tests — 17 passing 2026-03-18 03:07:39 +00:00
zhi
a6721ac171 docs: add round 26 dev status — P12.2-P12.3 documentation complete 2026-03-18 02:02:38 +00:00
zhi
90e1b4dfb0 docs(P12.2-P12.3): add state machine overview, permissions overview, and propose flow documentation 2026-03-18 02:02:08 +00:00
zhi
be82ea25cd docs: add round 25 dev status — batch transition P5.2-P5.6 sync 2026-03-18 01:02:27 +00:00
zhi
e09552b314 docs: dev status round 24 — P12.1 CLI propose commands + task_type cleanup 2026-03-18 00:02:22 +00:00
zhi
98c9eb83a8 feat(P12.1): CLI updates — propose commands, milestone status filter, task_type cleanup 2026-03-18 00:01:56 +00:00
zhi
e27adf9a4d round-23: clean TaskType.TASK residual + P3.6 feature story freeze edit lock 2026-03-17 23:02:20 +00:00
zhi
7236c4e90c docs: dev status round 21 — P2.2 default role seeds 2026-03-17 19:03:12 +00:00
zhi
19eba0b951 docs: round 20 status — P4.3 task dependency check wired into pending→open 2026-03-17 18:02:32 +00:00
zhi
1cebd63e06 Dev status: round 19 — P4.1 dependency check helper 2026-03-17 17:04:09 +00:00
zhi
0bc2379d18 Update backend submodule: P4.1 dependency check helper 2026-03-17 17:03:49 +00:00
zhi
0005134d77 docs: dev status round 17 — P2.1 permission registration 2026-03-17 15:04:50 +00:00
zhi
054cf43853 ref: update backend submodule for P2.1 permission registration 2026-03-17 15:04:17 +00:00
zhi
65b76dfb06 docs: update dev status — round 16, P10.7 propose edit 2026-03-17 14:06:21 +00:00
zhi
6441ea5ef6 ref: update submodules for P9.6 task creation restrictions 2026-03-17 13:02:50 +00:00
zhi
92c0c09df7 docs: dev status round 14 — P5.7 task edit restrictions 2026-03-17 12:04:59 +00:00
zhi
c3b59f7c91 docs: dev status round 13 — P5.3 assignee identity + P5.4 completion comment 2026-03-17 11:02:47 +00:00
zhi
0df2cfc0a9 docs: dev status round 11 — P3.6 milestone edit restrictions 2026-03-17 09:02:09 +00:00
zhi
6b265ea88d update submodules: P3.6 milestone edit restrictions 2026-03-17 09:01:43 +00:00
zhi
2fee85fdfb docs: round 9 status update 2026-03-17 07:10:33 +00:00
zhi
cc2086e941 Update frontend submodule: P9.2 task action buttons 2026-03-17 07:07:41 +00:00
zhi
63ba441f06 docs: update dev status — round 7 propose frontend pages 2026-03-17 05:04:16 +00:00
zhi
d4f95c56e2 docs: update dev status log for round 5 - propose CRUD router 2026-03-17 03:02:29 +00:00
zhi
5602b1b107 feat: propose CRUD router + accept/reject/reopen actions (P6.1-P6.4, backend submodule) 2026-03-17 03:01:56 +00:00
zhi
6b73604b96 docs: update dev status log for round 4 - propose model + DB migration 2026-03-17 02:05:25 +00:00
zhi
7afa8cda10 feat: propose model + DB migration scripts (backend submodule) 2026-03-17 02:04:47 +00:00
zhi
16531f6c98 docs: update dev status log for round 3 - frontend enum sync 2026-03-17 01:05:28 +00:00
zhi
7ba5d95201 docs: add dev status round 2 - enum replacement complete 2026-03-17 00:04:59 +00:00
zhi
569e0e50e0 docs: add milestone propose planning notes 2026-03-16 23:36:49 +00:00
74f1ffff7d Merge pull request 'chore: update modal-editor submodule refs' (#1) from feat/modal-edit-permissions-20260316 into main
Reviewed-on: #1
2026-03-16 19:45:04 +00:00
zhi
4a872722b2 chore: update modal editor submodules 2026-03-16 18:13:54 +00:00
zhi
752d9feba8 chore: update task modal and frontend test submodules 2026-03-16 16:32:37 +00:00
30 changed files with 6723 additions and 4 deletions

8
.gitmodules vendored
View File

@@ -16,3 +16,11 @@
[submodule "AbstractWizard"]
path = AbstractWizard
url = https://git.hangman-lab.top/nav/AbstractWizard.git
[submodule "HarborForge.Monitor"]
path = HarborForge.Monitor
url = https://git.hangman-lab.top/zhi/HarborForge.Monitor.git
branch = main
[submodule "HarborForge.Cli"]
path = HarborForge.Cli
url = https://git.hangman-lab.top/zhi/HarborForge.Cli.git
branch = main

1
HarborForge.Cli Submodule

Submodule HarborForge.Cli added at cd22642472

1
HarborForge.Monitor Submodule

Submodule HarborForge.Monitor added at 758d3d1c59

View File

@@ -0,0 +1,656 @@
# HarborForge 开发计划
**版本**: 0.3.0
**日期**: 2026-03-19
**状态**: 开发中
---
## 1. 项目概述
HarborForge 是一个 **AI Agent 与人类协同的任务管理平台**,用于管理项目、里程碑、任务和提案(Propose)。
### 核心特性
- 项目驱动的任务管理
- 里程碑(Milestone)状态机管理
- 任务(Task)状态机管理
- 提案(Propose)工作流
- 角色权限系统(RBAC)
- 服务器监控集成
- Webhook 扩展能力
- OpenClaw 插件生态
---
## 2. 系统架构
### 2.1 整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 客户端层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Web Frontend │ │ OpenClaw CLI │ │ OpenClaw Plugin │ │
│ │ (React/Vite) │ │ │ │ (Server Monitor) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
└─────────┼─────────────────┼─────────────────────┼──────────────┘
│ │ │
└─────────────────┼─────────────────────┘
│ HTTP/WebSocket
┌───────────────────────────▼─────────────────────────────────────┐
│ HarborForge.Backend │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ FastAPI + SQLAlchemy + MySQL │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Projects│ │Milestones│ │ Tasks │ │Proposes │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Auth │ │ RBAC │ │ Monitor │ │ Webhooks│ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
└──────────────────────────────────────────────────────┐
┌────────────────────────────────────────────────────────────────▼┐
│ 外部集成 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ LLM Providers│ │ Keycloak │ │ AbstractWizard │ │
│ │ (Claude/etc) │ │ (Auth) │ │ (Config Management) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 2.2 模块划分
| 模块 | 技术栈 | 职责 |
|------|--------|------|
| **Backend** | FastAPI + SQLAlchemy + MySQL | REST API + WebSocket业务逻辑 |
| **Frontend** | React + Vite + TypeScript | 用户界面,管理后台 |
| **OpenclawPlugin** | Node.js + TypeScript | OpenClaw 集成,服务器监控 |
| **Backend.Test** | pytest | 独立测试套件 |
| **Frontend.Test** | Playwright | E2E 测试 |
---
## 3. 数据模型
### 3.1 核心实体关系
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Project │◄────┤ Milestone │◄────┤ Task │
│ │ │ │ │ │
│ - id │ │ - id │ │ - id │
│ - name │ │ - title │ │ - title │
│ - owner_id │ │ - status │ │ - status │
│ - project_code│ │ - project_id│ │ - type │
└──────┬──────┘ └─────────────┘ └──────┬──────┘
│ │
│ ┌─────────────┐ │
└────────►│ Propose │◄─────────────┘
│ │
│ - id │
│ - title │
│ - status │
│ - feat_task_id (accept时创建)
└─────────────┘
```
### 3.2 状态机定义
#### Milestone 状态
```
open ──freeze──► freeze ──start──► undergoing ──close──► closed
│ │
│ └──auto-complete──► completed
└──────────────────────────────────────────────────► closed
```
#### Task 状态
```
open ──assign+start──► undergoing ──finish+comment──► completed ──close──► closed
│ │
│ └──reopen──► open
└──pending──► undergoing ──(同上)
```
#### Propose 状态
```
open ──accept──► accepted (创建 feature story task)
└──reject──► rejected ──reopen──► open
```
---
## 4. API 接口设计
### 4.1 认证接口
```yaml
POST /auth/token
# JWT 登录
Body: { username: string, password: string }
Response: { access_token: string, token_type: "bearer" }
GET /users/me
# 获取当前用户信息
Headers: Authorization: Bearer {token}
```
### 4.2 项目接口
```yaml
GET /projects
# 列表(支持分页)
Query: { page: int, page_size: int }
POST /projects
# 创建
Body: { name: string, description?: string, project_code?: string }
GET /projects/{id}
# 详情
PATCH /projects/{id}
# 更新
DELETE /projects/{id}
# 删除(需确认)
```
### 4.3 里程碑接口
```yaml
GET /projects/{project_id}/milestones
# 列表
Query: { status: "open|freeze|undergoing|completed|closed" }
POST /projects/{project_id}/milestones
# 创建
Body: { title: string, description?: string, due_date?: datetime }
GET /projects/{project_id}/milestones/{id}
# 详情
PATCH /projects/{project_id}/milestones/{id}
# 更新(仅在 open 状态允许修改大部分字段)
DELETE /projects/{project_id}/milestones/{id}
# 删除
# 状态机动作
POST /projects/{project_id}/milestones/{id}/freeze
POST /projects/{project_id}/milestones/{id}/start
POST /projects/{project_id}/milestones/{id}/close
# 预检接口
GET /projects/{project_id}/milestones/{id}/preflight
# 返回 { can_freeze: bool, can_start: bool, reasons: [...] }
```
### 4.4 任务接口
```yaml
GET /projects/{project_id}/tasks
# 列表
Query: {
status: "open|pending|undergoing|completed|closed",
assignee_id: int,
milestone_id: int,
task_type: "issue|story|test|..."
}
POST /projects/{project_id}/tasks
# 创建
Body: {
title: string,
milestone_id: int,
task_type: "issue|story|test|maintenance|research|review|resolution",
priority: "low|medium|high|critical",
assignee_id?: int
}
GET /projects/{project_id}/tasks/{id}
# 详情(包含 comments
PATCH /projects/{project_id}/tasks/{id}
# 更新
# 注意undergoing/completed/closed 状态限制 body 编辑
DELETE /projects/{project_id}/tasks/{id}
# 删除
# 状态机动作
POST /projects/{project_id}/tasks/{id}/transition
Body: {
action: "open|start|finish|close|reopen",
comment?: string, # finish 时必填
close_reason?: string # close 时可选
}
```
### 4.5 Propose 接口
```yaml
GET /projects/{project_id}/proposes
# 列表
POST /projects/{project_id}/proposes
# 创建
Body: { title: string, description?: string }
GET /projects/{project_id}/proposes/{id}
# 详情
PATCH /projects/{project_id}/proposes/{id}
# 更新(仅在 open 状态允许)
# 状态机动作
POST /projects/{project_id}/proposes/{id}/accept
Body: { milestone_id: int } # 指定 milestone 创建 feature story task
POST /projects/{project_id}/proposes/{id}/reject
POST /projects/{project_id}/proposes/{id}/reopen
# rejected -> open
```
### 4.6 监控接口
```yaml
GET /monitor/public/overview
# 公开概览数据
# 管理接口
GET /monitor/admin/servers
POST /monitor/admin/servers
DELETE /monitor/admin/servers/{id}
POST /monitor/admin/servers/{id}/api-key
DELETE /monitor/admin/servers/{id}/api-key
# 服务器上报(插件调用)
POST /monitor/server/heartbeat-v2
Headers:
X-API-Key: string
Body:
identifier: string
openclaw_version: string # 远程主机上的 OpenClaw 版本
plugin_version: string # harbor-forge 插件版本
cpu_pct: float
mem_pct: float
disk_pct: float
swap_pct: float
load_avg: [float, float, float]
uptime_seconds: int
agents: [...]
```
### 4.7 其他接口
```yaml
# 评论
GET /projects/{project_id}/tasks/{task_id}/comments
POST /projects/{project_id}/tasks/{task_id}/comments
# 角色权限
GET /roles
GET /roles/{id}
POST /roles
PATCH /roles/{id}
DELETE /roles/{id}
# Webhook
GET /webhooks
POST /webhooks
DELETE /webhooks/{id}
# Dashboard
GET /dashboard/stats?project_id={id}
# 健康检查
GET /health
GET /version
```
---
## 5. 安全设计
### 5.1 认证
- **JWT Token**: 基于 `python-jose`,有效期 configurable
- **API Key**: 支持服务间调用
- **Admin 权限**: `users.is_admin` 字段控制
### 5.2 项目权限 (RBAC)
| 角色 | 权限范围 |
|------|----------|
| admin | 全局所有操作 |
| owner | 项目内所有操作 |
| mgr | 里程碑/任务管理,接受/拒绝 propose |
| dev | 任务操作,创建 propose |
| guest | 只读访问 |
### 5.3 监控插件安全
```
1. 服务器注册
2. 管理员生成 API Key
3. 插件将 API Key 写入 OpenClaw plugin config
4. sidecar 通过 X-API-Key 调用 /monitor/server/heartbeat-v2
5. 服务端按 API Key 识别并接收遥测
```
---
## 6. 开发里程碑
### P0 - 基础框架 ✅
- [x] 项目初始化 (FastAPI + SQLAlchemy)
- [x] 用户认证 (JWT)
- [x] Docker Compose 部署
### P1 - 核心 CRUD ✅
- [x] Projects CRUD
- [x] Milestones CRUD
- [x] Tasks CRUD
- [x] Comments
### P2 - 权限系统 ✅
- [x] Role/Permission 模型
- [x] RBAC 中间件
- [x] 项目成员管理
### P3 - 里程碑状态机 ✅
- [x] freeze/start/close 动作
- [x] 自动完成钩子
- [x] 编辑限制
### P4 - 任务依赖 ✅
- [x] depend_on 字段
- [x] 依赖检查工具
- [x] 批量操作
### P5 - 任务状态机 ✅
- [x] open/start/finish/close/reopen
- [x] 负责人检查
- [x] 完成时必须评论
- [x] 编辑限制
### P6 - Propose 系统 ✅
- [x] Propose CRUD
- [x] accept/reject/reopen
- [x] accept 时创建 feature story task
### P7 - 任务类型重构 ✅
- [x] 移除 task 类型
- [x] issue 作为默认
- [x] 前端同步更新
### P8 - 里程碑预检 ✅
- [x] preflight 接口
- [x] 前端按钮状态
### P9 - 任务操作 UI ✅
- [x] 操作按钮
- [x] 完成评论弹窗
- [x] 关闭原因弹窗
### P10 - Propose UI ✅
- [x] Propose 列表页
- [x] Propose 详情页
- [x] 编辑弹窗(仅 open 状态)
### P11 - 监控后端 ✅
- [x] Provider 账户管理
- [x] 服务器注册/挑战
- [x] 心跳接收
- [x] WebSocket 支持
### P12 - CLI 工具 ✅
- [x] 命令行交互
- [x] Webhook 管理
- [x] 配置查看
### P13 - 测试 ✅
- [x] Backend 单元测试 (pytest)
- [x] 里程碑状态机测试
- [x] 任务状态机测试
- [x] Propose 测试
- [x] Frontend E2E 测试
### P14 - OpenClaw 集成 🔄
- [x] Plugin 架构设计
- [x] 遥测服务器
- [x] 安装脚本
- [ ] 完整测试
### P15 - 文档与发布 📋
- [ ] API 文档 (OpenAPI)
- [ ] 部署文档
- [ ] 用户手册
- [ ] v1.0 发布
---
## 7. 远程服务器通信协议
### 7.1 注册流程
```mermaid
sequenceDiagram
participant Admin
participant Monitor
participant Server
participant Plugin
Admin->>Monitor: POST /admin/servers
Monitor->>Admin: { challenge_uuid, expires_at }
Admin->>Server: 配置 challenge_uuid
Plugin->>Monitor: GET /public/server-public-key
Monitor->>Plugin: { public_key_pem, key_id }
Plugin->>Plugin: 加密 payload
Note right of Plugin: RSA-OAEP + SHA256
Plugin->>Monitor: POST /server/heartbeat
Note right of Plugin: 或 WS /server/ws
Monitor->>Monitor: 验证 challenge_uuid
Monitor->>Monitor: 验证 timestamp (防重放)
Monitor->>Monitor: 存储 server_state
```
### 7.2 心跳协议
**HTTP Heartbeat:**
```http
POST /monitor/server/heartbeat
Content-Type: application/json
X-Server-Identifier: vps.t1
X-Challenge-UUID: abc-123-def
{
"identifier": "vps.t1",
"challenge_uuid": "abc-123-def",
"timestamp": "2026-03-19T14:00:00Z",
"cpu_pct": 12.5,
"mem_pct": 41.2,
"disk_pct": 62.0,
"swap_pct": 0.0,
"uptime_sec": 86400,
"load_avg_1m": 0.5,
"platform": "linux",
"hostname": "vps.t1",
"openclaw_version": "1.2.3",
"openclaw_agent_count": 3,
"openclaw_agents": [
{ "id": "dev", "name": "Developer", "status": "running" }
]
}
```
**WebSocket 连接:**
```javascript
// 1. 建立连接
const ws = new WebSocket('wss://monitor.example.com/monitor/server/ws');
// 2. 发送加密握手
ws.send(JSON.stringify({
encrypted_payload: "base64_encoded_rsa_encrypted_json"
}));
// 3. 接收确认
// Server: { "status": "authenticated" }
// 4. 定期发送遥测
setInterval(() => {
ws.send(JSON.stringify({
type: "telemetry",
data: { /* 同上 */ }
}));
}, 30000);
```
### 7.3 加密格式
```python
# Payload 结构 (加密前)
{
"identifier": "vps.t1",
"challenge_uuid": "uuid-from-admin",
"nonce": "random-128bit-hex", # 防重放
"ts": "2026-03-19T14:00:00Z" # UTC ISO860110分钟有效期
}
# 加密
encrypted = RSA_OAEP_SHA256_encrypt(
plaintext=json.dumps(payload),
public_key=monitor_public_key
)
# 传输 (base64)
encrypted_payload_b64 = base64.b64encode(encrypted).decode()
```
---
## 8. 技术规范
### 8.1 代码规范
- **Backend**: PEP8, Black formatter, mypy type hints
- **Frontend**: ESLint, Prettier, strict TypeScript
- **Commits**: Conventional Commits (`feat:`, `fix:`, `test:`, `docs:`)
### 8.2 数据库规范
- 所有表必须有 `id` (PK, auto_increment)
- 时间字段使用 `DateTime(timezone=True)`
- 枚举使用 SQLAlchemy `Enum` + `values_callable`
- 外键必须建索引
### 8.3 API 规范
- RESTful 设计
- 统一响应格式: `{ data: ..., error?: ..., message?: ... }`
- HTTP 状态码规范使用
- 分页: `{ items: [...], total: N, page: 1, page_size: 20 }`
### 8.4 测试规范
- 测试覆盖率 > 80%
- 单元测试: SQLite in-memory
- E2E 测试: 独立 Docker 环境
- CI: GitHub Actions / Gitea Actions
---
## 9. 部署架构
### 9.1 生产环境
```yaml
# docker-compose.prod.yml
services:
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./HarborForge.Backend
environment:
- DATABASE_URL=mysql+pymysql://...
- SECRET_KEY=${SECRET_KEY}
frontend:
build: ./HarborForge.Frontend
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
```
### 9.2 监控插件部署
```bash
# 1. 在 Monitor 注册服务器并生成 API Key
# 2. 在服务器安装插件
node scripts/install.mjs
# 3. 配置 ~/.openclaw/openclaw.json
{
"plugins": {
"entries": {
"harbor-forge": {
"enabled": true,
"config": {
"enabled": true,
"apiKey": "YOUR_API_KEY",
"monitor_port": 9100
}
}
}
}
}
# 4. 重启 Gateway
openclaw gateway restart
```
---
## 10. 参考资源
### 代码仓库
- `HarborForge.Backend` - FastAPI 后端
- `HarborForge.Frontend` - React 前端
- `HarborForge.Test` - 测试套件
- `HarborForge.OpenclawPlugin` - OpenClaw 插件
### 关键文件
- `app/models/` - SQLAlchemy 模型
- `app/api/routers/` - API 路由
- `app/schemas/schemas.py` - Pydantic 模型
- `app/services/` - 业务逻辑
- `tests/` - 测试文件
### 外部依赖
- FastAPI 0.109
- SQLAlchemy 2.0
- React 18 + Vite 5
- OpenClaw Gateway
---
**文档版本**: 0.3.0
**最后更新**: 2026-03-19
**维护者**: HarborForge Team

View File

@@ -0,0 +1,77 @@
# OpenClaw Plugin 开发计划(当前版)
**状态**: API Key 方案已落地challenge / WebSocket 旧方案已废弃。
## 当前架构
- HarborForge Monitor Backend 提供服务器注册与遥测接收接口
- OpenClaw Gateway 加载 `harbor-forge` 插件
- 旧 sidecar (`server/telemetry.mjs`) 已移除
- 插件通过 Gateway/runtime 路径直接提供 OpenClaw 元数据
- Monitor 可选通过本地 `monitor_port` 桥接读取补充信息
## 当前后端接口
### 公开接口
- `GET /monitor/public/overview`
### 管理接口
- `GET /monitor/admin/servers`
- `POST /monitor/admin/servers`
- `DELETE /monitor/admin/servers/{id}`
- `POST /monitor/admin/servers/{id}/api-key`
- `DELETE /monitor/admin/servers/{id}/api-key`
### 插件上报接口
- `POST /monitor/server/heartbeat-v2`
- Header: `X-API-Key`
- Body:
- `identifier`
- `openclaw_version`
- `plugin_version`
- `agents`
- `cpu_pct`
- `mem_pct`
- `disk_pct`
- `swap_pct`
- `load_avg`
- `uptime_seconds`
## 数据语义
- `openclaw_version`: 远程服务器上的 OpenClaw 版本
- `plugin_version`: 远程服务器上的 `harbor-forge` 插件版本
## 已废弃内容
以下旧方案已经废弃,不再作为实现路径:
- challenge UUID
- `GET /monitor/public/server-public-key`
- `POST /monitor/admin/servers/{id}/challenge`
- `WS /monitor/server/ws`
- challenge / nonce 握手逻辑
## 前端管理页要求
Monitor 管理页应提供:
- Add Server
- Generate API Key
- Revoke API Key
- Delete Server
不再提供 `Generate Challenge`
## 运行流程
1. 管理员在 Monitor 中注册服务器
2. 管理员为服务器生成 API Key
3. 将 API Key 写入 `~/.openclaw/openclaw.json`
4. 如需本地桥接补充信息,配置 `monitor_port`
5. 重启 OpenClaw Gateway
6. 插件直接参与遥测链路;若本地桥接可达,则额外提供 OpenClaw 补充元数据
## 备注
当前保留了对旧 challenge 数据表的**删除兼容清理**(仅为兼容老数据库中的遗留数据),但不再保留 challenge 功能入口、WebSocket 方案或 sidecar 运行时逻辑。

View File

@@ -0,0 +1,5 @@
{
"wakeCount": 4,
"createdAt": "2026-03-21T12:25:00Z",
"updatedAt": "2026-03-21T13:29:00Z"
}

View File

@@ -0,0 +1,54 @@
你是 developer agent 的一个 15 分钟编排 cron 任务。
请在每次被唤醒时,维护并读取下面这个状态文件:
`/root/.openclaw/workspace/workspace-developer/HarborForge/plans/automation/cron/hf-bootstrap-2026-03-21-state.json`
规则:
1. 读取 `wakeCount`
2. 将其 +1 并写回文件。
3. 根据新的 wakeCount 执行对应动作。
4. 每次执行结束后,向 Discord 频道 `1474327736242798612` announce 汇报执行结果。
动作定义:
## 第 1 次唤醒
执行:
- 把 HarborForge 主仓和所有子模块从 `main` 拉取最新代码
- 给所有子模块创建开发分支:`dev-2026-03-21`
- 如分支已存在,则切换到该分支并确保它基于最新 main
## 第 2 次唤醒
执行:
- 创建第二个 cron 定时任务:`hf-dev-kimi-2026-03-21`
- 频率:每 30 分钟一次
- agent`developer`
- model`kimi-coding/k2p5`
- session`isolated`
- announce开启
- channel`discord`
- to`1474327736242798612`
- message 内容使用文件:
`/root/.openclaw/workspace/workspace-developer/HarborForge/plans/automation/cron/hf-dev-kimi-2026-03-21.prompt.md`
- 如果同名任务已存在,则不要重复创建
## 第 3 次唤醒
执行:
- 创建第三个 cron 定时任务:`hf-dev-opus-2026-03-21`
- 频率:每 30 分钟一次
- agent`developer`
- model`anthropic/claude-opus-4-6`
- 其余参数与第二个任务完全一致
- message 内容使用文件:
`/root/.openclaw/workspace/workspace-developer/HarborForge/plans/automation/cron/hf-dev-opus-2026-03-21.prompt.md`
- 如果同名任务已存在,则不要重复创建
## 第 4 次唤醒
执行:
- 删除你自己这个 cron 定时任务
- 先通过 `openclaw cron list --json` 找到名称为 `hf-bootstrap-2026-03-21` 的 job id
- 然后执行 `openclaw cron remove <jobId>`
额外要求:
- 执行中可以使用 shell / openclaw CLI 完成 cron 管理
- 如果某一步失败,要在 announce 中说明失败原因
- 不要跳步;严格按 wakeCount 对应动作执行

View File

@@ -0,0 +1,25 @@
你是 developer agent 的一个 cron 定时开发任务。
目标:参考 HarborForge 主仓中的开发计划与 TODO list寻找当前可以推进的任务并进行开发。
严格要求:
1. 工作目录以 `/root/.openclaw/workspace/workspace-developer/HarborForge` 为主。
2. 优先参考:
- `plans/harborforge-cli-go-plan.md`
- `plans/hf-cross-project-todo.md`
3. 只做当前明确可推进的任务,不要凭空发散。
4. 无需做 Test 子模块下的复杂测试。
5. 尤其禁止运行:`run-test-frontend`
6. 可以做轻量验证例如编译、lint、py_compile、类型检查、局部单测、静态检查等。
7. 每次完成后,把所有脏模块分别提交并 push 到分支:`dev-2026-03-21`
8. 如果发现 todo list 中所有待办都已完成,则删除你自己这个 cron 定时任务。
- 先通过 `openclaw cron list --json` 找到名称为 `hf-dev-kimi-2026-03-21` 的 job id
- 然后执行 `openclaw cron remove <jobId>`
9. 每次运行结束前,给 Discord 频道 `1474327736242798612` 做 announce 汇报。
建议汇报内容:
- 本次选择的 TODO
- 修改了哪些子模块
- 做了哪些轻量验证
- push 了哪些分支/提交
- 是否发现阻塞

View File

@@ -0,0 +1,25 @@
你是 developer agent 的一个 cron 定时开发任务。
目标:参考 HarborForge 主仓中的开发计划与 TODO list寻找当前可以推进的任务并进行开发。
严格要求:
1. 工作目录以 `/root/.openclaw/workspace/workspace-developer/HarborForge` 为主。
2. 优先参考:
- `plans/harborforge-cli-go-plan.md`
- `plans/hf-cross-project-todo.md`
3. 只做当前明确可推进的任务,不要凭空发散。
4. 无需做 Test 子模块下的复杂测试。
5. 尤其禁止运行:`run-test-frontend`
6. 可以做轻量验证例如编译、lint、py_compile、类型检查、局部单测、静态检查等。
7. 每次完成后,把所有脏模块分别提交并 push 到分支:`dev-2026-03-21`
8. 如果发现 todo list 中所有待办都已完成,则删除你自己这个 cron 定时任务。
- 先通过 `openclaw cron list --json` 找到名称为 `hf-dev-opus-2026-03-21` 的 job id
- 然后执行 `openclaw cron remove <jobId>`
9. 每次运行结束前,给 Discord 频道 `1474327736242798612` 做 announce 汇报。
建议汇报内容:
- 本次选择的 TODO
- 修改了哪些子模块
- 做了哪些轻量验证
- push 了哪些分支/提交
- 是否发现阻塞

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,430 @@
# hf / HarborForge Cross-Project TODO
> Scope: HarborForge.Cli, HarborForge.Backend, HarborForge.Frontend, HarborForge.OpenclawPlugin, HarborForge.Monitor, HarborForge.Test
>
> Goal: land the new `hf` CLI and the supporting backend/frontend/plugin/monitor changes described in the main CLI plan.
---
## 0. Cross-cutting / coordination
- [x] Finalize MVP scope for first shipping version of `hf`
- MVP includes: all CRUD commands for users, roles, projects, milestones, tasks, meetings, support, proposals, monitor
- Permission-aware help system, padded-cell/manual mode, code-first resource addressing
- Plugin installer `--install-cli` for automated deployment
- [x] Confirm which existing backend routes can be reused vs which new routes are needed
- [x] Define canonical code-first lookup policy across all resources
- [x] Define permission introspection strategy for `--help` / `--help-brief`
- settled as: token → current user → user role → role permissions
- `hf user create` remains a special account-manager-token flow and is not gated by ordinary user-token write permission
- [x] Define JSON output contract for CLI list/get commands
- current CLI contract: `--json` emits raw success payloads on stdout without a universal envelope; list/get responses should preserve canonical code-bearing fields when backend payloads provide them
- [x] Define CLI exit code / stderr conventions
- current CLI contract: success exits `0`; validation/runtime failures exit `1`; errors go to stderr and successful output goes to stdout
- [x] Define local plugin↔monitor communication protocol over `monitor_port`
- Monitor exposes `GET /health`, `GET /telemetry`, `POST /openclaw` on 127.0.0.1:MONITOR_PORT
- Plugin pushes OpenClaw metadata via POST /openclaw; Monitor enriches heartbeats with received data
- All communication is optional/degradable — both sides function independently
- [x] Define release order across submodules
- 1. Backend (code-first APIs, permission introspection)
- 2. CLI (depends on backend API surface)
- 3. Frontend (code-first UI, independent of CLI)
- 4. Monitor (standalone, bridge is optional)
- 5. Plugin (depends on CLI build for --install-cli, depends on Monitor for bridge)
- [x] Define rollback strategy if plugin / monitor bridge is unavailable
- Graceful degradation: Monitor operates normally without plugin data
- Plugin operates normally without Monitor bridge
- No hard dependency in either direction — bridge is optional enrichment
> Note: the CLI contract items above are now documented from the currently implemented `HarborForge.Cli` behavior; they can still be refined later if a stricter release contract is needed.
---
## 1. HarborForge.Cli
### 1.1 Go project scaffold
- [x] Initialize Go module for `hf`
- [x] Add binary entrypoint (`cmd/hf/main.go` or equivalent)
- [x] Add internal package layout (`config`, `help`, `mode`, `passmgr`, `client`, `commands`)
- [x] Add build instructions to `README.md`
- [x] Add `.gitignore` for Go artifacts
- [x] Add repo-config-safe contribution note if needed
- CLI README already contains build/run/install docs; no separate contribution note needed for current scope
### 1.2 Runtime mode detection
- [x] Implement `which pass_mgr` detection on startup
- [x] Add runtime mode enum: padded-cell mode / manual mode
- [x] Block manual credential flags in padded-cell mode
- [x] Return exact error when forbidden manual token flags are used:
- [x] `padded-cell installed, --token flag disabled, use command directly`
- [x] Define equivalent handling for `--acc-mgr-token` and related manual secret flags
### 1.3 Config handling
- [x] Resolve binary directory correctly at runtime
- [x] Read `<binary-dir>/.hf-config.json`
- [x] Write/update `base-url` via `hf config --url`
- [x] Add config validation for malformed/missing config
- [x] Add `hf config --acc-mgr-token`
- [x] Implement `pass_mgr set --public --key hf-acc-mgr-token --secret <token>`
- [x] Return exact error on failure:
- [x] `--acc-mgr-token can only be set with padded-cell plugin`
### 1.4 Help system
- [x] Implement `hf --help`
- [x] Implement `hf --help-brief`
- [x] Implement `<group> --help`
- [x] Implement `<group> --help-brief`
- [x] Implement leaf command `--help`
- [x] Implement leaf command `--help-brief`
- [x] Show all subcommands in normal help, marking unavailable ones as `(not permitted)`
- [x] Hide unavailable commands entirely in `--help-brief`
- [x] Ensure leaf `--help` for unavailable commands only prints `not permitted`
- [x] Hide manual auth flags from help in padded-cell mode
- [x] Show required manual auth flags in help in manual mode
- [x] Handle special help behavior for `hf user create`
### 1.5 Auth/token resolution layer
- [x] Implement shared normal token resolution helper
- [x] In padded-cell mode, resolve via `pass_mgr get-secret --key hf-token`
- [x] In manual mode, require explicit `--token`
- [x] Emit exact error on missing manual token:
- [x] `--token <token> required or execute this with pcexec`
- [x] Ensure `hf --help` never requires token
- [x] Ensure subcommand help can render even when token is unavailable
### 1.6 Output model
- [x] Add default human-readable output mode
- [x] Add `--json` output mode
- [x] Ensure list outputs include canonical resource code fields
- [x] Ensure machine-readable output is stable enough for agent use
### 1.7 Base commands
- [x] Implement `hf version`
- [x] Implement `hf health`
### 1.8 User commands
- [x] Implement `hf user create`
- [x] Forbid `--token` on `hf user create`
- [x] Do not support `--role` on `hf user create`
- [x] Default created accounts to `guest`
- [x] In padded-cell mode, auto-generate password with:
- [x] `pass_mgr generate --key hf --username <username>`
- [x] In padded-cell mode, auto-fetch account-manager token with:
- [x] `pass_mgr get-secret --public --key hf-acc-mgr-token`
- [x] Emit exact missing-password error:
- [x] `--pass <password> required or execute with pcexec`
- [x] Emit exact missing-account-manager-token error:
- [x] `--acc-mgr-token <token> required or execute with pcexec`
- [x] Implement `hf user list`
- [x] Implement `hf user get <username>`
- [x] Implement `hf user update <username>`
- [x] Implement `hf user activate <username>`
- [x] Implement `hf user deactivate <username>`
- [x] Implement `hf user delete <username>`
### 1.9 Role / permission commands
- [x] Implement `hf role list`
- [x] Implement `hf role get <role-name>`
- [x] Implement `hf role create`
- [x] Implement `hf role update`
- [x] Implement `hf role delete`
- [x] Implement `hf permission list`
- [x] Implement `hf role set-permissions`
- [x] Implement `hf role add-permissions`
- [x] Implement `hf role remove-permissions`
### 1.10 Project / milestone commands
- [x] Implement `hf project list`
- [x] Implement `hf project get <project-code>`
- [x] Implement `hf project create`
- [x] Implement `hf project update <project-code>`
- [x] Implement `hf project delete <project-code>`
- [x] Implement `hf project members <project-code>`
- [x] Implement `hf project add-member <project-code>`
- [x] Implement `hf project remove-member <project-code>`
- [x] Implement `hf milestone list --project <project-code>`
- [x] Implement `hf milestone get <milestone-code>`
- [x] Implement `hf milestone create`
- [x] Implement `hf milestone update <milestone-code>`
- [x] Implement `hf milestone delete <milestone-code>`
- [x] Implement `hf milestone progress <milestone-code>`
### 1.11 Task commands
- [x] Implement `hf task list`
- [x] Add filters:
- [x] `--project <project-code>`
- [x] `--milestone <milestone-code>`
- [x] `--status <status>`
- [x] `--taken-by <me|null|username>`
- [x] `--due-today <true|false>`
- [x] repeated `--order-by <due-date|priority|created|name>`
- [x] Implement `hf task get <task-code>`
- [x] Implement `hf task create`
- [x] Implement `hf task update <task-code>`
- [x] Implement `hf task transition <task-code> <status>`
- [x] Implement `hf task take <task-code>`
- [x] Return clear error when task is already taken by someone else
- [x] Return clear error when caller lacks permission to take task
- [x] Implement `hf task delete <task-code>`
- [x] Implement `hf task search`
### 1.12 Meeting commands
- [x] Implement `hf meeting list`
- [x] Implement `hf meeting get <meeting-code>`
- [x] Implement `hf meeting create`
- [x] Implement `hf meeting update <meeting-code>`
- [x] Implement `hf meeting attend <meeting-code>`
- [x] Ensure attend adds caller to participant list
- [x] Implement `hf meeting delete <meeting-code>`
### 1.13 Support commands
- [x] Implement `hf support list`
- [x] Implement `hf support get <support-code>`
- [x] Implement `hf support create`
- [x] Implement `hf support update <support-code>`
- [x] Implement `hf support take <support-code>`
- [x] Implement `hf support transition <support-code> <status>`
- [x] Implement `hf support delete <support-code>`
### 1.14 Propose commands
- [x] Implement `hf propose list --project <project-code>`
- [x] Implement `hf propose get <propose-code>`
- [x] Implement `hf propose create`
- [x] Implement `hf propose update <propose-code>`
- [x] Implement `hf propose accept <propose-code> --milestone <milestone-code>`
- [x] Implement `hf propose reject <propose-code>`
- [x] Implement `hf propose reopen <propose-code>`
### 1.15 Monitor commands
- [x] Implement `hf monitor overview`
- [x] Implement `hf monitor server list`
- [x] Implement `hf monitor server get <identifier>`
- [x] Implement `hf monitor server create --identifier <identifier>`
- [x] Implement `hf monitor server delete <identifier>`
- [x] Implement `hf monitor api-key generate <identifier>`
- [x] Implement `hf monitor api-key revoke <identifier>`
### 1.16 CLI packaging / release
- [x] Add cross-platform build targets if needed
- [x] Add release artifact naming for `hf`
- [x] Add install documentation
- [x] Add shell examples for padded-cell and manual mode
---
## 2. HarborForge.Backend
### 2.1 Code-first API support
- [x] Audit all CLI-targeted resources for code availability
- [x] Ensure `project-code` is accepted in get/update/delete/member APIs
- [x] Ensure `milestone-code` is accepted in get/update/delete/progress APIs
- [x] Ensure `task-code` is accepted in get/update/delete/transition APIs
- [x] Ensure `meeting-code` is accepted in get/update/delete/attend APIs
- [x] Ensure `support-code` is accepted in get/update/delete/take/transition APIs
- [x] Ensure `propose-code` is accepted in get/update/delete/accept/reject/reopen APIs
- [x] Add code-based list filters where missing
- [x] Ensure CLI-related list payloads always include canonical code fields
### 2.2 User / account-manager flow
- [x] Review current `account-manager` permission implementation
- [x] Add dedicated backend flow for account-manager-based account creation if current `/users` route is insufficient
- [x] Ensure `hf user create` maps cleanly to backend account-manager permission model
- [x] Ensure new accounts default to `guest`
- [x] Ensure admin role cannot be assigned through normal user management APIs
### 2.3 Permission introspection for CLI help
- [x] Decide how CLI will query effective permissions
- [x] Add/extend backend endpoint(s) for current-user permission introspection if needed
- [x] Ensure CLI can cheaply determine whether a subcommand is permitted
- [x] Support permission-aware help rendering without excessive API chattiness
### 2.4 Task / meeting / support actions
- [x] Add/confirm backend route for task self-assignment (`task take`)
- [x] Add/confirm conflict behavior when task already has a different assignee
- [x] Add/confirm backend route for meeting attendance (`meeting attend`)
- [x] Ensure meeting attendance updates participant list
- [x] Add/confirm backend route for support self-assignment (`support take`)
### 2.5 Frontend-facing code migration support
- [x] Add code-based detail endpoints or code query support for frontend routing
- [x] Ensure frontend can resolve resources by code without fallback to id-only APIs
- [x] Update serializers to expose code prominently wherever applicable
### 2.6 Legacy Python CLI retirement
- [x] Track parity between new `hf` CLI and old backend Python CLI
- [x] Once parity is acceptable, remove legacy Python CLI from backend repo
- [x] Remove backend docs referencing the old Python CLI
---
## 3. HarborForge.Frontend
### 3.1 Code-first UI migration
- [x] Audit current routes and identify every place still using raw ids
- [x] Move project detail lookup toward `project-code`
- [x] Move milestone detail lookup toward `milestone-code`
- [x] Move task detail lookup toward `task-code`
- [x] Move meeting detail lookup toward `meeting-code`
- [x] Move support detail lookup toward `support-code`
- [x] Move propose detail lookup toward `propose-code`
- [x] Stop surfacing raw ids as the main visible identifier in lists/details
- [x] Display codes consistently in relevant list and detail views
### 3.2 User / role UX alignment
- [x] Review current user management page against final backend behavior
- [x] Ensure only code/name-first identifiers are shown where relevant
- [x] Ensure account role display matches single-role model everywhere
### 3.3 Meeting / support UI
- [x] Audit current frontend support for meeting resources
- [x] Add/adjust UI for meeting participant state if needed
- [x] Add/adjust UI for support take/ownership state if needed
### 3.4 Monitor UI alignment
- [x] Ensure monitor views expose server identifier/code cleanly
- [ ] Review display of OpenClaw/plugin metadata once Monitor bridge is deployed
### 3.5 Future CLI alignment aids
- [x] Consider showing canonical codes more prominently to help users map UI↔CLI
- [x] Ensure copyable resource codes are easy to find from the UI
---
## 4. HarborForge.OpenclawPlugin
### 4.1 Plugin identity and packaging
- [x] Rename plugin registration name to `harbor-forge`
- [x] Audit all docs/config/install references to old plugin name
- [x] Ensure plugin config keys and examples reflect the new registration name
### 4.2 Remove sidecar architecture
- [x] Remove plugin-side `server/` telemetry sidecar
- [x] Remove sidecar startup/shutdown lifecycle logic
- [x] Remove sidecar-specific docs and examples
- [x] Replace old OpenClaw telemetry flow with direct plugin-exposed data path
### 4.3 Plugin config updates
- [x] Add `monitor_port` to plugin config schema
- [x] Document `monitor_port` in plugin README/docs/examples
- [x] Ensure runtime reads and validates `monitor_port`
### 4.4 CLI install support
- [x] Add install script flag `--install-cli`
- [x] Resolve OpenClaw profile bin directory (default `~/.openclaw/bin`)
- [x] Build `HarborForge.Cli`
- [x] Install compiled `hf` binary to profile `bin/`
- [x] `chmod +x` installed binary
- [x] Handle failure cases cleanly if CLI build/install fails
### 4.5 Skills deployment
- [x] Add plugin `skills/` directory
- [x] Add `skills/hf/`
- [x] Add `skills/hf/SKILL.md`
- [x] In `SKILL.md`, explain basic `hf` usage
- [x] In `SKILL.md`, encourage agents to use `hf --help-brief`
- [x] In `SKILL.md`, point to normal `--help` for full command tree
- [x] Installer should copy normal plugin skills into profile `skills/`
- [x] Installer should **not** copy `skills/hf/` unless `--install-cli` is present
- [x] Installer should copy `skills/hf/` when `--install-cli` is present
### 4.6 Monitor bridge endpoint
- [x] Define how plugin exposes OpenClaw metadata to Monitor over local port
- Plugin periodically POSTs metadata to Monitor bridge `POST /openclaw`
- [x] Decide HTTP endpoint structure / payload schema
- `POST /openclaw` with `{ version, plugin_version, agents }`
- [x] Expose OpenClaw version
- [x] Expose plugin version
- [x] Expose agent list / agent metadata
- [x] Ensure plugin remains functional even if Monitor never connects
---
## 5. HarborForge.Monitor
### 5.1 Docker/runtime changes
- [x] Add `MONITOR_PORT` env var
- [x] Ensure Monitor listens on `127.0.0.1:<MONITOR_PORT>`
- [x] Update Docker runtime docs/examples
- [x] Update docker-compose to expose that port to host `127.0.0.1`
### 5.2 Plugin communication
- [x] Implement local communication client to query plugin over `MONITOR_PORT`
- Note: the architecture is reversed — Monitor hosts the bridge, plugin pushes via POST /openclaw
- [x] Define request timeout / retry / fallback policy
- Plugin uses 3s timeout; Monitor bridge uses 5s read/write timeouts
- [x] Keep startup independent of plugin communication success
- [x] Keep heartbeat/telemetry upload independent of plugin communication success
- [x] If plugin is reachable, enrich telemetry with:
- [x] OpenClaw version
- [x] plugin version
- [x] agent info
- [x] If plugin is unreachable, continue current behavior unchanged
### 5.3 Telemetry model alignment
- [x] Ensure backend-facing telemetry payloads can carry optional OpenClaw metadata
- [x] Avoid making plugin-derived fields mandatory
- [x] Ensure monitor data model cleanly distinguishes:
- [x] host/hardware telemetry
- [x] optional OpenClaw metadata
### 5.4 Docs / examples
- [x] Update Monitor README to explain `MONITOR_PORT`
- [x] Explain degraded mode when plugin bridge is absent
- [x] Provide example Docker run / compose snippet with host loopback exposure
---
## 6. HarborForge.Test / HarborForge.Frontend.Test
### 6.1 Keep test runner aligned
- [ ] Preserve Frontend.Test Dockerfile as owner of proxy startup
- [ ] Keep `run-test-frontend.sh` from overriding default test container CMD unless strictly necessary
- [ ] Keep expose-port mode working with 127.0.0.1 + proxy architecture
### 6.2 Code-first frontend test updates
- [ ] Update tests to prefer resource codes over ids in assertions and navigation
- [ ] Remove assumptions that UI surfaces raw ids where codes should be primary
### 6.3 Future CLI tests
- [ ] Add tests for `hf` help rendering
- [ ] Add tests for `hf --help-brief`
- [ ] Add tests for padded-cell mode vs manual mode
- [ ] Add tests for exact stderr messages
- [ ] Add tests for code-only command acceptance
---
## 7. Suggested implementation order
### Phase A — Foundations
- [x] Finalize CLI help / mode / output model
- [x] Finalize backend permission introspection approach
- [x] Finalize plugin↔monitor local protocol
### Phase B — Backend first
- [x] Add/finish code-based backend support
- [x] Add/finish task take / meeting attend / support take
- [x] Add any missing account-manager creation behavior
### Phase C — CLI MVP
- [x] Build `hf` scaffold
- [x] Ship `version`, `health`, `config`
- [x] Ship `user create`, `user list`, `user get`
- [x] Ship `task list`, `task get`, `task take`
- [x] Ship initial `monitor` commands
### Phase D — Frontend alignment
- [x] Move frontend to code-first lookup/display
- [x] Surface canonical codes consistently in UI
### Phase E — Plugin / Monitor integration
- [x] Rename plugin to `harbor-forge`
- [x] Remove plugin sidecar
- [x] Add `--install-cli`
- [x] Add `skills/hf`
- [x] Add `monitor_port` / `MONITOR_PORT` bridge
### Phase F — Cleanup / retirement
- [x] Remove legacy backend Python CLI
- [x] Update all docs to point to `hf`
- [ ] Add final tests and packaging flow

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
# Monitor Server Connector Plan
## Current design
The plugin and Monitor communicate over a local bridge port (`monitor_port` / `MONITOR_PORT`).
### Data flow
1. **Monitor → Plugin** (GET): Plugin queries `GET /telemetry` on the bridge for host hardware data.
2. **Plugin → Monitor** (POST): Plugin pushes OpenClaw metadata via `POST /openclaw` to the bridge.
3. **Monitor → Backend**: Monitor heartbeats to `POST /monitor/server/heartbeat-v2` with `X-API-Key`, enriched with any available OpenClaw metadata.
### Bridge endpoints (on Monitor, 127.0.0.1:MONITOR_PORT)
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health` | GET | Health check, returns monitor version and identifier |
| `/telemetry` | GET | Latest hardware telemetry snapshot |
| `/openclaw` | POST | Receive OpenClaw metadata from plugin |
### Plugin behavior
- On `gateway_start`, plugin begins periodic metadata push (aligned with `reportIntervalSec`).
- Initial push is delayed 2s to allow Monitor bridge startup.
- If bridge is unreachable, pushes fail silently. Plugin remains fully functional.
- On `gateway_stop`, periodic push is stopped.
## No longer used
The following design has been retired:
- challenge UUID / RSA handshake / WebSocket telemetry
- Plugin-side `server/` sidecar process
## Heartbeat payload
```json
{
"identifier": "vps.t1",
"openclaw_version": "OpenClaw 2026.3.13 (61d171a)",
"plugin_version": "0.2.0",
"agents": [],
"cpu_pct": 10.5,
"mem_pct": 52.1,
"disk_pct": 81.0,
"swap_pct": 0.0,
"load_avg": [0.12, 0.09, 0.03],
"uptime_seconds": 12345,
"nginx_installed": true,
"nginx_sites": ["default"]
}
```
`openclaw_version`, `plugin_version`, and `agents` are optional enrichment from the plugin. If plugin never pushes metadata, these fields are omitted and the heartbeat contains only hardware telemetry.

View File

@@ -0,0 +1,78 @@
# HarborForge Monitor / OpenClaw Plugin Connector Plan
## 目标
使用 **API Key + HTTP heartbeat** 连接 HarborForge Monitor 与远程 OpenClaw 节点。
## 认证方式
- 管理员为服务器生成 API Key
- 插件通过 `X-API-Key` 调用 heartbeat 接口
- 不再使用 challenge / RSA 公钥 / WebSocket 握手
## 上报接口
`POST /monitor/server/heartbeat-v2`
### Headers
- `X-API-Key: <server-api-key>`
### Payload
```json
{
"identifier": "vps.t1",
"openclaw_version": "OpenClaw 2026.3.13 (61d171a)",
"plugin_version": "0.1.0",
"agents": [
{ "id": "agent-bot1", "name": "agent-bot1", "status": "configured" }
],
"cpu_pct": 12.3,
"mem_pct": 45.6,
"disk_pct": 78.9,
"swap_pct": 0,
"load_avg": [0.12, 0.08, 0.03],
"uptime_seconds": 12345
}
```
## 语义
- `openclaw_version`: 远程主机上的 OpenClaw 版本
- `plugin_version`: `harbor-forge` 插件版本
## 插件生命周期
- 插件注册名为 `harbor-forge`
- 不再启动独立 `server/telemetry.mjs` sidecar
- 插件直接通过 Gateway/runtime 路径暴露 OpenClaw 元数据
- 如配置了 `monitor_port`,插件还可通过本地桥接与 HarborForge.Monitor 交互
## 配置位置
`~/.openclaw/openclaw.json`
```json
{
"plugins": {
"entries": {
"harbor-forge": {
"enabled": true,
"config": {
"enabled": true,
"backendUrl": "http://127.0.0.1:8000",
"identifier": "vps.t1",
"apiKey": "your-api-key",
"monitor_port": 9100
}
}
}
}
}
```
## 已废弃
- challenge UUID
- server public key
- WebSocket telemetry
- encrypted handshake payload

View File

@@ -0,0 +1,584 @@
# ZHI_TASKS.md
> 基于 `docs/milestone-propose-requirements.md` 拆分的开发 TODO
> 更新时间2026-03-18
> 目标:把需求拆到接近"可直接开工 / 可独立提 PR"的粒度
---
# 使用建议
- 每个一级任务尽量对应一个小阶段
- 每个二级任务尽量对应一个可独立提交的改动点
- 做之前先勾选"设计/盘点",做完再勾选"测试/文档"
---
# P0 - 盘点与设计冻结 ✅
## P0.1 旧状态与旧逻辑盘点
- [x] 搜出所有 milestone status 的旧枚举使用位置
- [x] 搜出所有 task status 的旧枚举使用位置
- [x] 搜出所有前端 status badge / 文案 / 下拉框位置
- [x] 搜出所有后端 transition / update / filter 逻辑位置
- [x] 搜出所有 CLI 中 status choices 的位置
- [x] 搜出所有测试里写死旧状态名的位置
## P0.2 现有类型体系盘点
- [x] 盘点所有 task_type 的定义位置
- [x] 盘点所有 task_subtype 的定义位置
- [x] 确认前后端 `task_type = task` 的全部使用点
- [x] 列出历史数据迁移时 `task_type = task` 的处理方案候选
## P0.3 数据迁移设计
- [x] 设计 milestone 旧状态 -> 新状态映射
- [x] 设计 task 旧状态 -> 新状态映射
- [x] 设计 `assignee` 与现有 `assignee_id` 的过渡策略
- [x] 设计 `feat_task_id` 存储什么值task id string / task code
- [x] 设计 reopen 记录落地方式comment / activity / 独立表)
## P0.4 权限设计冻结
- [x] 确认 milestone 新权限名
- [x] 确认 task 新权限名
- [x] 确认 propose 新权限名
- [x] 确认 admin 是否默认拥有全部新增权限
- [x] 确认默认 role 是否需要预置部分权限
---
# P1 - 数据模型与迁移骨架 ✅
## P1.1 Milestone 模型改造
- [x] 修改后端 milestone enum 定义
- [x] 移除 `pending`
- [x] 移除 `deferred`
- [x] 移除 `progressing`
- [x] 增加 `freeze`
- [x] 增加 `undergoing`
- [x] 增加 `completed`
- [x] 增加 `started_at`
- [x] 更新 milestone schema
- [x] 更新 milestone response model
## P1.2 Task 模型改造
- [x] 修改后端 task enum 定义
- [x] 移除 `progressing`
- [x] 增加 `undergoing`
- [x] 增加 `completed`
- [x] 增加 `assignee` 字段 — 沿用已有 `assignee_id`
- [x] 明确 `assignee` 是否替代 `assignee_id` — 沿用 assignee_id
- [x] 更新 task schema
- [x] 更新 task response model
## P1.3 Propose 模型新增
- [x] 新建 propose model
- [x] 增加 `project_id`
- [x] 增加 `propose_code`
- [x] 增加 `title`
- [x] 增加 `description`
- [x] 增加 `status`
- [x] 增加 `created_by_id`
- [x] 增加 `created_at`
- [x] 增加 `updated_at`
- [x] 增加 `feat_task_id`
- [x]`feat_task_id` 标记为服务端只读
## P1.4 Propose 编码支持
- [x] 设计 propose counter 表/字段复用方案 — 用 max(id)+1
- [x] 实现按 project 独立计数
- [x] 实现 `P{i:05x}` 格式生成
- [x] 实现 `{proj_code}:P{i:05x}` 拼接
- [x] 为并发创建补唯一性保护 — unique 约束兜底
## P1.5 数据库迁移脚本
- [x] 编写 milestone 状态迁移脚本 — main.py _migrate_schema()
- [x] 编写 task 状态迁移脚本 — main.py _migrate_schema()
- [x] 编写新增 `started_at` 迁移
- [x] 编写新增 `assignee` 迁移 — 沿用已有字段
- [x] 编写新增 propose 表迁移 — create_all 自动建表
- [x] 编写新增 `feat_task_id` 迁移 — propose 表自带
- [x] 编写旧数据回填/默认值策略 — pending→open, deferred→closed, progressing→undergoing
## P1.6 模型层校验与 smoke test
- [x] 确认应用启动不报 enum/schema 错误 — AST 检查通过
- [x] 确认旧接口序列化不崩 — AST + tsc 检查通过
- [ ] 确认 migration 后可读写 milestone/task — 需本地 MySQL
- [ ] 确认 propose 表能正常创建记录 — 需本地 MySQL
---
# P2 - 权限骨架 ✅
## P2.1 后端权限枚举/注册
- [x] 注册 `milestone.freeze`
- [x] 注册 `milestone.start`
- [x] 注册 `milestone.close`
- [x] 注册 `task.close`
- [x] 注册 `task.reopen_closed`
- [x] 注册 `task.reopen_completed`
- [x] 注册 `propose.accept`
- [x] 注册 `propose.reject`
- [x] 注册 `propose.reopen`
## P2.2 默认角色与权限种子
- [x] 更新默认权限种子
- [x] 更新 admin 默认权限
- [x] 更新可能的 owner / manager / dev 权限分配
- [x] 写一份新旧权限差异说明 — docs/permissions-overview.md
## P2.3 权限检查辅助方法
- [x] 为 milestone action 增加统一权限检查 helper — 使用 check_permission
- [x] 为 task action 增加统一权限检查 helper — 使用 check_permission
- [x] 为 propose action 增加统一权限检查 helper — 使用 check_permission
---
# P3 - Milestone 状态机后端 ✅
## P3.1 Milestone 动作接口
- [x] 设计 milestone 动作接口路径 — /projects/{pid}/milestones/{mid}/actions/{action}
- [x] 实现 freeze 接口
- [x] 实现 start 接口
- [x] 实现 close 接口
- [x] 明确 completed 自动触发入口 — try_auto_complete_milestone()
## P3.2 Freeze 业务规则
- [x] 查询当前 milestone 下 maintenance/release task 数量
- [x] 校验"有且仅有一个 release maintenance task"
- [x] 失败时返回明确错误 detail
- [x] 成功时写入 `status=freeze`
- [x] 写 activity log / 操作记录
## P3.3 Start 业务规则
- [x] 读取 milestone 前置依赖
- [x] 校验依赖 milestone 是否完成
- [x] 校验依赖 task 是否完成
- [x] 校验其他依赖对象是否完成
- [x] 校验通过后写入 `status=undergoing`
- [x] 自动写入 `started_at`
- [x] 写 activity log / 操作记录
## P3.4 Close 业务规则
- [x] 仅允许 `open/freeze/undergoing -> closed`
- [x] 校验 `close milestone` 权限
- [x]`undergoing` close 增加附加确认/原因字段支持(如需要)
- [x] 为后续"依赖修正"预留服务端入口
- [x] 写 activity log / 操作记录
## P3.5 Completed 自动触发
- [x] 在 task 完成逻辑里检测 release maintenance task
- [x] 校验 milestone 下唯一 release task 已完成
- [x] 自动写入 milestone `completed`
- [x] 防止重复触发
- [x] 写 activity log / 操作记录
## P3.6 Milestone 编辑限制
- [x] `open` 允许编辑基本信息
- [x] `freeze` 禁止范围调整相关字段修改
- [x] `completed` 禁止编辑
- [x] `closed` 禁止编辑
- [x] 对 feature 相关变更做服务端防守 — freeze 后禁止新增/编辑 feature story task
---
# P4 - 依赖检查后端 ✅
## P4.1 通用依赖检查能力
- [x] 抽一个依赖检查 service/helper — app/services/dependency_check.py
- [x] 支持检查 milestone 依赖 — check_milestone_deps()
- [x] 支持检查 task 依赖 — check_task_deps()
- [ ] 支持检查 support 依赖 — 延后support 无 depend_on 字段)
- [ ] 支持检查 meeting 依赖 — 延后meeting 无 depend_on 字段)
## P4.2 milestone 开始前检查
- [x] milestone start 复用通用依赖检查
- [x] 返回详细未满足依赖信息
## P4.3 task 开始前检查
- [x] task `pending -> open` 复用通用依赖检查
- [x] 返回详细未满足依赖信息
## P4.4 close 后依赖修正预留
- [x] 设计 milestone close 后依赖修正数据结构 — 需手动调整依赖
- [x] 决定先阻塞 close 还是允许 close 后手动修复 — 允许 close手动修复
- [ ] 为未来依赖修正 UI/API 预留接口 — 延后
---
# P5 - Task 状态机后端 ✅
## P5.1 Task 动作接口梳理
- [x] 明确继续复用现有 transition 接口还是拆动作接口 — 复用 transition
- [x] 如复用 transition补足新状态合法性校验
## P5.2 `pending -> open`
- [x] 校验当前状态必须为 `pending`
- [x] 校验前置依赖全部满足
- [x] 校验所在 milestone 允许 task 进入 open
- [x] 更新状态为 `open`
- [x] 写 activity log / 操作记录
## P5.3 `open -> undergoing`
- [x] 校验当前状态必须为 `open`
- [x] 校验 `assignee` 非空
- [x] 校验操作者就是 assignee
- [x] 校验所在 milestone 为 `undergoing`
- [x] 更新状态为 `undergoing`
- [x] 写开始时间(如沿用 started_on
- [x] 写 activity log / 操作记录
## P5.4 `undergoing -> completed`
- [x] 校验当前状态必须为 `undergoing`
- [x] 校验操作者就是 assignee
- [x] 校验 completion comment 已提交
- [x] 更新状态为 `completed`
- [x] 写完成时间(如沿用 finished_on
- [x] 写 activity log / 操作记录
## P5.5 `pending/open/undergoing -> closed`
- [x] 校验当前状态合法
- [x] 校验 `close task` 权限
- [x] 更新状态为 `closed`
- [x] 写 close reason/comment如需要
- [x] 写 activity log / 操作记录
## P5.6 `closed/completed -> open` reopen
- [x] 校验当前状态为 `closed``completed`
- [x]`closed` 校验 `reopen closed task` 权限
- [x]`completed` 校验 `reopen completed task` 权限
- [x] 更新状态回 `open`
- [x] 写 reopen 记录
- [x] 写 activity log / 操作记录
## P5.7 Task 编辑权限服务端防守
- [x] `open + assignee=null` 允许编辑主体
- [x] `open + assignee!=null` 仅 assignee/admin 可编辑主体
- [x] `undergoing/completed/closed` 禁止主体编辑
- [x] 保留 comment 接口可用性
## P5.8 与 release maintenance task 联动
- [x] 在 task 完成时识别 release maintenance task
- [x] 与 milestone completed 自动触发逻辑打通
- [x] 防止普通 task 完成误触发 milestone completed
---
# P6 - Propose 后端 ✅
## P6.1 基础 CRUD
- [x] 实现 create propose
- [x] 实现 list proposes
- [x] 实现 get propose detail
- [x] 实现 update propose
- [x] 限制仅 `open` 可编辑主体
## P6.2 Accept
- [x] 设计 accept API
- [x] 接收 milestone 选择参数
- [x] 校验 propose 当前状态为 `open`
- [x] 校验 `accept propose` 权限
- [x] 校验 milestone 属于同 project
- [x] 校验 milestone status 为 `open`
- [x] 自动创建 `feature story task`
- [x] 复制 `title`
- [x] 复制 `description`
- [x] 复制 `created_by`
- [x] 设置新 task 默认状态 `pending`
- [x] 自动回填 `feat_task_id`
- [x] 更新 propose status 为 `accepted`
- [x] 写 activity log / 操作记录
## P6.3 Reject
- [x] 设计 reject API
- [x] 校验 propose 当前状态为 `open`
- [x] 校验 `reject propose` 权限
- [x] 支持 reason/comment
- [x] 更新 propose status 为 `rejected`
- [x] 写 activity log / 操作记录
## P6.4 Reopen
- [x] 设计 reopen API
- [x] 校验 propose 当前状态为 `rejected`
- [x] 校验 `reopen rejected propose` 权限
- [x] 复用当前 propose不创建新记录
- [x] 更新 propose status 为 `open`
- [x] 写 reopen 记录
- [x] 写 activity log / 操作记录
## P6.5 `feat_task_id` 只读保护
- [x] update 接口中忽略客户端传入的 `feat_task_id`
- [x] schema 中将 `feat_task_id` 标为只读输出字段
- [x] accept 成功后才允许服务端填充 `feat_task_id`
---
# P7 - 移除 `task_type = task` ✅
## P7.1 后端清理
- [x] 从后端 enum/type 定义中移除 `task`
- [x]`TASK_SUBTYPE_MAP` 中移除 `task`
- [x] 清理 create/update 校验逻辑中的 `task`
## P7.2 前端清理
- [x] 从 CreateTaskModal 移除 `task`
- [x] 从 CreateTaskPage 移除 `task`
- [x] 更新 task type 下拉默认值 — 改为 issue
- [x] 确认默认类型改成什么 — issue
## P7.3 历史数据处理
- [x] 统计数据库中已有多少 `task_type=task` — 迁移脚本自动处理
- [x] 确认迁移到哪个新 type/subtype — task→issue
- [x] 编写数据修复脚本 — main.py _migrate_schema()
---
# P8 - 前端Milestone 页面 ✅
## P8.1 类型与状态文案
- [x] 更新前端 milestone type/status 定义
- [x] 替换旧状态 badge
- [x] 增加新状态 badge — status-freeze, status-undergoing, status-completed
- [x] 展示 `started_at`
## P8.2 Detail 页按钮
- [x] `open` 显示 `freeze` + `close`
- [x] `freeze` 显示 `start` + `close`
- [x] `undergoing` 显示 `close`
- [x] `completed` 不显示状态动作按钮
- [x] `closed` 不显示状态动作按钮
## P8.3 按钮禁用与提示
- [x] `freeze` 不满足条件时禁用
- [x] `freeze` 提示缺少/多于 release maintenance task
- [x] `start` 不满足依赖时禁用
- [x] `start` 提示未完成依赖
## P8.4 编辑态限制
- [x] `open` 时允许编辑基本信息
- [x] `freeze` 时禁止范围调整相关编辑项 — 隐藏编辑按钮 + scope locked 提示
- [x] `completed/closed` 时禁用编辑入口
---
# P9 - 前端Task 页面 ✅
## P9.1 类型与状态文案
- [x] 更新前端 task status 类型定义
- [x] 移除 `progressing`
- [x] 增加 `undergoing`
- [x] 增加 `completed`
## P9.2 Detail 页按钮
- [x] `pending` 显示 `open` + `close`
- [x] `open` 显示 `start` + `close`
- [x] `undergoing` 显示 `finish` + `close`
- [x] `completed` 显示 `reopen`
- [x] `closed` 显示 `reopen`
- [x] 所有按钮按权限可见 — 后端权限校验,前端按钮按 status/assignee 显示
## P9.3 编辑行为
- [x] `open + assignee=null` 时显示编辑入口
- [x] `open + assignee!=null` 时按 assignee/admin 显示编辑入口
- [x] `undergoing/completed/closed` 时隐藏/禁用主体编辑入口
- [x] 保留 comment 区域
## P9.4 Finish 流程
- [x] finish 前要求填写 comment
- [x] 设计 finish + comment 的交互 — 弹窗输入 comment 后确认
- [x] finish 成功后刷新状态与 comment 列表
## P9.5 Reopen 流程
- [x] `completed` 显示 reopen
- [x] `closed` 显示 reopen
- [x] reopen 成功后状态回到 `open`
- [x] 显示 reopen 历史记录 — 通过 activity log
## P9.6 创建表单限制
- [x] 禁止通用 create task 创建 `feature story task`
- [x] 禁止通用 create task 创建 `release maintenance task`
- [x] 调整默认 task status 体验为 `pending`
- [x] 调整默认 task type移除 `task` 后) — 默认 issue
---
# P10 - 前端Propose 页面 ✅
## P10.1 列表页
- [x] 新建 propose 列表页
- [x] 支持按 project 查看
- [x] 支持显示 status
- [x] 支持显示 `propose_code`
## P10.2 创建页/弹窗
- [x] 新建 propose 创建表单
- [x] 支持填写 title/description
- [x] 自动归属当前 project
## P10.3 详情页
- [x] 展示 `propose_code`
- [x] 展示 `title`
- [x] 展示 `description`
- [x] 展示 `status`
- [x] 展示 `feat_task_id`
- [x] 展示 `created_by_id`
- [x] 展示 `created_at`
- [x] 展示 `updated_at`
## P10.4 按钮
- [x] `open` 显示 `accept` / `reject`
- [x] `accepted` 不显示状态动作按钮
- [x] `accepted` 显示 `View Generated Task`
- [x] `rejected` 显示 `reopen`
- [x] 所有按钮按权限可见 — 后端权限校验
## P10.5 Accept 交互
- [x] 弹出 milestone 选择框
- [x] 仅列出当前 project 下 `open` 的 milestone
- [x] accept 成功后展示生成的 feature task 跳转
- [x] 页面刷新后显示 `feat_task_id`
## P10.6 Reject / Reopen 交互
- [x] reject 时支持填写 reason/comment
- [x] reopen 时提示会把 propose 恢复到 `open`
- [x] reopen 成功后刷新详情页状态
## P10.7 编辑限制
- [x] `open` 时允许编辑 title/description
- [x] `accepted` 禁止编辑主体
- [x] `rejected` 禁止编辑主体
---
# P11 - 权限管理前端/管理页 ✅
## P11.1 新权限展示
- [x] 在权限列表中展示 milestone 新权限 — RoleEditorPage 动态加载
- [x] 在权限列表中展示 task 新权限 — RoleEditorPage 动态加载
- [x] 在权限列表中展示 propose 新权限 — RoleEditorPage 动态加载
## P11.2 Role 编辑
- [x] Role 编辑页支持勾选新权限 — RoleEditorPage 已有功能
- [x] 默认角色展示正确 — init_wizard 自动种子
- [x] 保存后权限持久化正确 — 已有功能
---
# P12 - CLI / 文档 / 开发者说明 ✅
## P12.1 CLI
- [x] 更新 task status choices
- [x] 更新 milestone status choices
- [x] 如需要,新增 propose 子命令 — 5 个子命令
## P12.2 README / docs
- [x] 更新状态枚举说明 — docs/state-machine-overview.md
- [x] 更新按钮/动作说明
- [x] 新增 propose 流程说明 — docs/propose-flow.md
- [x] 新增权限说明 — docs/permissions-overview.md
## P12.3 开发说明
- [x] 在 docs 中补一页"状态机总览" — docs/state-machine-overview.md
- [x] 在 docs 中补一页"权限总览" — docs/permissions-overview.md
- [x] 在 docs 中补一页"propose -> feature story -> milestone"流程图/文字 — docs/propose-flow.md
---
# P13 - 自动化测试 ✅(后端完成,前端延后)
## P13.1 Milestone 后端测试
- [x]`open -> freeze` 成功路径
- [x]`open -> freeze` 缺少 release task 失败
- [x]`open -> freeze` 多个 release task 失败
- [x]`freeze -> undergoing` 依赖未完成失败
- [x]`freeze -> undergoing` 成功并写 `started_at`
- [x] 测 release maintenance task 完成后 milestone 自动 completed
- [x] 测 milestone close 权限
## P13.2 Task 后端测试
- [x]`pending -> open` 依赖满足成功
- [x]`pending -> open` 依赖不满足失败
- [x]`open -> undergoing` assignee 为空失败
- [x]`open -> undergoing` 非 assignee 操作失败
- [x]`open -> undergoing` assignee 操作成功
- [x]`undergoing -> completed` 无 comment 失败
- [x]`undergoing -> completed` 成功
- [x]`close task` 权限
- [x]`reopen closed task` 权限
- [x]`reopen completed task` 权限
## P13.3 Propose 后端测试
- [x] 测 propose code 按 project 独立递增
- [x]`open -> accepted`
- [x] 测 accept 时 milestone 非 open 失败
- [x] 测 accept 后自动生成 feature story task
- [x] 测 accept 后自动写 `feat_task_id`
- [x]`open -> rejected`
- [x]`rejected -> open`
- [x]`feat_task_id` 无法手动修改
## P13.4 前端 / E2E — 延后(需运行环境)
- [ ] 测 milestone 按钮显示规则
- [ ] 测 milestone 按钮禁用提示
- [ ] 测 task 按钮显示规则
- [ ] 测 task finish 需要 comment
- [ ] 测 task reopen 后回到 open
- [ ] 测 propose create -> accept -> task generated 流程
- [ ] 测 propose reject -> reopen 流程
- [ ] 回归已有 wizard / role-editor / task / milestone 测试
---
# P14 - 收尾与上线前检查 — 延后(需运行环境)
## P14.1 数据校验
- [ ] 用旧数据跑迁移 — 需本地 MySQL
- [ ] 抽查 milestone 状态迁移结果
- [ ] 抽查 task 状态迁移结果
- [ ] 抽查 `task_type = task` 数据迁移结果
- [ ] 抽查 propose code 生成结果
## P14.2 手工验收
- [ ] 手工走 milestone freeze/start/close
- [ ] 手工走 task open/start/finish/close/reopen
- [ ] 手工走 propose create/accept/reject/reopen
- [ ] 手工检查权限可见性
- [ ] 手工检查禁用按钮与提示语
## P14.3 最终文档整理
- [x] 更新 `docs/milestone-propose-requirements.md` 与最终实现差异
- [x] 删除过时说明 — 无需删除,需求文档即实现
- [x] 标出最终未做项 / 延后项 — 见下方总结
---
# 完成总结2026-03-18 第 30 轮更新)
## 已完成P0-P13.3,共 30 轮迭代)
- ✅ P0 盘点与设计冻结
- ✅ P1 数据模型与迁移骨架milestone/task/propose
- ✅ P2 权限骨架9 个新权限 + admin/mgr/dev/guest 角色种子)
- ✅ P3 Milestone 状态机后端freeze/start/close/auto-complete + 编辑限制)
- ✅ P4 依赖检查后端(通用 helper + milestone/task 接入)
- ✅ P5 Task 状态机后端(状态校验 + assignee 身份 + comment 强制 + 编辑限制 + batch 同步)
- ✅ P6 Propose 后端CRUD + accept/reject/reopen + feat_task_id + code 生成)
- ✅ P7 移除 task_type=task前后端 + DB 迁移)
- ✅ P8 前端 Milestone 页面badge + 动作按钮 + preflight 禁用 + 编辑限制)
- ✅ P9 前端 Task 页面(动作按钮 + finish 弹窗 + 编辑守卫 + 创建限制)
- ✅ P10 前端 Propose 页面(列表 + 详情 + 创建 + accept/reject/reopen + 编辑限制)
- ✅ P11 权限管理前端(动态加载,无需额外开发)
- ✅ P12 CLI + 文档5 个 propose 子命令 + 3 份文档)
- ✅ P13.1-P13.3 后端测试70 个测试全部通过)
## 延后项(需本地运行环境)
- ⏸ P1.6 部分MySQL 集成验证
- ⏸ P4.1 部分support/meeting 依赖检查(无 depend_on 字段)
- ⏸ P4.4 部分:依赖修正 UI/API
- ⏸ P13.4:前端 E2E 测试
- ⏸ P14.1-P14.2:数据迁移验证 + 手工验收
## 统计
- 后端 commits: ~25+
- 前端 commits: ~12+
- 新文件: ~15+
- 测试: 70 passed, 0 failed
- 文档: 3 份新文档state-machine, permissions, propose-flow

View File

@@ -0,0 +1,31 @@
# BE-PR-001: Propose → Proposal Rename Impact Checklist
## Summary
Unified all backend Python-level naming from `Propose` to `Proposal`. DB table and column names kept unchanged for backward compatibility (no migration needed).
## Files Changed
### New Files
- `app/models/proposal.py` — Canonical model: `Proposal`, `ProposalStatus`
- `app/api/routers/proposals.py` — Canonical router at `/projects/{id}/proposals`
### Modified Files
- `app/models/propose.py` — Now a backward-compat shim re-exporting from `proposal.py`
- `app/api/routers/proposes.py` — Now a backward-compat shim delegating to `proposals.py` (legacy `/proposes` URL still works)
- `app/schemas/schemas.py` — Renamed: `ProposalStatusEnum`, `ProposalBase`, `ProposalCreate`, `ProposalUpdate`, `ProposalResponse` (old names kept as aliases)
- `app/main.py` — Registers both `proposals_router` (canonical) and `proposes_router` (legacy compat)
- `app/init_wizard.py` — Updated comments to say "Proposal" (permission names `propose.*` kept for DB compat)
- `tests/test_propose.py` — Updated all tests to use `/proposals` URL; added legacy endpoint compat tests
## What Was Kept for Backward Compatibility
| Item | Kept As-Is | Reason |
|------|-----------|--------|
| DB table name | `proposes` | Avoid DB migration |
| DB column | `propose_code` | Avoid DB migration |
| Permission names | `propose.accept`, `propose.reject`, `propose.reopen` | Already stored in DB |
| Legacy API path | `/projects/{id}/proposes/*` | Client compat |
| Python aliases | `Propose`, `ProposeStatus`, `ProposeCreate`, etc. | Import compat |
## API Endpoints
- **Canonical:** `/projects/{project_id}/proposals` (new)
- **Legacy:** `/projects/{project_id}/proposes` (still works, delegates to canonical)

View File

@@ -0,0 +1,90 @@
# HarborForge — 权限总览
> 更新时间2026-03-18
> 本文档列出 milestone-propose 功能新增的所有权限,以及默认角色分配。
---
## 1. 新增权限一览
| 权限名 | Category | 含义 |
|--------------------------|------------|-------------------------------|
| `milestone.freeze` | milestone | 将 milestone 从 open 冻结为 freeze |
| `milestone.start` | milestone | 将 milestone 从 freeze 启动为 undergoing |
| `milestone.close` | milestone | 将 milestone 废弃close |
| `task.close` | task | 将 task 废弃close |
| `task.reopen_closed` | task | 重新打开已废弃的 task |
| `task.reopen_completed` | task | 重新打开已完成的 task |
| `propose.accept` | propose | 接受 propose 并生成 feature task |
| `propose.reject` | propose | 拒绝 propose |
| `propose.reopen` | propose | 重新打开已拒绝的 propose |
---
## 2. 默认角色权限分配
### admin管理员
拥有**所有权限**,包括上述 9 个新权限。通过 `init_admin_role()` 自动同步。
### mgr经理
| 权限 | 有 |
|-----------------|----|
| milestone.freeze | ✓ |
| milestone.start | ✓ |
| milestone.close | ✓ |
| task.close | ✓ |
| task.reopen_closed | ✓ |
| task.reopen_completed | ✓ |
| propose.accept | ✓ |
| propose.reject | ✓ |
| propose.reopen | ✓ |
另含project.read/write/manage_members, task.create/read/write, milestone.create/read/write, monitor.read
### dev开发者
| 权限 | 有 |
|-----------------|----|
| milestone.freeze | ✗ |
| milestone.start | ✗ |
| milestone.close | ✗ |
| task.close | ✓ |
| task.reopen_closed | ✓ |
| task.reopen_completed | ✓ |
| propose.accept | ✗ |
| propose.reject | ✗ |
| propose.reopen | ✗ |
另含project.read, task.create/read/write, milestone.read, monitor.read
### guest访客
`*.read` 权限,无新增权限。
---
## 3. 权限设计原则
1. **独立不合并**`reopen_closed``reopen_completed` 是两个独立权限,允许不同角色分别控制
2. **增量同步**:角色种子系统只做"加权限",不删除手动配置的额外权限
3. **操作者校验**:部分动作除权限外还校验操作者身份
- `open → undergoing`:操作者必须是 assignee
- `undergoing → completed`:操作者必须是 assignee + 需提交 comment
- `completed` 不走 role 权限控制,而是由 assignee 身份决定
---
## 4. 前端可见性(当前状态)
> ⚠ 前端按钮当前对所有项目成员可见,尚未根据用户权限做细粒度隐藏。
> 权限不足时由后端返回 403 阻止操作。
后续可通过前端 permission context 实现按钮可见性控制。
---
## 5. 自定义角色
除默认角色外,管理员可通过 Role Editor 页面自由创建角色并分配上述权限。新增的 9 个权限按 `milestone` / `task` / `propose` 三个 category 分组展示。

View File

@@ -0,0 +1,263 @@
# HarborForge — Proposal / Essential / Story Restricted 迁移说明
> 更新时间2026-03-29
> 本文档描述 Propose → Proposal 重命名、Proposal Accept 语义变更、Essential 新增、以及 story/* restricted 的迁移细节与兼容策略。
---
## 一、Propose → Proposal 命名调整
### 1.1 变更范围
| 层 | 旧命名 | 新命名 | 涉及文件 |
|---|--------|--------|---------|
| **数据库表** | `proposes` | `proposals`(新表名) | Alembic migration |
| **Model** | `Propose`, `ProposeStatus` | `Proposal`, `ProposalStatus` | `models/propose.py``models/proposal.py` |
| **Schema** | `ProposeCreate`, `ProposeUpdate`, `ProposeResponse`, `ProposeStatusEnum`, `ProposeBase` | `ProposalCreate`, `ProposalUpdate`, `ProposalResponse`, `ProposalStatusEnum`, `ProposalBase` | `schemas/schemas.py` |
| **Router** | `proposes.py`, 路由前缀 `/proposes` | `proposals.py`, 路由前缀 `/proposals` | `api/routers/proposes.py``api/routers/proposals.py` |
| **Helper 函数** | `_find_propose()`, `_serialize_propose()`, `_generate_propose_code()`, `_can_edit_propose()` | `_find_proposal()`, `_serialize_proposal()`, `_generate_proposal_code()`, `_can_edit_proposal()` | 同上 router 文件 |
| **Code 字段** | `propose_code` | `proposal_code` | Model、Schema、序列化逻辑 |
| **Activity log** | `entity_type="propose"` | `entity_type="proposal"` | `log_activity()` 调用处 |
| **权限 key** | `propose.accept`, `propose.reject`, `propose.reopen` | `proposal.accept`, `proposal.reject`, `proposal.reopen` | `check_permission()` 调用处、RBAC 数据 |
| **前端** | 页面标题、菜单、API 调用中的 `propose` 文案 | 统一为 `proposal` | 前端组件、路由、API 调用 |
| **CLI** | `hf propose`, `hf propose-create`, `hf propose-accept` 等 | `hf proposal`, `hf proposal create`, `hf proposal accept` 等 | CLI 命令注册与 help 文案 |
### 1.2 数据库迁移策略
```sql
-- Alembic migration
ALTER TABLE proposes RENAME TO proposals;
ALTER TABLE proposals CHANGE propose_code proposal_code VARCHAR(64);
```
- `proposal_code` 的已有编码值(如 `HF:P00001`)不变,仅字段名变更
- 所有外键引用(如 `proposals.id`)保持不变(表内 PK 不变)
### 1.3 API 兼容策略
**方案:直接切换,不保留旧路由**
理由:
- HarborForge 目前为内部系统,无外部消费者
- CLI 和前端同步更新,不存在旧客户端兼容问题
- 保留兼容别名会增加长期维护负担
具体做法:
1. 后端路由从 `/projects/{pid}/proposes` 切换为 `/projects/{pid}/proposals`
2. 前端所有 API 调用同步更新
3. CLI 命令同步更新
4. **不保留** `/proposes` 旧路由
> 如果未来需要面向外部提供 API应在 API 版本化层面处理兼容,而非在路由别名层面。
---
## 二、Proposal Accept 语义变化
### 2.1 旧行为
```
Proposal (open) ──accept──▶ Proposal (accepted)
单个 story/feature Task
feat_task_id 回填到 Proposal
```
- Accept 时自动创建 **1 个** `story/feature` task
- `feat_task_id` 字段记录生成的 task ID
### 2.2 新行为
```
Proposal (open)
├── Essential (feature) ──┐
├── Essential (improvement) ─┤── accept ──▶ Proposal (accepted)
└── Essential (refactor) ──┘ │
story/feature Task ← from Essential(feature)
story/improvement Task ← from Essential(improvement)
story/refactor Task ← from Essential(refactor)
全部落入选定 Milestone
```
- Proposal 下维护多个 **Essential**(可落地核心条目)
- Accept 时,遍历该 Proposal 下全部 Essential
- 按 Essential.type 映射生成对应 `story/*` task
- `feature``story/feature`
- `improvement``story/improvement`
- `refactor``story/refactor`
- 生成目标 Milestone 在 Accept 时明确选择(与旧行为一致)
- **批量创建在同一个数据库事务中完成**
### 2.3 Accept 前置条件变更
| 条件 | 旧 | 新 |
|------|----|----|
| 操作者权限 | `propose.accept` | `proposal.accept` |
| 目标 Milestone | 必须选择,状态 `open` | 同上 |
| Essential 数量 | 无此概念 | **必须至少 1 个 Essential**,否则 Accept 报错 |
### 2.4 Accept 返回值变更
- 旧:返回 Proposal 详情(含 `feat_task_id`
- 新:返回 Proposal 详情 + 嵌套的 Essential 列表 + 每个 Essential 生成的 task 信息
---
## 三、story/* 改为 Restricted 的影响面
### 3.1 当前状态
后端 `tasks.py` 中已有 restricted 机制:
```python
RESTRICTED_TYPE_SUBTYPES = {
("story", "feature"),
}
```
目前仅 `story/feature` 是 restricted。
### 3.2 变更内容
**所有 `story/*` 组合** 标记为 restricted
```python
RESTRICTED_TYPE_SUBTYPES = {
("story", "feature"),
("story", "improvement"),
("story", "refactor"),
}
```
### 3.3 影响面
| 入口 | 影响 | 处理 |
|------|------|------|
| **通用 Task Create API** (`POST /projects/{pid}/milestones/{mid}/tasks`) | 无法创建任何 `story/*` task | 已有 `_validate_task_type_subtype()` 校验,扩展 restricted 集合即可 |
| **Proposal Accept** | 内部受控入口,`allow_restricted=True` | 保留,唯一合法创建 `story/*` 的途径 |
| **前端 Task 创建表单** | `story` 类型从选择器中移除或标为不可选 | 前端调整 |
| **CLI `hf task create`** | 阻止 `--type story` | CLI 侧校验或依赖后端 403 |
| **CSV 导入**(如有) | 阻止 `story/*` 行 | 导入逻辑需加校验 |
| **Milestone 下 Task Create** (`milestones.py` 路由) | 已有 `story/feature` 限制逻辑 | 扩展为全部 `story/*` |
### 3.4 已有数据兼容
- 历史上通过旧 Accept 创建的 `story/feature` task **保持不变**
- 不需要迁移或修改已有 story task
- restricted 仅影响 **新建**,不影响已有记录的读取/更新/状态流转
---
## 四、旧数据与旧接口兼容策略
### 4.1 `feat_task_id` 字段
| 处理方式 | 说明 |
|---------|------|
| **保留字段,标记为 deprecated** | 数据库列保留,避免破坏已有数据 |
| **只读** | API 继续返回 `feat_task_id`(已有 Proposal 的值不丢失) |
| **新 Proposal 不再写入** | 新的 Accept 流程不再设置 `feat_task_id` |
| **新增追踪方式** | 通过 Essential → Task 的关联关系(`essential_id` 或关联表)替代 |
| **未来清理** | 等所有旧 Proposal 迁移完毕后,可选择 DROP 该列 |
### 4.2 旧 Proposal 数据读取
- 旧的 `accepted` 状态 Proposal 仍有 `feat_task_id`,前端继续支持 "View Generated Task" 跳转
- 旧 Proposal 没有 Essential详情页 Essential 区域显示空列表
- 不需要为旧 Proposal 补建 Essential 记录
### 4.3 Proposal Code 格式
- 已有编码如 `HF:P00001` 保持不变
- 新 Proposal 继续使用相同格式
- 字段名从 `propose_code` 变为 `proposal_code`,但值的格式不变
### 4.4 权限 Key 迁移
| 旧 | 新 | 迁移方式 |
|----|----|----|
| `propose.accept` | `proposal.accept` | 数据库中更新 RBAC permission 记录 |
| `propose.reject` | `proposal.reject` | 同上 |
| `propose.reopen` | `proposal.reopen` | 同上 |
```sql
-- RBAC permission key migration
UPDATE permissions SET key = REPLACE(key, 'propose.', 'proposal.') WHERE key LIKE 'propose.%';
```
> 如果权限 key 存储在 code 中而非数据库,则只需修改代码常量。
### 4.5 Activity Log 兼容
- 旧 activity log 中 `entity_type="propose"` 的记录保留不动
- 前端展示时做兼容映射:`propose` → 显示为 "Proposal"
- 新 activity log 统一使用 `entity_type="proposal"`
---
## 五、Essential 新增概要
### 5.1 数据模型
```
Essential
├── id (PK)
├── essential_code (UNIQUE) — 格式参考 ProjectCode / TaskCode
├── proposal_id (FK → proposals.id)
├── type (Enum: feature, improvement, refactor)
├── title
├── description (nullable)
├── created_by_id (FK → users.id, nullable)
├── created_at
└── updated_at
```
### 5.2 EssentialCode 编码
- 格式:`{proposal_code}:E{i:05x}`
- 示例:`HF:P00001:E00001`
- 每个 Proposal 独立递增
### 5.3 Essential 生命周期
1. Proposal `open` 状态下可创建/编辑/删除 Essential
2. Proposal Accept 时,全部 Essential 用于生成 `story/*` task
3. Proposal 进入 `accepted`/`rejected`Essential 不可修改
### 5.4 API 端点
| 操作 | 方法 | 路径 |
|------|------|------|
| 列出 | GET | `/projects/{pid}/proposals/{proposal_id}/essentials` |
| 创建 | POST | `/projects/{pid}/proposals/{proposal_id}/essentials` |
| 详情 | GET | `/projects/{pid}/proposals/{proposal_id}/essentials/{id}` |
| 编辑 | PATCH | `/projects/{pid}/proposals/{proposal_id}/essentials/{id}` |
| 删除 | DELETE | `/projects/{pid}/proposals/{proposal_id}/essentials/{id}` |
---
## 六、迁移执行顺序
推荐按以下顺序执行,确保每一步可独立验证:
1. **后端 Model/Schema 重命名**`Propose``Proposal`BE-PR-001, BE-PR-002
2. **数据库 migration** — 表名、字段名变更
3. **新增 Essential Model/Schema**BE-PR-003, BE-PR-004, BE-PR-005
4. **新增 Essential CRUD API**BE-PR-006
5. **重构 Accept 逻辑**BE-PR-007, BE-PR-008
6. **收紧 story restricted**BE-PR-009
7. **清理 feat_task_id**BE-PR-010
8. **前端同步更新**FE-PR-001 ~ FE-PR-005
9. **CLI 同步更新**CLI-PR-001 ~ CLI-PR-004
10. **测试补全**BE-PR-011, TEST-BE-PR-001, TEST-FE-PR-001, TEST-CLI-PR-001
---
## 七、风险与注意事项
1. **表重命名的 downtime**`ALTER TABLE RENAME` 在 MySQL 中是瞬时操作,但需确保无长事务锁表
2. **权限 key 更新** — 如果有缓存层,需要在迁移后清理缓存
3. **前后端同步部署** — 建议同时部署前后端,避免前端调旧路由 404
4. **回滚方案** — 如需回滚反向执行表重命名和字段重命名即可Essential 表作为新增表,回滚时 DROP 即可

163
docs/propose-flow.md Normal file
View File

@@ -0,0 +1,163 @@
# HarborForge — Propose → Feature Story → Milestone 流程
> 更新时间2026-03-18
> 本文档描述 feature 进入 milestone 的完整流程。
---
## 1. 流程总览
```
用户创建 Propose 负责人审阅 系统自动生成
│ │ │
▼ ▼ ▼
Propose (open) ──accept──▶ Propose (accepted)
│ │
│ ▼
│ Feature Story Task (pending)
│ 归属选定 milestone
──reject──▶ Propose (rejected)
──reopen──▶ Propose (open) ── 重新审阅 ──▶ ...
```
---
## 2. 详细步骤
### Step 1创建 Propose
- 用户在 project 下创建 propose
- 填写 title + description
- 系统自动生成 `propose_code`(格式:`{proj_code}:P{i:05x}`
- 初始状态:`open`
### Step 2审阅
- 负责人在 Propose 详情页查看内容
- `open` 状态下可选操作:
- **Accept** — 接受并生成 feature task
- **Reject** — 拒绝(建议填写 reason
- Propose 创建者在 `open` 状态下可编辑 title/description
### Step 3aAccept
前置条件:
- 操作者拥有 `propose.accept` 权限
- 选择一个 `open` 状态的目标 milestone同 project
系统执行:
1. Propose status → `accepted`
2. 在目标 milestone 下自动创建 `story/feature` task
- 继承 title、description、created_by
- 默认状态 `pending`
3. 自动回填 `feat_task_id`(只读字段)
4. 写入 activity log
Accept 后:
- Propose 详情页显示 "View Generated Task" 跳转按钮
- Propose 主体不可再编辑
### Step 3bReject
前置条件:
- 操作者拥有 `propose.reject` 权限
系统执行:
1. Propose status → `rejected`
2. 写入 reject reasonactivity log
Reject 后:
- Propose 详情页显示 "Reopen" 按钮
- Propose 主体不可编辑
### Step 4Reopen可选
前置条件:
- 操作者拥有 `propose.reopen` 权限
- Propose 当前状态为 `rejected`
系统执行:
1. Propose status → `open`(复用原 propose不创建新记录
2. 写入 reopen 记录
Reopen 后:
- 可再次编辑 title/description
- 可再次 accept 或 reject
---
## 3. Feature Task 生命周期
Accept 生成的 feature story task 遵循标准 task 状态机:
```
pending → open → undergoing → completed
(触发 milestone auto-complete
仅当该 task 是 release task 时)
```
关键约束:
- Feature story task **不能**通过通用 create task 页面创建
- Milestone 进入 `freeze` 后,不再接受新的 feature story
- Milestone 非 `open` 时,已有 feature story task 的 body 字段锁定
---
## 4. Milestone 完整生命周期(含 propose
```
1. 创建 milestone (open)
2. 通过 propose → accept 添加 feature story tasks
3. 创建 release maintenance task通过 milestone endpoint
4. Freeze milestone需有且仅有 1 个 release task
5. 满足依赖后 Start milestone → undergoing
6. Tasks 开始执行pending → open → undergoing → completed
7. Release maintenance task 完成 → milestone 自动 completed
```
---
## 5. Propose 编码规则
- 格式:`{proj_code}:P{i:05x}`
- 示例:`HF:P00001`, `HF:P00002`, `HF:P0000a`
- 每个 project 独立递增
- 并发安全:数据库 unique 约束保底
---
## 6. API 端点
| 操作 | 方法 | 路径 |
|---------|--------|--------------------------------------------------|
| 创建 | POST | `/projects/{pid}/proposes` |
| 列表 | GET | `/projects/{pid}/proposes` |
| 详情 | GET | `/projects/{pid}/proposes/{id}` |
| 编辑 | PATCH | `/projects/{pid}/proposes/{id}` |
| Accept | POST | `/projects/{pid}/proposes/{id}/actions/accept` |
| Reject | POST | `/projects/{pid}/proposes/{id}/actions/reject` |
| Reopen | POST | `/projects/{pid}/proposes/{id}/actions/reopen` |
---
## 7. CLI 命令
```bash
# 列出 proposes
harborforge proposes --project <project_id>
# 创建 propose
harborforge propose-create "My Feature Idea" --project <project_id>
# Accept需指定 milestone
harborforge propose-accept <propose_id> --project <project_id> --milestone <milestone_id>
# Reject可选 reason
harborforge propose-reject <propose_id> --project <project_id> --reason "Not in scope"
# Reopen
harborforge propose-reopen <propose_id> --project <project_id>
```

View File

@@ -0,0 +1,185 @@
# HarborForge — 状态机总览
> 更新时间2026-03-18
> 本文档描述 milestone、task、propose 三大实体的状态枚举、流转规则及关键约束。
---
## 1. Milestone 状态机
### 1.1 状态枚举
| 状态 | 含义 | 终态 |
|-------------|--------------------------|------|
| `open` | 新建,可接纳 feature | ✗ |
| `freeze` | 范围冻结,准备执行 | ✗ |
| `undergoing`| 正在执行 | ✗ |
| `completed` | 正常完成(自动触发) | ✓ |
| `closed` | 废弃 / 取消 | ✓ |
### 1.2 状态流转
```
open ──freeze──▶ freeze ──start──▶ undergoing ──(auto)──▶ completed
│ │ │
└──close──▶ closed ◀──close──┘ ◀──close──┘
```
- **open → freeze**:需有且仅有 1 个 `maintenance/release` task
- **freeze → undergoing**所有前置依赖milestone + task必须已 completed自动记录 `started_at`
- **undergoing → completed**:唯一的 `release maintenance task` 完成时自动触发
- **open/freeze/undergoing → closed**:需 `milestone.close` 权限
### 1.3 编辑限制
| 状态 | 基本信息编辑 | 新增 feature story | 新增其他 task | 删除 milestone |
|-------------|-------------|-------------------|--------------|---------------|
| `open` | ✓ | ✓ | ✓ | ✓ |
| `freeze` | 范围字段锁定 | ✗ | ✓ | ✓ |
| `undergoing`| 范围字段锁定 | ✗ | ✗ | ✗ |
| `completed` | ✗ | ✗ | ✗ | ✗ |
| `closed` | ✗ | ✗ | ✗ | ✗ |
范围字段 = title, description, due_date, planned_release_date, depend_on_milestones, depend_on_tasks
---
## 2. Task 状态机
### 2.1 状态枚举
| 状态 | 含义 | 终态 |
|-------------|----------------------|------|
| `pending` | 等待(被 milestone 或依赖锁住) | ✗ |
| `open` | 可开始,尚未开工 | ✗ |
| `undergoing`| 正在处理 | ✗ |
| `completed` | 正常完成 | ✓* |
| `closed` | 废弃 / 取消 | ✓* |
*支持受控 reopen
### 2.2 状态流转
```
pending ──open──▶ open ──start──▶ undergoing ──finish──▶ completed
│ │ │ │
└──close──▶ closed ◀──close──┘ ◀──close──┘ │
│ │
└◀────────────── reopen ──────────────────────────────┘
└──────────── reopen ──── completed
```
### 2.3 流转条件
| 流转 | 条件 |
|------------------------|------------------------------------------------|
| pending → open | milestone 为 undergoing + task depend_on 全部 completed |
| open → undergoing | assignee 非空 + 操作者是 assignee |
| undergoing → completed | 操作者是 assignee + 必须提交 completion comment |
| any → closed | 需 `task.close` 权限 |
| closed → open | 需 `task.reopen_closed` 权限;清除 finished_on |
| completed → open | 需 `task.reopen_completed` 权限;清除 finished_on |
### 2.4 编辑限制
| 状态 | 主体编辑 |
|-------------|-------------------------------|
| `pending` | ✓ |
| `open` (无 assignee) | ✓ (任何项目成员) |
| `open` (有 assignee) | 仅 assignee + admin |
| `undergoing`| ✗ |
| `completed` | ✗ |
| `closed` | ✗ |
Feature story task 在 milestone 非 open 时body 字段额外锁定。
### 2.5 与 Milestone 联动
- milestone `open/freeze` → task 只能停留在 `pending``closed`
- milestone `undergoing` → task 才允许从 `pending` 往后推进
- milestone `completed/closed` → task 不再继续推进
---
## 3. Propose 状态机
### 3.1 状态枚举
| 状态 | 含义 | 终态 |
|-----------|-----------|------|
| `open` | 新建/待审 | ✗ |
| `accepted`| 已接受 | ✓ |
| `rejected`| 已拒绝 | ✓* |
*支持 reopen
### 3.2 状态流转
```
open ──accept──▶ accepted
└──reject──▶ rejected ──reopen──▶ open
```
### 3.3 流转条件
| 流转 | 条件 |
|------------------|----------------------------------------------------------|
| open → accepted | 需 `propose.accept` 权限 + 选择 open 状态的目标 milestone |
| open → rejected | 需 `propose.reject` 权限;建议填写 reason |
| rejected → open | 需 `propose.reopen` 权限;复用原 propose |
### 3.4 Accept 副作用
- 自动创建 `story/feature` task继承 title/description/created_by
- 新 task 默认状态 `pending`
- 自动填写 `feat_task_id`(只读)
### 3.5 编辑限制
| 状态 | 主体编辑 |
|-----------|----------------------------|
| `open` | ✓ (creator / admin / mgr) |
| `accepted`| ✗ |
| `rejected`| ✗ |
---
## 4. 创建限制
以下 task 类型**不能**通过通用 create task 页面创建:
| 类型 | 正确创建入口 |
|-----------------|------------------------|
| story/feature | propose → accept |
| maintenance/release | milestone endpoint |
---
## 5. 旧枚举映射DB 迁移)
### Milestone
| 旧值 | 新值 |
|-------------|-------------|
| `open` | `open` |
| `pending` | `open` |
| `deferred` | `closed` |
| `progressing`| `undergoing`|
| `closed` | `closed` |
### Task
| 旧值 | 新值 |
|-------------|-------------|
| `open` | `open` |
| `pending` | `pending` |
| `progressing`| `undergoing`|
| `closed` | `closed` |
### Task Type
| 旧值 | 新值 |
|--------|--------|
| `task` | `issue`|

106
docs/wave-2026-03-scope.md Normal file
View File

@@ -0,0 +1,106 @@
# 本波开发范围说明
> Date: 2026-03-29
> Wave: 2026-03 (Calendar & Proposal 重构)
---
## 一、两条功能线概述
本波开发包含两条独立的功能线:
### 功能线 1Calendar 日程系统(独立功能线)
全新功能模块,为 HarborForge 增加日程调度能力。
**包含内容:**
- `TimeSlot` 日程槽模型与 CRUD API
- `SchedulePlan` 周期性计划模型与管理 API
- Agent 状态管理Idle / Busy / OnCall / Exhausted / Offline
- `MinimumWorkload` 最小工作量配置
- Plan 虚拟 slot 标识与物化策略
- Overlap 校验与 Workload warning 规则
- 不可变过去 slot 规则
- Agent 心跳唤醒机制与 Exhausted 恢复
- 前端 Calendar 页面
- CLI `hf calendar` 命令组
- OpenClaw 插件 Calendar 心跳联动
### 功能线 2Proposal / Essential / Story restricted项目结构调整线
对已有的 Propose 流程进行重构和增强。
**包含内容:**
- `Propose``Proposal` 统一重命名
- 新增 `Essential` 概念及数据模型
- `EssentialCode` 编码规则
- Proposal Accept 语义变更:遍历 Essential 批量生成 story task
- `story/*` 整个大类设为 restricted仅允许通过 Proposal Accept 创建
- 清理旧 `feat_task_id` 语义
- 前端 Proposal 详情页 Essential 管理
- CLI Proposal Essential 子命令
---
## 二、两条线的交叉点
两条功能线设计上相互独立,交叉点仅限于以下层面:
| 交叉点 | 说明 |
|--------|------|
| `event_data` | Calendar 的 TimeSlot 通过 `event_data` JSON 字段引用 Task/Essential code但不直接依赖 Proposal/Essential 的数据模型 |
| Agent 调度引用层 | Calendar 心跳唤醒 Agent 执行任务时,任务可能是 story task由 Proposal Accept 生成),但 Calendar 只关心 task code不关心其来源 |
**关键原则:**
- Calendar 不直接 FK 到 Essential 或 Proposal 表
- Proposal/Essential 不直接 FK 到 TimeSlot 或 SchedulePlan 表
- 两者通过 code 引用(字符串)松耦合
- 可以独立开发、独立测试、独立部署
---
## 三、本波必须完成 vs 仅设计保留
### ✅ 必须本波完成
#### Calendar 线
| 范围 | 任务 ID 区间 | 说明 |
|------|-------------|------|
| 后端基础模型 | BE-CAL-001 ~ BE-CAL-008 | TimeSlot、SchedulePlan、Agent 扩展、MinimumWorkload、物化策略、overlap/warning/不可变规则 |
| 后端 API | BE-CAL-API-001 ~ BE-CAL-API-007 | 日程 CRUD、计划 CRUD、date-list |
| 后端 Agent 协作 | BE-AGT-001 ~ BE-AGT-004 | 心跳查询、状态流转、多 slot 竞争、Exhausted 恢复 |
| 前端 | FE-CAL-001 ~ FE-CAL-005 | 页面骨架、slot 列表、计划列表、CRUD 交互、状态提示 |
| CLI | CLI-CAL-001 ~ CLI-CAL-010 | `hf calendar` 全部子命令 |
| 插件 | PLG-CAL-001 ~ PLG-CAL-004 | 心跳格式、唤醒处理、Deferred 分支、ScheduledGatewayRestart |
#### Proposal 线
| 范围 | 任务 ID 区间 | 说明 |
|------|-------------|------|
| 后端 | BE-PR-001 ~ BE-PR-011 | 重命名、Essential 模型/schema/API、Accept 重构、story restricted、测试 |
| 前端 | FE-PR-001 ~ FE-PR-005 | 重命名、Essential 列表/表单、Accept milestone 选择、story 限制 |
| CLI | CLI-PR-001 ~ CLI-PR-004 | 重命名、Essential 命令、Accept 更新、story 限制 |
#### 文档与测试
| 范围 | 任务 ID 区间 | 说明 |
|------|-------------|------|
| 文档 | DOC-001 ~ DOC-003 | 范围说明、迁移说明、验收清单 |
| 测试 | TEST-* | 各子模块测试补充 |
### 📐 仅设计保留(不在本波实现)
| 内容 | 说明 |
|------|------|
| Entertainment 事件子类型 | `event_data` 中 Entertainment 的具体结构待设计 |
| 用户级时区支持 | 本波统一使用服务器时区 |
| 前端日程表详细 UI 设计 | 本波实现基础功能骨架,精细 UI 留后续迭代 |
| Agent 唤醒的提示词模板 | 本波实现唤醒机制,提示词模板留后续打磨 |
| Proposal/Essential 数据迁移工具 | 旧数据兼容读取即可,自动化迁移工具留后续 |
---
## 四、Bug Fix附带修复
- **acc-mgr 密码修改限制**:后端禁止修改 acc-mgr 用户密码;前端隐藏修改密码入口

View File

@@ -0,0 +1,169 @@
# Calendar 验收清单
> 基于 `NEXT_WAVE_DEV_DIRECTION.md` 设计文档整理
> Date: 2026-03-29
---
## 一、后端验收项 (Backend)
### 1.1 数据模型
- [ ] `TimeSlot` 模型已创建字段完整slot_id, user_id, date, slot_type, estimated_duration, scheduled_at, started_at, attended, actual_duration, event_type, event_data, priority, status, plan_id, created_at, updated_at
- [ ] `SchedulePlan` 模型已创建字段完整id, user_id, slot_type, estimated_duration, event_type, event_data, at_time, on_day, on_week, on_month, created_at, updated_at
- [ ] Agent 表已扩展字段status, last_heartbeat, exhausted_at, recovery_at, exhaust_reason
- [ ] 枚举类型已定义SlotType (Work, OnCall, Entertainment, System)、SlotStatus (NotStarted, Ongoing, Deferred, Skipped, Paused, Finished, Aborted)、EventType (Job, Entertainment, SystemEvent)、AgentStatus (Idle, OnCall, Busy, Exhausted, Offline)、ExhaustReason (RateLimit, Billing)
- [ ] SchedulePlan 周期参数层级约束已实现on_month 需 on_weekon_week 需 on_dayat 始终必填)
- [ ] MinimumWorkload 存储方案已实现(用户级配置读写)
### 1.2 Slot ID 策略与物化
- [ ] 已物化 slot 使用数据库自增 ID
- [ ] Plan 虚拟 slot 使用 `plan-{plan_id}-{date}` 标识
- [ ] 虚拟 slot 被 edit/cancel 时物化到数据库,断开 plan 关联
- [ ] Plan 不预展开,只存规则
### 1.3 验证规则
- [ ] Overlap 检测:同日时间重叠 → 拒绝并报错
- [ ] Overlap 检测区分 create 与 edit 场景
- [ ] MinimumWorkload warning不满足时返回 warning 但允许提交
- [ ] Warning 数据结构统一定义
- [ ] 计算 daily / weekly / monthly / yearly 工作量
### 1.4 不可变性规则
- [ ] 禁止 edit 过去的 slot
- [ ] 禁止 cancel 过去的 slot
- [ ] plan-edit / plan-cancel 不追溯过去已物化 slot
### 1.5 Calendar API
- [ ] `POST` 单次日程创建:支持 slot_type, scheduled_at, estimated_duration, job/system/event_data接入 overlap 与 workload warning
- [ ] `GET` 某日 Calendar 查询:返回真实 slot + 合成当日 plan 虚拟 slot统一排序
- [ ] `PATCH/PUT` Calendar 编辑:支持真实 slot 编辑 + 虚拟 slot 编辑并触发物化
- [ ] `DELETE/POST` Calendar 取消:支持真实 slot cancel + 虚拟 slot cancel 并触发物化,状态字段更新
- [ ] `POST` plan-schedule创建周期性计划
- [ ] `GET` plan-list列出所有计划
- [ ] `PATCH/PUT` plan-edit编辑计划不追溯过去已物化数据
- [ ] `POST/DELETE` plan-cancel取消计划不追溯过去已物化数据
- [ ] `GET` date-list仅列出有已物化未来 slot 的日期,排除纯 plan 未物化日期
### 1.6 Agent / 心跳协作
- [ ] 心跳查询服务:筛选当天 NotStarted / Deferred 且 scheduled_at 已过的 slot按优先级排序
- [ ] Agent 状态流转Idle ↔ Busy/OnCall、超时→Offline、API错误→Exhausted
- [ ] 多 slot 竞争:选最高 priority 执行,其余 DeferredDeferred slot priority += 1
- [ ] Exhausted 恢复时间解析:解析 retry-after / reset in / resets at失败默认 5 小时,到期恢复 Idle
---
## 二、前端验收项 (Frontend)
### 2.1 页面骨架
- [ ] Calendar 路由入口已添加
- [ ] 侧边栏 Calendar 入口已添加
- [ ] Calendar 基础页面布局完成
### 2.2 日程展示
- [ ] 某日 slot 列表展示(时间轴或列表视图)
- [ ] 区分真实 slot 与 plan 虚拟 slot视觉区分
- [ ] 展示 status / type / duration / priority 等核心字段
### 2.3 计划展示
- [ ] 计划列表展示:规则、周期参数
- [ ] 支持从计划列表跳转编辑
### 2.4 日程操作交互
- [ ] 新建 slot 表单(含 slot_type, scheduled_at, estimated_duration, event_data 等)
- [ ] 编辑 slot 表单
- [ ] Cancel 操作确认弹窗
- [ ] 展示后端返回的 warningworkload 不足等)
### 2.5 状态提示
- [ ] Deferred 状态提示
- [ ] Overlap 报错展示
- [ ] Workload warning 展示
- [ ] Exhausted 状态展示(含预计恢复时间)
### 2.6 权限
- [ ] 普通用户仅查看/调整自己的日程表
- [ ] Admin 可查看/调整所有用户的日程表
---
## 三、CLI 验收项 (CLI)
### 3.1 命令组
- [ ] `hf calendar` 命令组已注册help 正常输出
### 3.2 日程操作命令
- [ ] `hf calendar schedule <slot-type> <scheduled-at> <estimated-duration> [--job <code>] [--date <yyyy-mm-dd>]` 正常工作
- [ ] `hf calendar show [--date <yyyy-mm-dd>]` 正常展示当日日程(真实 + 虚拟 slot 合并)
- [ ] `hf calendar edit [--date] <slot-id> [--slot-type] [--estimated-duration] [--job] [--scheduled-at]` 正常工作
- [ ] `hf calendar cancel [--date] <slot-id>` 正常工作
- [ ] `hf calendar date-list` 列出有已物化日程的未来日期
### 3.3 计划操作命令
- [ ] `hf calendar plan-schedule <slot-type> <estimated-duration> --at <HH:mm> [--on-day] [--on-week] [--on-month]` 正常工作
- [ ] `hf calendar plan-list` 列出所有计划
- [ ] `hf calendar plan-edit <plan-id> [options]` 正常工作
- [ ] `hf calendar plan-cancel <plan-id>` 正常工作
### 3.4 输出格式
- [ ] 所有命令支持 JSON 输出(`--json` 或类似选项)
- [ ] 错误信息overlap 等)清晰明确
- [ ] Warning 信息workload 不足等)正常展示
### 3.5 用户创建扩展
- [ ] `hf user create` 支持 `--agent-id` + `--claw-identifier` 参数
- [ ] 两参数必须同时出现或同时不出现
- [ ] pcexec 模式下自动从环境变量 / openclaw config 获取
---
## 四、插件联动验收项 (OpenclawPlugin)
### 4.1 心跳请求
- [ ] 插件每分钟向 HarborForge 发送心跳
- [ ] 心跳请求正确传递 claw_identifier 和 agent_id
- [ ] 正确接收返回的 slot 列表
### 4.2 唤醒逻辑
- [ ] Agent Idle 时:唤醒 agent透传任务上下文更新 attended/started_at/status
- [ ] Agent 非 Idle 时:上报 Deferred
- [ ] 多 slot 竞争时正确选择最高 priority
### 4.3 状态管理
- [ ] 超过 2 分钟无心跳 → Agent 标记 Offline
- [ ] API rate-limit / billing 错误 → Agent 标记 Exhausted
- [ ] Exhausted 恢复计时器到期 → Agent 恢复 Idle
### 4.4 ScheduledGatewayRestart 处理
- [ ] 收到 ScheduledGatewayRestart 事件后持久化状态
- [ ] 发送最终心跳
- [ ] 暂停定时任务
---
## 五、跨模块集成验收
- [ ] 完整流程:创建 plan → 心跳触发物化 → Agent 被唤醒执行 → slot 状态更新为 Finished
- [ ] 完整流程schedule 单次日程 → CLI 查看 → 前端查看 → Agent 执行
- [ ] Overlap / Warning 全链路:后端检测 → CLI 展示 → 前端展示
- [ ] Exhausted 全链路Agent 报错 → 后端标记 Exhausted → 前端展示 → 恢复后自动 Idle

View File

@@ -0,0 +1,382 @@
# HarborForge Calendar System — Design Document
> Date: 2026-03-22
---
## Overview
为 HarborForge 新增日程表Calendar系统支持 Agent/人类用户的任务调度、周期性计划、以及通过 OpenClaw 插件心跳自动唤醒 Agent 执行日程。
同时记录一项项目结构调整:
- Propose 改名为 Proposal
- Proposal Accept 不再生成单个 Feature Task
- 改为在 Proposal 下维护多个 EssentialAccept 时将该 Proposal 下所有 Essential 按类型生成对应的 story task并落到 Proposal 选择的 Milestone
- story 整个大类改为 restricted只允许通过 Proposal Accept 创建
- Essential 拥有独立的 EssentialCode编码风格参考 ProjectCode / TaskCode 等既有结构
同时包含一个 bug fixacc-mgr 用户密码不可修改,前端隐藏修改密码入口。
---
## 一、数据模型
### 1.1 TimeSlot日程槽
| 字段 | 类型 | 说明 |
|------|------|------|
| slot_id | int (PK) | 已物化 slot 的数据库 ID |
| user_id | FK -> users.id | 所属用户 |
| date | date | 日期 |
| slot_type | Enum(Work, OnCall, Entertainment, System) | 槽类型 |
| estimated_duration | int (1-50) | 预估时长(分钟),设计上限 50 分钟,超过需拆分 |
| scheduled_at | time (00:00-23:00) | 计划开始时间 |
| started_at | time, nullable | 实际开始时间 |
| attended | bool, default false | 是否已出席 |
| actual_duration | int (0-65535), nullable | 实际时长(分钟),无上限 |
| event_type | Enum(Job, Entertainment, SystemEvent), nullable | 事件类型 |
| event_data | JSON, nullable | 事件详情(见下方 Event 子类型) |
| priority | int (0-99) | 优先级 |
| status | Enum(NotStarted, Ongoing, Deferred, Skipped, Paused, Finished, Aborted) | 状态 |
| plan_id | FK -> schedule_plans.id, nullable | 来源计划(物化自 plan 时填入,被 edit/cancel 后置 NULL |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
### 1.2 Event 子类型(存储在 event_data JSON 中)
**Job:**
```json
{
"type": "Task|Support|Meeting|Essential",
"code": "TASK-42",
"working_sessions": ["session-id-1", "session-id-2"]
}
```
**SystemEvent:**
```json
{
"event": "ScheduleToday|SummaryToday|ScheduledGatewayRestart"
}
```
- `ScheduleToday` — 每日日程规划
- `SummaryToday` — 每日总结
- `ScheduledGatewayRestart` — OpenClaw 网关计划重启前触发;插件收到后应持久化状态、发送最终心跳、暂停定时任务
**Entertainment:**
```
待设计
```
### 1.3 SchedulePlan周期性计划
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int (PK) | plan-id |
| user_id | FK -> users.id | 所属用户 |
| slot_type | Enum(Work, OnCall, Entertainment, System) | 槽类型 |
| estimated_duration | int (1-50) | 预估时长 |
| event_type | Enum(Job, Entertainment, SystemEvent), nullable | 事件类型 |
| event_data | JSON, nullable | 事件详情 |
| at_time | time | 每天的计划时间 (--at HH:mm) |
| on_day | Enum(Sun, Mon, Tue, Wed, Thu, Fri, Sat), nullable | 星期几 (--on-day) |
| on_week | int (1-4), nullable | 第几周 (--on-week) |
| on_month | Enum(Jan-Dec), nullable | 月份 (--on-month) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
**周期参数层级约束:**
- 使用 `--on-month``--on-week` 必须也用
- 使用 `--on-week``--on-day` 必须也用
- `--at` 始终必填
**示例:**
- `--at 09:00 --on-day Sun --on-week 1 --on-month Jan` → 每年一月第一周周日 09:00
- `--at 09:00 --on-day Sun --on-week 1` → 每月第一周周日 09:00
- `--at 09:00 --on-day Sun` → 每周日 09:00
- `--at 09:00` → 每天 09:00
### 1.4 Agent 表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int (PK) | |
| user_id | FK -> users.id, UNIQUE | 关联用户 |
| agent_id | VARCHAR, UNIQUE | OpenClaw agent name ($AGENT_ID) |
| claw_identifier | VARCHAR | OpenClaw 实例 identifier与 Monitor 碰巧一致,无 FK |
| status | Enum(Idle, OnCall, Busy, Exhausted, Offline), default Idle | Agent 当前状态 |
| last_heartbeat | datetime, nullable | 最后心跳时间 |
| created_at | datetime | 创建时间 |
### 1.5 MinimumWorkload最小工作量配置
```json
{
"daily": { "work": 0, "on_call": 0, "entertainment": 0 },
"weekly": { "work": 0, "on_call": 0, "entertainment": 0 },
"monthly": { "work": 0, "on_call": 0, "entertainment": 0 },
"yearly": { "work": 0, "on_call": 0, "entertainment": 0 }
}
```
值为分钟数 (0-65535)。存储方式待定(可作为用户级配置存 JSON 字段或独立表)。
---
## 二、Slot ID 策略
- **已物化的 slot**:使用数据库自增 ID
- **Plan 虚拟 slot**(未物化):使用 `plan-{plan_id}-{date}` 格式
- 当虚拟 slot 被 `edit``cancel` 时,物化到数据库,获得真实 ID同时该日期该 plan 不再生成虚拟 slot
---
## 三、存储与缓存策略
### 3.1 Plan 不预展开
Plan 只存规则,不为每一天生成数据行。
### 3.2 物化时机
以下情况写入 time_slots 表:
1. `hf calendar schedule` 手动创建
2. Plan 的虚拟 slot 被 `edit``cancel`(物化后断开 plan 关联)
3. 每天预计算:服务器每日将当天所有 plan 匹配的 slot 物化到缓存/数据库
### 3.3 当日缓存
- 每天(凌晨或首次心跳时)预计算当天所有 plan → 物化为当日 slot 缓存
- 当天新增 `schedule` / `plan-schedule` 影响当天时,同步更新缓存
### 3.4 不可变性
- `cancel` / `edit` 不能操作过去的 slot
- `plan-cancel` / `plan-edit` 不追溯过去已物化的 slot
---
## 四、时区
统一使用 HarborForge 服务器时区,不做用户级时区。
---
## 五、验证规则
`schedule` / `plan-schedule` 提交时验证:
1. **Overlap 检测**:与同日已有 slot 时间重叠 → **拒绝,报错**
2. **最小工作量检查**:不满足 MinimumWorkload 配置 → **警告,但允许提交**
---
## 六、Agent 唤醒机制
### 6.1 心跳流程
1. 插件每分钟向 HarborForge 服务器发送心跳
2. 服务器返回该插件claw_identifier对应所有 Agent 当前需要执行的日程
- 筛选条件:当天 slotstatus 为 NotStarted 或 Deferredscheduled_at 已过
3. 插件检查 Agent 状态
### 6.2 唤醒逻辑
**Agent 状态为 Idle**
- 唤醒 Agent提供提示词开始工作
- 向服务器设置 Agent status = Busy 或 OnCall取决于 slot_type
- 设置 slot: attended = true, started_at = now, status = Ongoing
**Agent 状态非 Idle**
- 设置 slot status = Deferred
### 6.3 多 Slot 竞争
- 选 priority 最高的执行,其余 Deferred 且 priority += 1
- 通知 Agent 当前任务完成后重新规划所有 Deferred + NotStarted 的 slot
### 6.4 状态转移
| 触发条件 | Agent Status 变化 |
|---------|-----------------|
| 超过 2 分钟无心跳 | → Offline |
| 无待执行日程 | → Idle |
| 被 TimeSlot 唤醒 | → Busy / OnCall |
| 完成 TimeSlot | → Idle |
| API rate-limit 或 billing 错误 | → Exhausted |
| Exhausted 恢复计时器到期 | → Idle |
### 6.5 Exhausted 状态详细规则
**前提:** 所有 Agent 只使用一个主模型,没有 fallback 模型。
**进入条件:**
- Agent 调用 LLM API 时收到 rate-limit 错误HTTP 429 等)
- Agent 调用 LLM API 时收到 billing 相关错误(额度不足、配额耗尽等)
**恢复逻辑:**
- 解析错误信息,查找类似 `reset in X mins``retry after X``resets at <timestamp>` 的模式
- 如果能解析出时间 → 设置 **X 分钟** 后恢复为 Idle
- 如果无法解析 → 默认 **5 小时** 后恢复为 Idle
**Exhausted 期间行为:**
- Agent 视为不可用,不被心跳唤醒
- 待执行的 slot 设为 Deferred
- 前端/Monitor 显示 Exhausted 状态 + 预计恢复时间
**Agent 表扩展字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| exhausted_at | datetime, nullable | 进入 Exhausted 的时间 |
| recovery_at | datetime, nullable | 预计恢复时间 |
| exhaust_reason | Enum(RateLimit, Billing), nullable | 原因 |
---
## 七、CLI 命令
### 7.1 日程操作
```bash
# 创建单次日程
hf calendar schedule <slot-type> <scheduled-at> <estimated-duration> \
[--job <code>] [--date <yyyy-mm-dd>]
# 查看某天日程
hf calendar show [--date <yyyy-mm-dd>]
# 取消日程plan 来源的 slot 物化后断开 plan
hf calendar cancel [--date <yyyy-mm-dd>] <slot-id>
# 编辑日程plan 来源的 slot 物化后断开 plan
hf calendar edit [--date <yyyy-mm-dd>] <slot-id> \
[--slot-type <type>] [--estimated-duration <mins>] \
[--job <code>] [--scheduled-at <HH:mm>]
# 列出所有有已物化日程的未来日期(纯 plan 的不算)
hf calendar date-list
```
### 7.2 计划操作
```bash
# 创建周期性计划
hf calendar plan-schedule <slot-type> <estimated-duration> \
--at <HH:mm> [--on-day <day>] [--on-week <1-4>] [--on-month <month>]
# 列出所有计划
hf calendar plan-list
# 取消计划(不追溯过去)
hf calendar plan-cancel <plan-id>
# 编辑计划(不追溯过去)
hf calendar plan-edit <plan-id> \
[--at <HH:mm>] [--on-day <day>] [--on-week <1-4>] [--on-month <month>] \
[--slot-type <type>] [--estimated-duration <mins>]
```
### 7.3 用户创建Agent 支持)
```bash
hf user create <username> [--agent-id <id>] [--claw-identifier <id>] ...
```
- `--agent-id` + `--claw-identifier` 必须同时出现或同时不出现
- pcexec 模式下:
- `--agent-id``$AGENT_ID`
- `--claw-identifier``openclaw config get plugins.harbor-forge.identifier`
- 后端 `POST /users` 扩展:接受 `agent_id` + `claw_identifier`,创建 User 同时写入 agents 表
---
## 八、项目结构调整记录(与 Calendar 相关联的设计备注)
### 8.1 命名调整
- `Propose` 统一改名为 `Proposal`
### 8.2 新结构
```text
Project
└─ Proposal
├─ Essential
│ ├─ feature
│ ├─ improvement
│ └─ refactor
└─ accept -> 将该 Proposal 下所有 Essential 生成对应类型的 story task并创建到 Proposal 选择的 Milestone
```
### 8.3 Proposal Accept 语义变更
旧行为:
- Proposal Accept 后生成单个 `story/feature` task
新行为:
- Proposal Accept **不再生成单个 Feature Task**
- 每个 Proposal 可维护多个 Essential
- Accept 时,遍历该 Proposal 下全部 Essential
- 按 Essential 类型映射生成对应的 story task
- `feature` -> `story/feature`
- `improvement` -> `story/improvement`
- `refactor` -> `story/refactor`
- 生成目标 Milestone 由 Proposal 在 Accept 前或 Accept 时明确选择
### 8.4 Story 创建限制
- `story` 整个大类视为 **restricted**
- 任何 `story/*` task 都不允许通过通用 task create endpoint 直接创建
- `story` 仅允许通过 `Proposal Accept` 工作流生成
### 8.5 Essential
新增 `Essential` 概念,用于承载 Proposal 下的可落地核心条目。
建议字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int (PK) | |
| essential_code | VARCHAR(64), UNIQUE | EssentialCode风格参考 ProjectCode / TaskCode / MilestoneCode / ProposalCode |
| proposal_id | FK -> proposals.id | 所属 Proposal |
| type | Enum(feature, improvement, refactor) | Essential 类型 |
| title | VARCHAR(255) | 标题 |
| description | TEXT, nullable | 描述 |
| created_by_id | FK -> users.id, nullable | 创建人 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
### 8.6 代码生成
- `Essential` 拥有独立 `EssentialCode`
- 编码规则参考现有类似结构,例如:
- `ProjectCode`
- `MilestoneCode`
- `TaskCode`
- `ProposalCode`
- 具体前缀与编号策略待后续单独定稿
## 九、前端
- 每个用户可查看/调整自己的日程表
- Admin 可查看/调整所有用户的日程表
- 日程表页面展示(具体 UI 待设计)
---
## 十、Bug Fix
- acc-mgr 用户后端禁止修改密码admin 也不行)
- 前端acc-mgr 用户不显示修改密码入口
---
## 十一、待定项
- Entertainment 事件子类型设计
- MinimumWorkload 存储方式JSON 字段 vs 独立表)
- 前端日程表 UI 详细设计
- Agent 唤醒的提示词模板
- Proposal / Essential 的详细数据模型、API、前端页面与 accept 流程实现细节
- Story restricted 后,现有 task create / propose accept / milestone flow 的兼容迁移策略

380
plans/TASKLIST.md Normal file
View File

@@ -0,0 +1,380 @@
# TASKLIST.md
> 说明:如果某个进行中的 Task 没有完全完成,或者在执行过程中遇到 block,需要在该 Task 下继续拆分若干子 TODO item:本次开发中已经完成的部分标记为已完成,block / pending / 尚未完成的部分标记为未完成。
>
> 拆分原则:尽量保证 Task 之间相互独立;每个 Task 最好只改动一个子模块(如 `HarborForge.Backend` / `HarborForge.Frontend` / `HarborForge.Cli` / `HarborForge.OpenclawPlugin` / 根目录文档),避免一次任务同时横跨多个子模块。只有在确实无法避免时,才建立跨模块 Task。
---
# TODOLIST
## A. Root / Docs(根目录与规划文档)
- [x] DOC-001:整理本波开发范围说明(root docs only)
- [x] 明确 Calendar 属于独立功能线
- [x] 明确 Proposal / Essential 属于项目结构调整线
- [x] 明确两条线的交叉点仅限 `event_data` / Agent 调度引用层
- [x] 将"必须本波完成"和"仅设计保留"区分写清楚
- [x] DOC-002:整理 Proposal / Essential / Story restricted 的迁移说明(root docs only)
- [x] 说明 `Propose -> Proposal` 的命名调整
- [x] 说明 `Proposal Accept` 语义变化
- [x] 说明 `story/*` 改为 restricted 的影响面
- [x] 说明旧数据和旧接口的兼容策略
- [x] DOC-003整理 Calendar 验收清单(root docs only)
- [x] 列出后端验收项
- [x] 列出前端验收项
- [x] 列出 CLI 验收项
- [x] 列出插件联动验收项
## B. HarborForge.Backend - Proposal / Essential / Story restricted
- [x] BE-PR-001:后端统一重命名 `Propose` 概念为 `Proposal`(backend only)
- [x] 盘点 `models / schemas / routers / services / tests``propose` 命名
- [x] 明确保留兼容别名还是直接切换 → 保留别名 + legacy API 路由
- [x] 输出重命名影响清单 → `docs/BE-PR-001-rename-impact.md`
- [x] BE-PR-002:新增 Proposal 数据模型调整(backend only)
- [x] 调整 Proposal 模型命名与字段注释
- [x] 确认 Proposal 与 `project_id / created_by_id / feat_task_id` 的后续关系
- [x] 标记 `feat_task_id` 是否废弃或替换
- [x] BE-PR-003:新增 Essential 模型(backend only)
- [x] 新增 `Essential` SQLAlchemy model
- [x] 增加 `proposal_id` 外键
- [x] 增加 `essential_code`
- [x] 增加 `type / title / description / created_by_id / created_at / updated_at`
- [x] BE-PR-004:实现 EssentialCode 编码规则(backend only)
- [x] 参考现有 `ProjectCode / MilestoneCode / TaskCode / ProposeCode` 生成方式
- [x] 设计 Essential code 前缀
- [x] 实现唯一编号生成逻辑
- [x] 明确是否需要独立 counter 表
- [x] BE-PR-005:新增 Essential 的 schema 定义(backend only)
- [x] 新增 create schema
- [x] 新增 update schema
- [x] 新增 response schema
- [x] 新增 Proposal detail 中嵌套 Essential 的返回结构
- [x] BE-PR-006:新增 Proposal 下 Essential CRUD API(backend only)
- [x] 实现创建 Essential
- [x] 实现编辑 Essential
- [x] 实现删除 Essential
- [x] 实现 Proposal 详情返回 Essential 列表
- [x] BE-PR-007:重构 Proposal Accept 逻辑(backend only)
- [x] 移除"accept 后生成单个 `story/feature` task"的旧逻辑
- [x] Accept 时要求显式选择目标 Milestone
- [x] 遍历 Proposal 下全部 Essential
- [x] 按 Essential.type 生成对应 `story/*` task
- [x] 保证批量创建在一个事务中完成
- [x] BE-PR-008:补充 Proposal Accept 追踪字段/关系(backend only)
- [x] 明确 Proposal 与生成 tasks 的映射方式
- [x] 设计是用反查字段、关联表还是事件记录
- [x] 实现最小可用追踪能力
- [x] BE-PR-009:收紧 Task 类型规则,限制全部 `story/*`(backend only)
- [x] 更新 `TASK_SUBTYPE_MAP` 相关约束
- [x] 将所有 `story/*` 组合标记为 restricted
- [x] 禁止通用 create endpoint 直接创建任何 story
- [x] 保留内部受控入口用于 Proposal Accept
- [x] BE-PR-010:清理旧的 `feat_task_id` 语义(backend only)
- [x] 判断字段是否保留但废弃 → 保留 DB 列,标记 DEPRECATED
- [x] 如果废弃,给出兼容读取策略 → 旧行仍返回值,新 accept 不写入,客户端迁移到 generated_tasks
- [x] 如果替换,落地新的字段或关联方式 → 已由 BE-PR-008 通过 Task.source_proposal_id 替代
- [x] BE-PR-011:补 Proposal / Essential / Story restricted 的后端测试(backend only)
- [x] Essential CRUD 测试
- [x] Proposal Accept 批量生成 story task 测试
- [x] 非受控入口创建 `story/*` 的失败测试
- [x] 兼容旧 proposal 数据的测试
## C. HarborForge.Backend - Calendar 基础模型与规则
- [x] BE-CAL-001:新增 Calendar 基础模型 `TimeSlot`(backend only)
- [x] 新增表结构
- [x] 定义 slot status / slot type / event type 枚举
- [x] 定义时间字段与时长字段
- [x] 定义 `plan_id` 关联
- [x] BE-CAL-002:新增 Calendar 基础模型 `SchedulePlan`(backend only)
- [x] 新增表结构
- [x] 定义 `at_time / on_day / on_week / on_month`
- [x] 加入层级参数校验约束
- [x] 处理 user 归属关系
- [x] BE-CAL-003:新增 Agent 扩展字段(backend only)
- [x] 为 Agent 增加 `status / last_heartbeat`
- [x] 增加 `exhausted_at / recovery_at / exhaust_reason`
- [x] 明确与现有 user / monitor 标识的关系
- [x] BE-CAL-004:实现 MinimumWorkload 存储方案(backend only)
- [x] 确定 JSON 字段还是独立表 → 独立表 `minimum_workloads`config 列为 JSON
- [x] 实现用户级配置读写 → GET/PUT/PATCH `/calendar/workload-config` + admin 路由
- [x] 提供后续校验调用入口 → `services/minimum_workload.check_workload_warnings()`
- [x] BE-CAL-005:实现 Plan 虚拟 slot 标识与物化策略(backend only)
- [x] 实现 `plan-{plan_id}-{date}` 标识规则
- [x] 实现虚拟 slot 转真实 slot 的物化逻辑
- [x] 实现 edit / cancel 后断开 plan 关联
- [x] BE-CAL-006:实现 Calendar overlap 校验(backend only)
- [x] 校验同日时间冲突
- [x] 返回明确的冲突错误信息
- [x] 区分 create 与 edit 两种场景
- [x] BE-CAL-007:实现 MinimumWorkload warning 规则(backend only)
- [x] 计算 daily / weekly / monthly / yearly 工作量
- [x] 不阻止提交,仅返回 warning
- [x] 统一 warning 数据结构
- [x] BE-CAL-008:实现不可修改过去 slot 的规则(backend only)
- [x] 禁止 edit 过去 slot
- [x] 禁止 cancel 过去 slot
- [x] 保证 plan-edit / plan-cancel 不追溯过去已物化 slot
## D. HarborForge.Backend - Calendar API
- [x] BE-CAL-API-001:实现单次日程创建 API(backend only)
- [x] 创建 slot
- [x] 支持 job/system/event_data
- [x] 接入 overlap 与 workload warning
- [x] BE-CAL-API-002:实现某日 Calendar 查询 APIbackend only
- [x] 返回真实 slot
- [x] 合成当日 plan 虚拟 slot
- [x] 输出统一排序结构
- [x] BE-CAL-API-003:实现 Calendar 编辑 APIbackend only
- [x] 支持真实 slot 编辑
- [x] 支持虚拟 slot 编辑并触发物化
- [x] 返回编辑后的真实结果
- [x] BE-CAL-API-004:实现 Calendar 取消 API(backend only)
- [x] 支持真实 slot cancel
- [x] 支持虚拟 slot cancel 并触发物化
- [x] 处理状态字段更新
- [x] BE-CAL-API-005:实现 plan-schedule / plan-list API(backend only)
- [x] 创建计划
- [x] 列出计划
- [x] 返回计划规则字段
- [x] BE-CAL-API-006:实现 plan-edit / plan-cancel APIbackend only
- [x] 编辑计划
- [x] 取消计划
- [x] 不追溯已物化过去数据
- [x] BE-CAL-API-007:实现 date-list API(backend only)
- [x] 仅列出有已物化未来 slot 的日期
- [x] 排除纯 plan 未物化日期
## E. HarborForge.Backend - Agent / Plugin Calendar 协作
- [x] BE-AGT-001:定义心跳查询待执行 slot 的服务层(backend only)
- [x] 筛选当天 `NotStarted / Deferred`
- [x] 仅返回 `scheduled_at` 已过的 slot
- [x] 按优先级排序
- [x] BE-AGT-002:实现 Agent 状态流转服务(backend only)
- [x] Idle -> Busy / OnCall
- [x] Busy / OnCall -> Idle
- [x] 超时无心跳 -> Offline
- [x] API 配额错误 -> Exhausted
- [x] BE-AGT-003:实现多 slot 竞争处理(backend only)
- [x] 选最高 priority 执行
- [x] 其余 slot 标记 Deferred
- [x] Deferred slot 自动 priority += 1
- [x] BE-AGT-004:实现 Exhausted 恢复时间解析(backend only)
- [x] 解析 retry-after / reset in / resets at
- [x] 解析失败时默认 5 小时
- [x] 到期恢复 Idle
## F. HarborForge.Frontend - Proposal / Essential / Story restricted
- [x] FE-PR-001:前端统一重命名 Propose -> Proposal(frontend only)
- [x] 调整页面标题与菜单文案
- [x] 调整类型名与 API 调用命名
- [x] 清理旧 propose 文案
- [x] FE-PR-002:Proposal 详情页增加 Essential 列表区(frontend only)
- [x] 展示 Essential 列表
- [x] 展示 Essential type / code / title
- [x] 处理空状态
- [x] FE-PR-003:新增 Essential 创建/编辑表单(frontend only)
- [x] 创建表单
- [x] 编辑表单
- [x] type 选择器
- [x] 提交后局部刷新
- [x] FE-PR-004:Proposal Accept 增加目标 Milestone 选择(frontend only)
- [x] Accept 前展示 milestone 选择控件
- [x] 校验必须选择 milestone
- [x] 展示 Accept 成功后的生成结果
- [x] FE-PR-005:限制前端直接创建 `story/*`(frontend only)
- [x] 从 Task 创建入口移除 story
- [x] 或将 story 整体设为不可选
- [x] 调整相关提示文案
## G. HarborForge.Frontend - Calendar
- [x] FE-CAL-001:新增 Calendar 页面基础骨架(frontend only)
- [x] 增加路由入口
- [x] 增加侧边栏入口
- [x] 增加基础页面布局
- [x] FE-CAL-002:实现某日 slot 列表展示(frontend only)
- [x] 展示时间轴或列表
- [x] 区分真实 slot 与 plan 虚拟 slot
- [x] 展示状态 / 类型 / 时长 / 优先级
- [x] FE-CAL-003:实现计划列表展示(frontend only)
- [x] 展示计划规则
- [x] 展示周期参数
- [x] 支持跳转编辑
- [x] FE-CAL-004:实现创建 / 编辑 / 取消日程交互(frontend only)
- [x] 新建 slot 表单
- [x] 编辑 slot 表单
- [x] cancel 操作确认
- [x] 展示后端 warning
- [x] FE-CAL-005:实现 Deferred / Exhausted / overlap 等状态提示(frontend only)
- [x] Deferred 提示
- [x] overlap 报错展示
- [x] workload warning 展示
- [x] Exhausted 状态展示
## H. HarborForge.Cli - Proposal / Essential / Story restricted
- [x] CLI-PR-001:统一 CLI 文案 `propose -> proposal`(cli only)
- [x] 调整命令 help 文案
- [x] 调整输出文本
- [x] 评估命令名是否兼容保留 `hf propose` → 保留为 alias
- [x] CLI-PR-002:新增 Essential 相关命令(cli only)
- [x] `hf proposal essential list`
- [x] `hf proposal essential create`
- [x] `hf proposal essential update`
- [x] `hf proposal essential delete`
- [x] CLI-PR-003:更新 Proposal Accept CLI(cli only)
- [x] Accept 时支持传入 milestone
- [x] 展示批量生成的 task 结果
- [x] 更新帮助文案
- [x] CLI-PR-004:限制 CLI 直接创建 `story/*`(cli only)
- [x] 阻止 story 类型直建
- [x] 返回明确错误提示
- [x] 提示改走 Proposal Accept
## I. HarborForge.Cli - Calendar
- [x] CLI-CAL-001:新增 `hf calendar` 命令组骨架(cli only)
- [x] 注册命令组
- [x] 增加 help surface
- [x] 增加 brief help
- [x] CLI-CAL-002:实现 `hf calendar schedule`(cli only)
- [x] 参数解析
- [x] 请求构造
- [x] 结果输出
- [x] CLI-CAL-003:实现 `hf calendar show`(cli only)
- [x] 日期参数
- [x] 列表输出
- [x] JSON 输出
- [x] CLI-CAL-004:实现 `hf calendar edit`(cli only)
- [x] 支持 slot-id 与 date
- [x] PATCH/POST 适配
- [x] 输出 warning / error
- [x] CLI-CAL-005:实现 `hf calendar cancel`(cli only)
- [x] 支持 slot-id 与 date
- [x] 输出结果
- [x] CLI-CAL-006:实现 `hf calendar date-list`(cli only)
- [x] 列出未来已物化日期
- [x] 适配 JSON 输出
- [x] CLI-CAL-007:实现 `hf calendar plan-schedule`(cli only)
- [x] 参数解析 `--at --on-day --on-week --on-month`
- [x] 请求构造
- [x] 输出结果
- [x] CLI-CAL-008:实现 `hf calendar plan-list`(cli only)
- [x] 列表输出
- [x] JSON 输出
- [x] CLI-CAL-009:实现 `hf calendar plan-edit`(cli only)
- [x] 参数解析
- [x] 请求发送
- [x] 输出结果
- [x] CLI-CAL-010:实现 `hf calendar plan-cancel`(cli only)
- [x] 参数解析
- [x] 请求发送
- [x] 输出结果
## J. HarborForge.OpenclawPlugin / Monitor 联动
- [x] PLG-CAL-001:插件侧定义 Calendar 心跳请求格式(plugin only)
- [x] 明确 claw_identifier 传递方式
- [x] 明确 agent_id 传递方式
- [x] 明确返回 slot 列表结构
- [x] PLG-CAL-002:插件侧处理待执行 slot 唤醒(plugin only)
- [x] Idle 时唤醒 agent
- [x] 透传任务上下文
- [x] 执行前更新 attended / started_at / status
- [x] PLG-CAL-003:插件侧处理非 Idle / Deferred 分支(plugin only)
- [x] Agent 非 Idle 时上报 Deferred
- [x] 处理多 slot 重排后的重新规划
- [x] PLG-CAL-004:插件侧处理 ScheduledGatewayRestart(plugin only)
- [x] 收到事件后持久化状态
- [x] 发送最终心跳
- [x] 暂停定时任务
## K. Tests / Integration(按子模块分别补,不混做)
- [x] TEST-BE-CAL-001:补 Calendar backend 测试(backend tests only)
- [x] 模型测试
- [x] API 测试
- [x] overlap / warning / materialize 测试
- [x] Blocker resolved: `HarborForge.Backend/app/schemas/calendar.py` 的 Python 3.12 + Pydantic 2.5 递归建模问题已通过 schema 类型别名修复,本次已继续补齐 Calendar API / model tests
- [x] TEST-BE-PR-001:补 Proposal / Essential backend 测试(backend tests only)
- [x] Essential CRUD
- [x] Accept 生成 story tasks
- [x] story restricted
- [x] TEST-FE-CAL-001:补 Calendar 前端测试(frontend tests only)
- [x] 页面渲染
- [x] 表单交互
- [x] warning / error 展示
- [x] TEST-FE-PR-001:补 Proposal / Essential 前端测试(frontend tests only)
- [x] Essential 列表与表单
- [x] Accept milestone 选择
- [x] story 创建入口限制
- [x] TEST-CLI-CAL-001:补 Calendar CLI 测试(cli tests only)
- [x] 命令解析
- [x] JSON 输出
- [x] 错误输出
- [x] TEST-CLI-PR-001:补 Proposal / Essential CLI 测试(cli tests only)
- [x] Essential 子命令
- [x] accept milestone 参数
- [x] story 限制提示

View File

@@ -0,0 +1,8 @@
{
"createdAt": "2026-03-29T11:50:00Z",
"lastRun": null,
"totalRuns": 0,
"completedTasks": [],
"currentTask": null,
"status": "active"
}

View File

@@ -0,0 +1,56 @@
# HarborForge 自动化开发任务 - 定时唤醒
# 模型: kimi/k2p5 | Agent: developer
# 目标: Discord 1474327736242798612
## 任务说明
每次唤醒后执行以下操作:
### 1. 读取计划文档
- 阅读 `/root/.openclaw/workspace/workspace-developer/HarborForge/plans/NEXT_WAVE_DEV_DIRECTION.md`
- 理解当前开发方向和架构设计
### 2. 读取任务列表
- 阅读 `/root/.openclaw/workspace/workspace-developer/HarborForge/plans/TASKLIST.md`
- 识别未完成的任务项
### 3. 任务执行策略
- 从 TASKLIST.md 中选择一个**未完成的、可独立执行**的任务
- 优先选择只涉及单个子模块的任务Backend/Frontend/CLI/Plugin
- 避免一次任务横跨多个子模块
- 如任务过大,拆分为更小的子任务
### 4. 执行流程
1. 创建任务分支(如需要)
2. 实现功能代码
3. 编写/更新测试
4. 本地验证(如可能)
5. 提交代码并推送
6. 更新 TASKLIST.md将完成的任务标记为 `[x]`
### 5. 汇报要求
向 Discord channel `1474327736242798612` 发送执行摘要:
- 本次处理的任务ID和标题
- 完成状态(已完成/部分完成/遇到阻塞)
- 关键变更摘要
- 下一步计划或遇到的问题
### 6. 任务完成检测
- 检查 TASKLIST.md 中是否还有未完成任务
- 如果**所有任务都已完成**
- 在 Discord 汇报最终完成情况
- 调用 `openclaw cron delete hf-dev-kimi-scheduler` 删除本定时任务
- 说明删除原因
## 开发原则
- **单一职责**:每次只处理一个任务
- **小步快跑**:任务可拆分则拆分
- **及时汇报**:每个任务完成后立即汇报进度
- **安全优先**:涉及破坏性变更时先确认
## 当前上下文
- 工作目录: `/root/.openclaw/workspace/workspace-developer/HarborForge`
- Git 仓库: https://git.hangman-lab.top/zhi/HarborForge
- 包含子模块: Backend, Frontend, Cli, Monitor, OpenclawPlugin, Test