cursorfleet 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. cursorfleet/__init__.py +9 -0
  2. cursorfleet/_templates/cursor/agents/architect.md +18 -0
  3. cursorfleet/_templates/cursor/agents/implementer.md +20 -0
  4. cursorfleet/_templates/cursor/agents/patcher.md +17 -0
  5. cursorfleet/_templates/cursor/agents/qa.md +21 -0
  6. cursorfleet/_templates/cursor/agents/reviewer.md +20 -0
  7. cursorfleet/_templates/cursor/agents/scout.md +17 -0
  8. cursorfleet/_templates/cursor/agents/tester.md +20 -0
  9. cursorfleet/_templates/cursor/agents-md/root.md +7 -0
  10. cursorfleet/_templates/cursor/agents-md/work.md +7 -0
  11. cursorfleet/_templates/cursor/config/config.toml +47 -0
  12. cursorfleet/_templates/cursor/hooks/entry.json +4 -0
  13. cursorfleet/_templates/cursor/rules/cursorfleet-core.mdc +10 -0
  14. cursorfleet/_templates/cursor/rules/cursorfleet-handoff.mdc +15 -0
  15. cursorfleet/_templates/cursor/skills/cursorfleet-artifacts/SKILL.md +57 -0
  16. cursorfleet/_templates/cursor/skills/cursorfleet-coordinator/SKILL.md +35 -0
  17. cursorfleet/adapters/__init__.py +0 -0
  18. cursorfleet/adapters/cursor/__init__.py +0 -0
  19. cursorfleet/adapters/cursor/blocks.py +104 -0
  20. cursorfleet/adapters/cursor/diagnostics.py +547 -0
  21. cursorfleet/adapters/cursor/fsutil.py +156 -0
  22. cursorfleet/adapters/cursor/hook_main.py +428 -0
  23. cursorfleet/adapters/cursor/hook_normalize.py +527 -0
  24. cursorfleet/adapters/cursor/hook_policy.py +76 -0
  25. cursorfleet/adapters/cursor/hook_sanitize.py +474 -0
  26. cursorfleet/adapters/cursor/hooksjson.py +305 -0
  27. cursorfleet/adapters/cursor/installer.py +626 -0
  28. cursorfleet/adapters/cursor/kit.py +210 -0
  29. cursorfleet/adapters/cursor/kit_probe.py +54 -0
  30. cursorfleet/adapters/cursor/lock.py +145 -0
  31. cursorfleet/adapters/cursor/templates.py +60 -0
  32. cursorfleet/adapters/cursor/validation.py +365 -0
  33. cursorfleet/adapters/cursor/workspace.py +80 -0
  34. cursorfleet/cli/__init__.py +0 -0
  35. cursorfleet/cli/commands/__init__.py +1 -0
  36. cursorfleet/cli/commands/_common.py +82 -0
  37. cursorfleet/cli/commands/_resolution.py +56 -0
  38. cursorfleet/cli/commands/doctor.py +81 -0
  39. cursorfleet/cli/commands/events.py +197 -0
  40. cursorfleet/cli/commands/index.py +55 -0
  41. cursorfleet/cli/commands/init.py +71 -0
  42. cursorfleet/cli/commands/migrate.py +43 -0
  43. cursorfleet/cli/commands/replay.py +76 -0
  44. cursorfleet/cli/commands/run.py +97 -0
  45. cursorfleet/cli/commands/status.py +210 -0
  46. cursorfleet/cli/commands/tui.py +47 -0
  47. cursorfleet/cli/commands/uninstall.py +73 -0
  48. cursorfleet/cli/commands/validate.py +69 -0
  49. cursorfleet/cli/main.py +81 -0
  50. cursorfleet/config/__init__.py +44 -0
  51. cursorfleet/config/io.py +27 -0
  52. cursorfleet/config/models.py +154 -0
  53. cursorfleet/config/roster.py +245 -0
  54. cursorfleet/events/__init__.py +39 -0
  55. cursorfleet/events/forbidden.py +45 -0
  56. cursorfleet/events/ids.py +109 -0
  57. cursorfleet/events/kinds.py +132 -0
  58. cursorfleet/events/models.py +213 -0
  59. cursorfleet/events/pathcheck.py +45 -0
  60. cursorfleet/git/__init__.py +0 -0
  61. cursorfleet/git/collector.py +226 -0
  62. cursorfleet/git/runner.py +135 -0
  63. cursorfleet/git/worktrees.py +71 -0
  64. cursorfleet/policy/__init__.py +0 -0
  65. cursorfleet/py.typed +0 -0
  66. cursorfleet/safeexe.py +70 -0
  67. cursorfleet/schema_gen.py +73 -0
  68. cursorfleet/state/__init__.py +0 -0
  69. cursorfleet/state/artifact_scan.py +309 -0
  70. cursorfleet/state/context.py +38 -0
  71. cursorfleet/state/event_store.py +227 -0
  72. cursorfleet/state/indexer.py +443 -0
  73. cursorfleet/state/lock.py +74 -0
  74. cursorfleet/state/models.py +268 -0
  75. cursorfleet/state/reducer.py +588 -0
  76. cursorfleet/state/retention.py +218 -0
  77. cursorfleet/state/run_builder.py +136 -0
  78. cursorfleet/state/run_model.py +43 -0
  79. cursorfleet/state/run_store.py +95 -0
  80. cursorfleet/state/runtime.py +645 -0
  81. cursorfleet/state/spool.py +186 -0
  82. cursorfleet/state/spool_read.py +242 -0
  83. cursorfleet/state/status_doc.py +293 -0
  84. cursorfleet/tui/__init__.py +0 -0
  85. cursorfleet/tui/app.py +581 -0
  86. cursorfleet/tui/data.py +545 -0
  87. cursorfleet/tui/filters.py +82 -0
  88. cursorfleet/tui/gates.py +255 -0
  89. cursorfleet/tui/help.py +101 -0
  90. cursorfleet/tui/layout.py +26 -0
  91. cursorfleet/tui/theme.py +176 -0
  92. cursorfleet/tui/views.py +1077 -0
  93. cursorfleet/tui/watch.py +33 -0
  94. cursorfleet/workflow/__init__.py +0 -0
  95. cursorfleet/workflow/artifacts.py +148 -0
  96. cursorfleet/workflow/frontmatter.py +232 -0
  97. cursorfleet-0.1.0.dist-info/METADATA +161 -0
  98. cursorfleet-0.1.0.dist-info/RECORD +101 -0
  99. cursorfleet-0.1.0.dist-info/WHEEL +4 -0
  100. cursorfleet-0.1.0.dist-info/entry_points.txt +3 -0
  101. cursorfleet-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,268 @@
1
+ """State models: persisted accumulators (projection) and derived views (``status --json``).
2
+
3
+ Accumulators (``*Acc``) are what the reducer folds events into and what SQLite stores as
4
+ JSON. Views (``*View``) are computed from accumulators plus an injected ``now``; they carry
5
+ the stale/offline decision and are what the CLI prints.
6
+
7
+ Lanes are HEURISTICS over observed (and self-reported) events, not ground truth; every
8
+ lane carries its ``lane_source`` and the TUI must say so (docs/status-json.md).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from datetime import UTC, datetime
14
+ from enum import StrEnum
15
+ from typing import Annotated, Literal
16
+
17
+ from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, field_validator
18
+
19
+ from cursorfleet.events.kinds import Attribution, Outcome, Source
20
+
21
+ STATE_SCHEMA_VERSION = 1
22
+ MAX_FILES_PER_AGENT = 500
23
+ BUDGET_UNKNOWN = "unknown" # Cursor hooks expose no token budget (ADR 0001 A9)
24
+
25
+
26
+ class Lane(StrEnum):
27
+ """Workflow lane. ``unknown`` means "no telemetry"; it is never rendered as idle."""
28
+
29
+ QUEUED = "queued"
30
+ LOADING_CONTEXT = "loading_context"
31
+ PLANNING = "planning"
32
+ WORKING = "working"
33
+ VERIFYING = "verifying"
34
+ AWAITING_REVIEW = "awaiting_review"
35
+ PATCHING = "patching"
36
+ BLOCKED = "blocked"
37
+ DONE = "done"
38
+ STALE_OFFLINE = "stale_offline"
39
+ UNKNOWN = "unknown"
40
+
41
+
42
+ def utc(value: datetime) -> datetime:
43
+ return value.astimezone(UTC)
44
+
45
+
46
+ _STRICT = ConfigDict(extra="forbid", validate_assignment=False)
47
+ UtcDatetime = Annotated[AwareDatetime, Field()]
48
+
49
+
50
+ class _Acc(BaseModel):
51
+ model_config = _STRICT
52
+
53
+ @field_validator("*", mode="after")
54
+ @classmethod
55
+ def _normalize_tz(cls, value: object) -> object:
56
+ return utc(value) if isinstance(value, datetime) else value
57
+
58
+
59
+ class LastTest(_Acc):
60
+ outcome: Outcome
61
+ ts: UtcDatetime
62
+
63
+
64
+ class StopReport(_Acc):
65
+ """What Cursor itself reported when a subagent stopped (``subagentStop``)."""
66
+
67
+ outcome: Outcome | None = None
68
+ duration_ms: int | None = None
69
+ tool_call_count: int | None = None
70
+ message_count: int | None = None
71
+ loop_count: int | None = None
72
+
73
+
74
+ class AgentAcc(_Acc):
75
+ key: str
76
+ role: str | None = None
77
+ instance_id: str | None = None
78
+ attribution: Attribution = Attribution.UNKNOWN
79
+ lane: Lane = Lane.UNKNOWN
80
+ lane_source: Source | None = None
81
+ lane_since: UtcDatetime | None = None
82
+ first_ts: UtcDatetime
83
+ last_ts: UtcDatetime
84
+ last_live_ts: UtcDatetime | None = None # last observed/derived event (not self-reported)
85
+ events: int = 0
86
+ lifecycle: Literal["none", "running", "stopped"] = "none"
87
+ lifecycle_only: bool = False # running subagent with no attributed telemetry yet
88
+ started_ts: UtcDatetime | None = None
89
+ stopped_ts: UtcDatetime | None = None
90
+ spawn_link: str | None = None # tool_use_id / tool_call_id (PROVISIONAL linkage)
91
+ pre_calls: int = 0
92
+ pre_shell_calls: int = 0
93
+ before_shell_calls: int = 0
94
+ tool_failures: int = 0
95
+ last_tool: str | None = None
96
+ compactions: int = 0
97
+ last_context_usage_percent: float | None = None
98
+ last_context_tokens: int | None = None
99
+ last_context_window: int | None = None
100
+ files: list[str] = Field(default_factory=list)
101
+ files_overflow: bool = False
102
+ reviewed: bool = False
103
+ last_test: LastTest | None = None
104
+ stop_report: StopReport | None = None
105
+ plans: int = 0
106
+ handoffs: int = 0
107
+ blockers: int = 0
108
+ contexts_loaded: int = 0
109
+ issue_refs: list[str] = Field(default_factory=list)
110
+ worktree_id: str | None = None
111
+ branch: str | None = None
112
+ commit: str | None = None
113
+
114
+ @property
115
+ def tool_call_count(self) -> int:
116
+ """Tool calls seen. ``preToolUse`` is canonical; Shell-hook starts count only when
117
+ no ``preToolUse`` for Shell was seen (hook set may be a subset), so overlapping
118
+ hooks never double count."""
119
+ shell_fallback = self.before_shell_calls if self.pre_shell_calls == 0 else 0
120
+ return self.pre_calls + shell_fallback
121
+
122
+
123
+ class GateAcc(_Acc):
124
+ state: str
125
+ ts: UtcDatetime
126
+ commit: str | None = None
127
+
128
+
129
+ class SessionAcc(_Acc):
130
+ schema_version: int = STATE_SCHEMA_VERSION
131
+ session_id: str
132
+ first_ts: UtcDatetime
133
+ last_ts: UtcDatetime
134
+ last_live_ts: UtcDatetime | None = None
135
+ started_ts: UtcDatetime | None = None
136
+ ended_ts: UtcDatetime | None = None
137
+ ended: bool = False
138
+ end_outcome: Outcome | None = None
139
+ cursor_version: str | None = None
140
+ branch: str | None = None
141
+ commit: str | None = None
142
+ worktree_ids: list[str] = Field(default_factory=list)
143
+ events: int = 0
144
+ by_source: dict[str, int] = Field(default_factory=dict)
145
+ unpaired_stops: int = 0
146
+ agents: dict[str, AgentAcc] = Field(default_factory=dict)
147
+ gates: dict[str, GateAcc] = Field(default_factory=dict)
148
+ watermark_ts: UtcDatetime
149
+ watermark_id: str
150
+
151
+
152
+ # ---------------------------------------------------------------- views
153
+
154
+
155
+ class _View(BaseModel):
156
+ model_config = ConfigDict(extra="forbid")
157
+
158
+
159
+ class LastTestView(_View):
160
+ outcome: str
161
+ ts: datetime
162
+
163
+
164
+ class StopReportView(_View):
165
+ outcome: str | None
166
+ duration_ms: int | None
167
+ tool_call_count: int | None
168
+ message_count: int | None
169
+
170
+
171
+ class AgentView(_View):
172
+ key: str
173
+ role: str | None
174
+ instance_id: str | None
175
+ attribution: str
176
+ lane: str
177
+ lane_source: str | None
178
+ lane_basis: str
179
+ stale: bool
180
+ last_lane: str | None # the lane before it went stale_offline
181
+ lifecycle: str
182
+ lifecycle_only: bool
183
+ first_ts: datetime
184
+ last_ts: datetime
185
+ elapsed_s: float
186
+ tool_call_count: int
187
+ tool_failures: int
188
+ compactions: int
189
+ last_context_usage_percent: float | None
190
+ files_changed: int
191
+ reviewed: bool
192
+ last_test: LastTestView | None
193
+ stop_report: StopReportView | None
194
+ issue_refs: list[str]
195
+ worktree_id: str | None
196
+ branch: str | None
197
+ token_budget: str
198
+
199
+
200
+ class GateView(_View):
201
+ name: str
202
+ state: str
203
+ ts: datetime
204
+ commit: str | None
205
+
206
+
207
+ class SessionView(_View):
208
+ session_id: str
209
+ lane: str
210
+ ended: bool
211
+ end_outcome: str | None
212
+ first_ts: datetime
213
+ last_ts: datetime
214
+ started_ts: datetime | None
215
+ ended_ts: datetime | None
216
+ elapsed_s: float
217
+ tool_call_count: int
218
+ compactions: int
219
+ event_count: int
220
+ by_source: dict[str, int]
221
+ cursor_version: str | None
222
+ branch: str | None
223
+ commit: str | None
224
+ worktree_ids: list[str]
225
+ unpaired_stops: int
226
+ token_budget: str
227
+ agents: list[AgentView]
228
+ gates: list[GateView]
229
+
230
+
231
+ class TaskView(_View):
232
+ issue_ref: str
233
+ lane: str
234
+ session_ids: list[str]
235
+ agent_keys: list[str]
236
+ first_ts: datetime
237
+ last_ts: datetime
238
+ plans: int
239
+ handoffs: int
240
+ blockers: int
241
+
242
+
243
+ class FleetView(_View):
244
+ generated_at: datetime
245
+ stale_after_s: int
246
+ sessions: list[SessionView]
247
+ tasks: list[TaskView]
248
+
249
+
250
+ __all__ = [
251
+ "BUDGET_UNKNOWN",
252
+ "MAX_FILES_PER_AGENT",
253
+ "STATE_SCHEMA_VERSION",
254
+ "AgentAcc",
255
+ "AgentView",
256
+ "FleetView",
257
+ "GateAcc",
258
+ "GateView",
259
+ "Lane",
260
+ "LastTest",
261
+ "LastTestView",
262
+ "SessionAcc",
263
+ "SessionView",
264
+ "StopReport",
265
+ "StopReportView",
266
+ "TaskView",
267
+ "utc",
268
+ ]