opencode-extended-sidebar 0.2.90

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 (105) hide show
  1. package/.oesignore +17 -0
  2. package/CHANGELOG.md +95 -0
  3. package/LICENSE +21 -0
  4. package/README.md +235 -0
  5. package/oes.json +11 -0
  6. package/package.json +100 -0
  7. package/scripts/install-git-hooks.mjs +29 -0
  8. package/src/pware.oc.core/constants/index.ts +18 -0
  9. package/src/pware.oc.core/constants/pware.oc.core.constants.eventKind.ts +29 -0
  10. package/src/pware.oc.core/constants/pware.oc.core.constants.eventName.ts +13 -0
  11. package/src/pware.oc.core/constants/pware.oc.core.constants.eventType.ts +241 -0
  12. package/src/pware.oc.core/constants/pware.oc.core.constants.myWork.ts +55 -0
  13. package/src/pware.oc.core/constants/pware.oc.core.constants.partType.ts +65 -0
  14. package/src/pware.oc.core/constants/pware.oc.core.constants.phase.ts +58 -0
  15. package/src/pware.oc.core/constants/pware.oc.core.constants.pulse.ts +63 -0
  16. package/src/pware.oc.core/constants/pware.oc.core.constants.rowKind.ts +34 -0
  17. package/src/pware.oc.core/constants/pware.oc.core.constants.status.ts +74 -0
  18. package/src/pware.oc.core/constants/pware.oc.core.constants.toolName.ts +69 -0
  19. package/src/pware.oc.core/git/index.ts +7 -0
  20. package/src/pware.oc.core/git/pware.oc.core.git.ts +237 -0
  21. package/src/pware.oc.core/git/pware.oc.core.gitignore.ts +87 -0
  22. package/src/pware.oc.core/index.ts +18 -0
  23. package/src/pware.oc.core/pware.oc.core.bus.ts +42 -0
  24. package/src/pware.oc.core/pware.oc.core.cache.ts +48 -0
  25. package/src/pware.oc.core/pware.oc.core.clipboard.ts +97 -0
  26. package/src/pware.oc.core/pware.oc.core.debug.ts +280 -0
  27. package/src/pware.oc.core/pware.oc.core.events.ts +79 -0
  28. package/src/pware.oc.core/pware.oc.core.glyph.ts +135 -0
  29. package/src/pware.oc.core/pware.oc.core.layout.ts +234 -0
  30. package/src/pware.oc.core/pware.oc.core.oes.ts +89 -0
  31. package/src/pware.oc.core/pware.oc.core.paths.ts +240 -0
  32. package/src/pware.oc.core/pware.oc.core.preview.ts +74 -0
  33. package/src/pware.oc.core/pware.oc.core.pulse.ts +726 -0
  34. package/src/pware.oc.core/pware.oc.core.sqlite.ts +175 -0
  35. package/src/pware.oc.core/pware.oc.core.status.ts +214 -0
  36. package/src/pware.oc.core/pware.oc.core.timing.ts +63 -0
  37. package/src/pware.oc.core/pware.oc.core.width.ts +215 -0
  38. package/src/pware.oc.omo/constants/index.ts +15 -0
  39. package/src/pware.oc.omo/constants/pware.oc.omo.constants.backgroundTask.ts +18 -0
  40. package/src/pware.oc.omo/constants/pware.oc.omo.constants.boulderStatus.ts +49 -0
  41. package/src/pware.oc.omo/constants/pware.oc.omo.constants.docKind.ts +29 -0
  42. package/src/pware.oc.omo/constants/pware.oc.omo.constants.eventName.ts +11 -0
  43. package/src/pware.oc.omo/constants/pware.oc.omo.constants.planStatus.ts +60 -0
  44. package/src/pware.oc.omo/constants/pware.oc.omo.constants.reviewStatus.ts +49 -0
  45. package/src/pware.oc.omo/constants/pware.oc.omo.constants.startWork.ts +25 -0
  46. package/src/pware.oc.omo/constants/pware.oc.omo.constants.verdict.ts +38 -0
  47. package/src/pware.oc.omo/index.ts +7 -0
  48. package/src/pware.oc.omo/resolver/index.ts +19 -0
  49. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approval.ts +179 -0
  50. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalGroup.ts +116 -0
  51. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalState.ts +34 -0
  52. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.boulder.ts +503 -0
  53. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.config.ts +40 -0
  54. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.doc.ts +269 -0
  55. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.draftFile.ts +18 -0
  56. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.notepadsFile.ts +18 -0
  57. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.plan.ts +155 -0
  58. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.planFile.ts +361 -0
  59. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.proofFile.ts +18 -0
  60. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.rulesFile.ts +11 -0
  61. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.runContinuationFile.ts +14 -0
  62. package/src/pware.oc.opencode/constants/index.ts +10 -0
  63. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.eventName.ts +15 -0
  64. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.fileTouch.ts +18 -0
  65. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.ts +45 -0
  66. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.sessionStatus.ts +58 -0
  67. package/src/pware.oc.opencode/index.ts +8 -0
  68. package/src/pware.oc.opencode/pware.oc.opencode.events.ts +182 -0
  69. package/src/pware.oc.opencode/pware.oc.opencode.files.ts +399 -0
  70. package/src/pware.oc.opencode/resolver/index.ts +170 -0
  71. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.file.ts +162 -0
  72. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.question.ts +185 -0
  73. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.session.ts +211 -0
  74. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.todo.ts +26 -0
  75. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.tool.ts +236 -0
  76. package/src/pware.oc.perf/index.ts +14 -0
  77. package/src/pware.oc.perf/pware.oc.perf.asciichart.d.ts +15 -0
  78. package/src/pware.oc.perf/pware.oc.perf.charts.ts +284 -0
  79. package/src/pware.oc.perf/pware.oc.perf.reader.ts +927 -0
  80. package/src/pware.oc.perf/pware.oc.perf.realtime.ts +88 -0
  81. package/src/pware.oc.perf/pware.oc.perf.realtimeBlock.ts +118 -0
  82. package/src/pware.oc.perf/pware.oc.perf.realtimeCpuRam.ts +79 -0
  83. package/src/pware.oc.perf/pware.oc.perf.realtimeSampler.ts +71 -0
  84. package/src/pware.oc.perf/pware.oc.perf.realtimeTimeline.ts +214 -0
  85. package/src/pware.oc.perf/pware.oc.perf.self.ts +179 -0
  86. package/src/pware.oc.perf/pware.oc.perf.view.tsx +462 -0
  87. package/src/pware.oc.runtime/index.ts +13 -0
  88. package/src/pware.oc.runtime/pware.oc.runtime.monitor.ts +142 -0
  89. package/src/pware.oc.runtime/pware.oc.runtime.mywork-enrich.ts +79 -0
  90. package/src/pware.oc.runtime/pware.oc.runtime.mywork.ts +253 -0
  91. package/src/pware.oc.runtime/pware.oc.runtime.questions.ts +95 -0
  92. package/src/pware.oc.runtime/pware.oc.runtime.snapshotClient.ts +129 -0
  93. package/src/pware.oc.runtime/pware.oc.runtime.source.ts +105 -0
  94. package/src/pware.oc.runtime/pware.oc.runtime.worker.ts +43 -0
  95. package/src/pware.oc.runtime/resolver/index.ts +224 -0
  96. package/src/pware.oc.runtime/resolver/pware.oc.runtime.resolver.delegate.ts +146 -0
  97. package/src/pware.oc.ui/index.ts +12 -0
  98. package/src/pware.oc.ui/pware.oc.ui.chrome.tsx +339 -0
  99. package/src/pware.oc.ui/pware.oc.ui.glyphs.tsx +144 -0
  100. package/src/pware.oc.ui/pware.oc.ui.host.tsx +111 -0
  101. package/src/pware.oc.ui/pware.oc.ui.live.tsx +82 -0
  102. package/src/pware.oc.ui/pware.oc.ui.menudialogs.tsx +843 -0
  103. package/src/pware.oc.ui/pware.oc.ui.sections.tsx +526 -0
  104. package/src/pware.oc.ui/pware.oc.ui.sidebar.tsx +1629 -0
  105. package/src/pware.oc.ui.tsx +98 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * pware.oc.omo.constants.backgroundtask
3
+ *
4
+ * `.omo/run-continuation/<sessionID>.json` → `sources["background-task"].state`
5
+ * values.
6
+ */
7
+
8
+ /** Background-task state: a background task is actively running. */
9
+ export const BACKGROUND_TASK_ACTIVE = "active"
10
+
11
+ /** Background-task state: no background task is running. */
12
+ export const BACKGROUND_TASK_IDLE = "idle"
13
+
14
+ /** The `sources["background-task"].state` values a run-continuation marker can hold. */
15
+ export const BACKGROUND_TASK_STATES = [BACKGROUND_TASK_ACTIVE, BACKGROUND_TASK_IDLE] as const
16
+
17
+ /** A single run-continuation background-task state value. */
18
+ export type BackgroundTaskState = (typeof BACKGROUND_TASK_STATES)[number]
@@ -0,0 +1,49 @@
1
+ /**
2
+ * pware.oc.omo.constants.boulderstatus
3
+ *
4
+ * OMO boulder.json work/task status values. The plugin normalizes them via
5
+ * core `normalizeStatus`, but the raw boulder strings belong here.
6
+ */
7
+
8
+ /** Boulder status: work in progress. */
9
+ export const BOULDER_STATUS_IN_PROGRESS = "in_progress"
10
+
11
+ /** Boulder status: actively running. */
12
+ export const BOULDER_STATUS_RUNNING = "running"
13
+
14
+ /** Boulder status: live — the status boulder writes when a work starts. */
15
+ export const BOULDER_STATUS_ACTIVE = "active"
16
+
17
+ /** Boulder status: queued / waiting for a slot. */
18
+ export const BOULDER_STATUS_PENDING = "pending"
19
+
20
+ /** Boulder status: completed. */
21
+ export const BOULDER_STATUS_COMPLETED = "completed"
22
+
23
+ /** Boulder status: errored. */
24
+ export const BOULDER_STATUS_ERROR = "error"
25
+
26
+ /** Boulder status: paused. */
27
+ export const BOULDER_STATUS_PAUSED = "paused"
28
+
29
+ /** Boulder status: abandoned. */
30
+ export const BOULDER_STATUS_ABANDONED = "abandoned"
31
+
32
+ /** Boulder status: cancelled. */
33
+ export const BOULDER_STATUS_CANCELLED = "cancelled"
34
+
35
+ /** Raw boulder.json work/task status values. */
36
+ export const BOULDER_STATUSES = [
37
+ BOULDER_STATUS_IN_PROGRESS,
38
+ BOULDER_STATUS_RUNNING,
39
+ BOULDER_STATUS_ACTIVE,
40
+ BOULDER_STATUS_PENDING,
41
+ BOULDER_STATUS_COMPLETED,
42
+ BOULDER_STATUS_ERROR,
43
+ BOULDER_STATUS_PAUSED,
44
+ BOULDER_STATUS_ABANDONED,
45
+ BOULDER_STATUS_CANCELLED,
46
+ ] as const
47
+
48
+ /** A raw boulder.json work/task status value. */
49
+ export type BoulderStatus = (typeof BOULDER_STATUSES)[number]
@@ -0,0 +1,29 @@
1
+ /**
2
+ * pware.oc.omo.constants.dockind
3
+ *
4
+ * OMO document kinds: the plan, drafts, notepads and evidence under `.omo/`.
5
+ * Indexed in `pware.oc.omo/resolver/pware.oc.omo.resolver.doc.ts`.
6
+ */
7
+
8
+ /** Doc kind: the active plan. */
9
+ export const DOC_KIND_PLAN = "plan"
10
+
11
+ /** Doc kind: a draft plan still being written. */
12
+ export const DOC_KIND_DRAFT = "draft"
13
+
14
+ /** Doc kind: a notepad. */
15
+ export const DOC_KIND_NOTEPAD = "notepad"
16
+
17
+ /** Doc kind: evidence (proof) files. */
18
+ export const DOC_KIND_PROOF = "proof"
19
+
20
+ /** Every OMO document kind. */
21
+ export const DOC_KINDS = [
22
+ DOC_KIND_PLAN,
23
+ DOC_KIND_DRAFT,
24
+ DOC_KIND_NOTEPAD,
25
+ DOC_KIND_PROOF,
26
+ ] as const
27
+
28
+ /** An OMO document kind. */
29
+ export type DocKind = (typeof DOC_KINDS)[number]
@@ -0,0 +1,11 @@
1
+ export const EV_OMO_BOULDER_CHANGED = "pware.omo.boulder.changed"
2
+ export const EV_OMO_DOCS_CHANGED = "pware.omo.docs.changed"
3
+ export const EV_OMO_CONFIG_CHANGED = "pware.omo.config.changed"
4
+
5
+ export const OMO_EVENT_NAMES = [
6
+ EV_OMO_BOULDER_CHANGED,
7
+ EV_OMO_DOCS_CHANGED,
8
+ EV_OMO_CONFIG_CHANGED,
9
+ ] as const
10
+
11
+ export type OmoEventName = (typeof OMO_EVENT_NAMES)[number]
@@ -0,0 +1,60 @@
1
+ /**
2
+ * pware.oc.omo.constants.planstatus
3
+ *
4
+ * OMO plan/draft markdown frontmatter `status:` values that mean "waiting for
5
+ * user sign-off" (the PENDING_STATUS set currently private in the approval
6
+ * resolver), plus the terminal states of the plan lifecycle
7
+ * `drafting → awaiting-approval → approved → done`.
8
+ */
9
+
10
+ /** Plan status: awaiting the user's approval. */
11
+ export const PLAN_STATUS_AWAITING_APPROVAL = "awaiting-approval"
12
+
13
+ /** Plan status: pending approval (hyphenated spelling). */
14
+ export const PLAN_STATUS_PENDING_APPROVAL = "pending-approval"
15
+
16
+ /** Plan status: pending approval (underscore spelling). */
17
+ export const PLAN_STATUS_PENDING_APPROVAL_UNDERSCORE = "pending_approval"
18
+
19
+ /** Plan status: pending (bare spelling). */
20
+ export const PLAN_STATUS_PENDING = "pending"
21
+
22
+ /** Plan status: draft still being written — not yet awaiting approval. */
23
+ export const PLAN_STATUS_DRAFTING = "drafting"
24
+
25
+ /** Plan status: the user approved the plan. */
26
+ export const PLAN_STATUS_APPROVED = "approved"
27
+
28
+ /** Plan status: the plan finished execution. */
29
+ export const PLAN_STATUS_DONE = "done"
30
+
31
+ /** Plan `status:` values that mean the plan is waiting for user sign-off. */
32
+ export const PLAN_PENDING_STATUSES = [
33
+ PLAN_STATUS_AWAITING_APPROVAL,
34
+ PLAN_STATUS_PENDING_APPROVAL,
35
+ PLAN_STATUS_PENDING_APPROVAL_UNDERSCORE,
36
+ PLAN_STATUS_PENDING,
37
+ ] as const
38
+
39
+ /** A plan `status:` value that counts as pending user approval. */
40
+ export type PlanPendingStatus = (typeof PLAN_PENDING_STATUSES)[number]
41
+
42
+ /** Work state: a boulder work for this plan finished. */
43
+ export const WORK_STATE_COMPLETED = "completed"
44
+
45
+ /** Work state: a boulder work exists but did not finish. */
46
+ export const WORK_STATE_NOT_COMPLETED = "not-completed"
47
+
48
+ /** Work state: no boulder work for this plan (or no boulder.json). */
49
+ export const WORK_STATE_ABSENT = "absent"
50
+
51
+ /**
52
+ * How the plan's boulder work relates to "finished", for the My-work
53
+ * reconciliation. `completed` = a boulder work for this plan finished;
54
+ * `not-completed` = a work exists but did not finish (running / error / paused /
55
+ * abandoned); `absent` = no boulder work for this plan (or no boulder.json).
56
+ */
57
+ export type WorkState =
58
+ | typeof WORK_STATE_COMPLETED
59
+ | typeof WORK_STATE_NOT_COMPLETED
60
+ | typeof WORK_STATE_ABSENT
@@ -0,0 +1,49 @@
1
+ /**
2
+ * pware.oc.omo.constants.reviewstatus
3
+ *
4
+ * OMO `ulw-plan` review-lifecycle status values — the state machine that runs
5
+ * a plan through the review lanes (momus / independent). Transitions:
6
+ * `pending -> launching -> in_flight -> approved | changes_requested |
7
+ * inconclusive`; `round_status` is `active` while a round is live.
8
+ */
9
+
10
+ /** Review status: lane created, waiting to be launched. */
11
+ export const REVIEW_STATUS_PENDING = "pending"
12
+
13
+ /** Review status: reviewer process spawned, no receipt yet. */
14
+ export const REVIEW_STATUS_LAUNCHING = "launching"
15
+
16
+ /** Review status: reviewer process has a receipt and is working. */
17
+ export const REVIEW_STATUS_IN_FLIGHT = "in_flight"
18
+
19
+ /** Review status: reviewer approved the plan. */
20
+ export const REVIEW_STATUS_APPROVED = "approved"
21
+
22
+ /** Review status: reviewer requested changes. */
23
+ export const REVIEW_STATUS_CHANGES_REQUESTED = "changes_requested"
24
+
25
+ /** Review status: reviewer could not reach a verdict. */
26
+ export const REVIEW_STATUS_INCONCLUSIVE = "inconclusive"
27
+
28
+ /** Review status: a review round is live. */
29
+ export const ROUND_STATUS_ACTIVE = "active"
30
+
31
+ /** Every `ulw-plan` review-lifecycle status value. */
32
+ export const REVIEW_STATUSES = [
33
+ REVIEW_STATUS_PENDING,
34
+ REVIEW_STATUS_LAUNCHING,
35
+ REVIEW_STATUS_IN_FLIGHT,
36
+ REVIEW_STATUS_APPROVED,
37
+ REVIEW_STATUS_CHANGES_REQUESTED,
38
+ REVIEW_STATUS_INCONCLUSIVE,
39
+ ] as const
40
+
41
+ /** A single `ulw-plan` review-lifecycle status value. */
42
+ export type ReviewStatus = (typeof REVIEW_STATUSES)[number]
43
+
44
+ /** Terminal review statuses — a lane ends here, never resumes. */
45
+ export const TERMINAL_REVIEW_STATUSES = [
46
+ REVIEW_STATUS_APPROVED,
47
+ REVIEW_STATUS_CHANGES_REQUESTED,
48
+ REVIEW_STATUS_INCONCLUSIVE,
49
+ ] as const
@@ -0,0 +1,25 @@
1
+ /**
2
+ * pware.oc.omo.constants.startwork
3
+ *
4
+ * Delivery modes for the OMO `start work` command. Built into the exact
5
+ * command text in `pware.oc.runtime/pware.oc.runtime.mywork.ts`.
6
+ */
7
+
8
+ /** Start-work mode: plain `start work <plan>`. */
9
+ export const START_WORK_PLAIN = "plain"
10
+
11
+ /** Start-work mode: `start work <plan> --make-pr`. */
12
+ export const START_WORK_MAKE_PR = "make-pr"
13
+
14
+ /** Start-work mode: `start work <plan> --ship`. */
15
+ export const START_WORK_SHIP = "ship"
16
+
17
+ /** Every start-work delivery mode. */
18
+ export const START_WORK_MODES = [
19
+ START_WORK_PLAIN,
20
+ START_WORK_MAKE_PR,
21
+ START_WORK_SHIP,
22
+ ] as const
23
+
24
+ /** A start-work delivery mode. */
25
+ export type StartWorkMode = (typeof START_WORK_MODES)[number]
@@ -0,0 +1,38 @@
1
+ /**
2
+ * pware.oc.omo.constants.verdict
3
+ *
4
+ * OMO review lane verdicts — the outcome a reviewer lane reports at the end of
5
+ * a `ulw-plan` review round (`review-work` / `visual-qa` lane protocol: one
6
+ * verdict per lane, one-shot; a re-review after fixes is a fresh round).
7
+ */
8
+
9
+ /** Verdict: the review passed. */
10
+ export const VERDICT_PASS = "pass"
11
+
12
+ /** Verdict: the review found blocking problems. */
13
+ export const VERDICT_FAIL = "fail"
14
+
15
+ /** Verdict: the reviewer could not reach a conclusion. */
16
+ export const VERDICT_INCONCLUSIVE = "inconclusive"
17
+
18
+ /** Verdict: approved with or without notes. */
19
+ export const VERDICT_APPROVED = "approved"
20
+
21
+ /** Verdict: blocked, needs changes before a re-review. */
22
+ export const VERDICT_BLOCKED = "blocked"
23
+
24
+ /** Verdict: reviewer working on a long pass (progress signal). */
25
+ export const VERDICT_WORKING = "working"
26
+
27
+ /** Every review lane verdict value. */
28
+ export const VERDICTS = [
29
+ VERDICT_PASS,
30
+ VERDICT_FAIL,
31
+ VERDICT_INCONCLUSIVE,
32
+ VERDICT_APPROVED,
33
+ VERDICT_BLOCKED,
34
+ VERDICT_WORKING,
35
+ ] as const
36
+
37
+ /** A single review lane verdict value. */
38
+ export type Verdict = (typeof VERDICTS)[number]
@@ -0,0 +1,7 @@
1
+ /**
2
+ * pware.oc.omo
3
+ *
4
+ * oh-my-openagent domain: boulder, plans, approvals, docs index and config.
5
+ * Imports core only.
6
+ */
7
+ export * from "./resolver/index.js"
@@ -0,0 +1,19 @@
1
+ /**
2
+ * pware.oc.core.omo.resolver
3
+ *
4
+ * Aggregate of the omo resolvers: boulder/works/tasks/delegates, plan parsing,
5
+ * the approval queue, the docs index and the omo config. Re-exports the entity
6
+ * resolvers so consumers import from one module.
7
+ */
8
+ export * from "./pware.oc.omo.resolver.boulder.js"
9
+ export * from "./pware.oc.omo.resolver.plan.js"
10
+ export * from "./pware.oc.omo.resolver.planFile.js"
11
+ export * from "./pware.oc.omo.resolver.draftFile.js"
12
+ export * from "./pware.oc.omo.resolver.notepadsFile.js"
13
+ export * from "./pware.oc.omo.resolver.proofFile.js"
14
+ export * from "./pware.oc.omo.resolver.rulesFile.js"
15
+ export * from "./pware.oc.omo.resolver.runContinuationFile.js"
16
+ export * from "./pware.oc.omo.resolver.approval.js"
17
+ export * from "./pware.oc.omo.resolver.approvalState.js"
18
+ export * from "./pware.oc.omo.resolver.doc.js"
19
+ export * from "./pware.oc.omo.resolver.config.js"
@@ -0,0 +1,179 @@
1
+ /**
2
+ * pware.oc.core.omo.resolver.approval
3
+ *
4
+ * OMO plan approval queue — drafts/plans under `.omo/` (or legacy `.sisyphus/`)
5
+ * whose `status` says they are waiting for the user's sign-off. File discovery
6
+ * and stat are shared with the docs index: both this module and `doc.ts` read
7
+ * one per-root omo scan cache, so `.omo/` is walked once per TTL no matter how
8
+ * many consumers ask. Classification then reads each plan/draft file's
9
+ * frontmatter; the result is memoized against the same scan record and is
10
+ * recomputed only when that record turns over. A missing `.omo/` is an empty
11
+ * list, not an error.
12
+ */
13
+ import fs from "node:fs"
14
+ import path from "node:path"
15
+ import { profile } from "../../pware.oc.core/pware.oc.core.debug.js"
16
+ import { canonicalizePath } from "../../pware.oc.core/pware.oc.core.paths.js"
17
+ import {
18
+ MY_WORK_GROUP_DRAFTING,
19
+ MY_WORK_GROUP_FINISHED,
20
+ MY_WORK_GROUP_READY_REVIEW,
21
+ MY_WORK_GROUP_READY_START,
22
+ } from "../../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
23
+ import { resolveApprovalGroup } from "./pware.oc.omo.resolver.approvalGroup.js"
24
+ import { planWorkStateByPlanName } from "./pware.oc.omo.resolver.boulder.js"
25
+ import {
26
+ approvalName,
27
+ parsePlanPendingAction,
28
+ parsePlanStatus,
29
+ parseReviewBlock,
30
+ type ApprovalItem,
31
+ } from "./pware.oc.omo.resolver.plan.js"
32
+ import { DOC_KIND_DRAFT, DOC_KIND_PLAN } from "../constants/pware.oc.omo.constants.docKind.js"
33
+ import {
34
+ omoKindRows,
35
+ omoScanRecord,
36
+ resetDocsCache,
37
+ type OmoDocScan,
38
+ } from "./pware.oc.omo.resolver.doc.js"
39
+ import type { DocView } from "./pware.oc.omo.resolver.doc.js"
40
+
41
+ const MAX_ITEMS = 40
42
+
43
+ /** The "My work" approval buckets, keyed by group, in scan order. */
44
+ export type ScanResult = {
45
+ drafting: ApprovalItem[]
46
+ readyReview: ApprovalItem[]
47
+ readyStart: ApprovalItem[]
48
+ finished: ApprovalItem[]
49
+ /** Draft documents no action group covers — approved/done, unknown or no status. */
50
+ draftDocs: ApprovalItem[]
51
+ /** Plan documents no action group covers — unknown or no status. */
52
+ plans: ApprovalItem[]
53
+ }
54
+
55
+ function emptyScan(): ScanResult {
56
+ return {
57
+ drafting: [],
58
+ readyReview: [],
59
+ readyStart: [],
60
+ finished: [],
61
+ draftDocs: [],
62
+ plans: [],
63
+ }
64
+ }
65
+
66
+ function sortApprovals(items: ApprovalItem[]): ApprovalItem[] {
67
+ items.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0) || a.name.localeCompare(b.name))
68
+ return items.slice(0, MAX_ITEMS)
69
+ }
70
+
71
+ function isMarkdown(rel: string): boolean {
72
+ return rel.toLowerCase().endsWith(".md")
73
+ }
74
+
75
+ /** Drafts/plans split into the four "My work" buckets by status + file type. */
76
+ function classify(
77
+ root: string,
78
+ draftRows: readonly DocView[],
79
+ planRows: readonly DocView[],
80
+ ): ScanResult {
81
+ const drafting: ApprovalItem[] = []
82
+ const readyReview: ApprovalItem[] = []
83
+ const readyStart: ApprovalItem[] = []
84
+ const finished: ApprovalItem[] = []
85
+ const draftDocs: ApprovalItem[] = []
86
+ const plans: ApprovalItem[] = []
87
+ const seen = new Set<string>()
88
+ const workStates = planWorkStateByPlanName(root)
89
+ const visit = (rows: readonly DocView[], isDraft: boolean) => {
90
+ for (const row of rows) {
91
+ const rel = row.rel
92
+ if (!isMarkdown(rel) || seen.has(rel)) continue
93
+ let text = ""
94
+ try {
95
+ text = fs.readFileSync(path.join(root, rel), "utf8")
96
+ } catch {
97
+ continue
98
+ }
99
+ const status = parsePlanStatus(text)
100
+ const name = approvalName(rel)
101
+ const workState = workStates.get(name) ?? "absent"
102
+ // A plan with no parseable status still reconciles against boulder: one
103
+ // whose boulder work completed lands in Finished (resolveApprovalGroup →
104
+ // planWorkDone returns true for a completed work state regardless of
105
+ // status). A no-status plan with no completed work falls through to the
106
+ // Plans archive below; a no-status draft is a working document — Draft docs.
107
+ const group = resolveApprovalGroup(status, isDraft, workState, false)
108
+ const item: ApprovalItem = {
109
+ rel,
110
+ name,
111
+ status,
112
+ pendingAction: parsePlanPendingAction(text),
113
+ updatedAt: row.updatedAt,
114
+ review: parseReviewBlock(text),
115
+ workState,
116
+ }
117
+ seen.add(rel)
118
+ if (!group) {
119
+ // A document no action group covers (superseded approved/done, unknown
120
+ // or no status) is browsable, not a queue item: drafts → Draft docs,
121
+ // plans → Plans.
122
+ if (isDraft) draftDocs.push(item)
123
+ else plans.push(item)
124
+ continue
125
+ }
126
+ switch (group) {
127
+ case MY_WORK_GROUP_DRAFTING:
128
+ drafting.push(item)
129
+ break
130
+ case MY_WORK_GROUP_READY_REVIEW:
131
+ readyReview.push(item)
132
+ break
133
+ case MY_WORK_GROUP_READY_START:
134
+ readyStart.push(item)
135
+ break
136
+ case MY_WORK_GROUP_FINISHED:
137
+ finished.push(item)
138
+ break
139
+ }
140
+ }
141
+ }
142
+ visit(draftRows, true)
143
+ visit(planRows, false)
144
+ return {
145
+ drafting: sortApprovals(drafting),
146
+ readyReview: sortApprovals(readyReview),
147
+ readyStart: sortApprovals(readyStart),
148
+ finished: sortApprovals(finished),
149
+ draftDocs: sortApprovals(draftDocs),
150
+ plans: sortApprovals(plans),
151
+ }
152
+ }
153
+
154
+ /** Approval buckets memoized against the shared per-root omo scan record. */
155
+ const approvalMemo = new WeakMap<OmoDocScan, ScanResult>()
156
+
157
+ /** Drop the shared omo scan cache — approvals and docs both re-read next call. */
158
+ export function resetApprovalsCache(): void {
159
+ resetDocsCache()
160
+ }
161
+
162
+ /** Drafts/plans split into the four "My work" buckets by status + file type. */
163
+ export function listApprovals(projectRoot: string | null | undefined): ScanResult {
164
+ if (!projectRoot) return emptyScan()
165
+ const root = canonicalizePath(projectRoot)
166
+ const scan = omoScanRecord(root)
167
+ if (!scan) return emptyScan()
168
+ const memoized = approvalMemo.get(scan)
169
+ if (memoized) return memoized
170
+ const result = profile("omo.approvals", () =>
171
+ classify(
172
+ root,
173
+ omoKindRows(DOC_KIND_DRAFT, root),
174
+ omoKindRows(DOC_KIND_PLAN, root),
175
+ ),
176
+ )
177
+ approvalMemo.set(scan, result)
178
+ return result
179
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * pware.oc.omo.resolver.approvalGroup
3
+ *
4
+ * Which "My work" approval group a plan belongs to, from its OMO plan status
5
+ * alone, plus whether a plan path is still a draft. Lives in omo (not core)
6
+ * because it consumes the OMO plan-status constants; core may not import them.
7
+ */
8
+ import {
9
+ MY_WORK_GROUP_DRAFTING,
10
+ MY_WORK_GROUP_FINISHED,
11
+ MY_WORK_GROUP_READY_REVIEW,
12
+ MY_WORK_GROUP_READY_START,
13
+ type ApprovalGroupKind,
14
+ } from "../../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
15
+ import {
16
+ PLAN_PENDING_STATUSES,
17
+ PLAN_STATUS_APPROVED,
18
+ PLAN_STATUS_DONE,
19
+ PLAN_STATUS_DRAFTING,
20
+ WORK_STATE_ABSENT,
21
+ WORK_STATE_COMPLETED,
22
+ type WorkState,
23
+ } from "../../pware.oc.omo/constants/pware.oc.omo.constants.planStatus.js"
24
+
25
+ /** The pending sign-off set widened so `.includes()` accepts any status string. */
26
+ const PENDING_STATUSES: readonly string[] = PLAN_PENDING_STATUSES
27
+
28
+ /**
29
+ * Which approval group a plan belongs to, from its OMO status alone:
30
+ * `drafting` while still a draft, `ready-to-review` for a pending status,
31
+ * `ready-to-start` for an approved plan, `finished` for a done plan. Null when
32
+ * the item is superseded — an approved or done draft, or an unknown status —
33
+ * and must not be shown.
34
+ */
35
+ export function approvalGroup(
36
+ status: string | null,
37
+ isDraft: boolean,
38
+ ): ApprovalGroupKind | null {
39
+ const s = (status ?? "").toLowerCase()
40
+ if (s === PLAN_STATUS_DRAFTING) return MY_WORK_GROUP_DRAFTING
41
+ if (PENDING_STATUSES.includes(s)) return MY_WORK_GROUP_READY_REVIEW
42
+ if (s === PLAN_STATUS_APPROVED) return isDraft ? null : MY_WORK_GROUP_READY_START
43
+ if (s === PLAN_STATUS_DONE) return isDraft ? null : MY_WORK_GROUP_FINISHED
44
+ return null
45
+ }
46
+
47
+ /** True when a plan path points at a draft still being written, not a final plan. */
48
+ export function isDraftOf(rel: string): boolean {
49
+ return rel.startsWith("drafts/") || rel.startsWith(".sisyphus/drafts/")
50
+ }
51
+
52
+ /**
53
+ * True when we have trustworthy evidence the plan's work finished: a boulder
54
+ * work completed (layer 1), or — with no boulder work for this plan — the
55
+ * writer session's todos all completed (layer 2). Layer 2 only applies to an
56
+ * `approved` plan; a pending/drafting plan was never cleared to start, so its
57
+ * completed todos are the planner's, not the work's.
58
+ */
59
+ export function planWorkDone(
60
+ status: string | null,
61
+ workState: WorkState,
62
+ todosDone: boolean,
63
+ ): boolean {
64
+ const s = (status ?? "").toLowerCase()
65
+ if (workState === WORK_STATE_COMPLETED) return true
66
+ if (workState === WORK_STATE_ABSENT && todosDone && s === PLAN_STATUS_APPROVED) return true
67
+ return false
68
+ }
69
+
70
+ /**
71
+ * The effective My-work group, reconciling the (untrusted) frontmatter status
72
+ * against boulder + db evidence. Done work → finished regardless of the
73
+ * frontmatter (a draft stays superseded); otherwise it falls back to the pure
74
+ * `approvalGroup` mapping, so the plugin still works with no boulder and no db.
75
+ */
76
+ export function resolveApprovalGroup(
77
+ status: string | null,
78
+ isDraft: boolean,
79
+ workState: WorkState,
80
+ todosDone: boolean,
81
+ ): ApprovalGroupKind | null {
82
+ if (planWorkDone(status, workState, todosDone)) {
83
+ return isDraft ? null : MY_WORK_GROUP_FINISHED
84
+ }
85
+ return approvalGroup(status, isDraft)
86
+ }
87
+
88
+ /** True when the group is the drafting bucket. */
89
+ export function isDrafting(g: ApprovalGroupKind | null): boolean {
90
+ return g === MY_WORK_GROUP_DRAFTING
91
+ }
92
+
93
+ /** True when the group is waiting for the user's sign-off. */
94
+ export function isReadyToReview(g: ApprovalGroupKind | null): boolean {
95
+ return g === MY_WORK_GROUP_READY_REVIEW
96
+ }
97
+
98
+ /** Alias for isReadyToReview — a plan awaiting approval. */
99
+ export function isWaitingApproval(g: ApprovalGroupKind | null): boolean {
100
+ return g === MY_WORK_GROUP_READY_REVIEW
101
+ }
102
+
103
+ /** Alias for isReadyToReview — a plan pending approval. */
104
+ export function isPendingApproval(g: ApprovalGroupKind | null): boolean {
105
+ return g === MY_WORK_GROUP_READY_REVIEW
106
+ }
107
+
108
+ /** True when the group is approved and ready to start. */
109
+ export function isReadyToStart(g: ApprovalGroupKind | null): boolean {
110
+ return g === MY_WORK_GROUP_READY_START
111
+ }
112
+
113
+ /** True when the group is finished. */
114
+ export function isFinished(g: ApprovalGroupKind | null): boolean {
115
+ return g === MY_WORK_GROUP_FINISHED
116
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * pware.oc.omo.resolver.approvalstate
3
+ *
4
+ * Reads the planner session's `.omo/run-continuation` background-task marker.
5
+ * Lives in the omo layer — no sibling domain may read omo files. The runtime
6
+ * layer's my-work enrich module composes this marker with the session activity
7
+ * state.
8
+ */
9
+ import path from "node:path"
10
+ import { firstOmoPath } from "./pware.oc.omo.resolver.boulder.js"
11
+ import { readJson } from "../../pware.oc.core/pware.oc.core.paths.js"
12
+
13
+ /** First existing `.omo`/`.sisyphus` run-continuation directory, or null. */
14
+ export function firstRunContinuationDir(projectRoot: string): string | null {
15
+ return firstOmoPath(projectRoot, "run-continuation")
16
+ }
17
+
18
+ /**
19
+ * The `.omo/run-continuation` background-task state for a session, or null when
20
+ * absent/unreadable.
21
+ */
22
+ export function readRunContinuationState(
23
+ projectRoot: string | null | undefined,
24
+ sessionId: string,
25
+ ): string | null {
26
+ if (!projectRoot) return null
27
+ const dir = firstRunContinuationDir(projectRoot)
28
+ if (!dir) return null
29
+ const raw = readJson(path.join(dir, `${sessionId}.json`)) as {
30
+ sources?: { "background-task"?: { state?: unknown } }
31
+ } | null
32
+ const state = raw?.sources?.["background-task"]?.state
33
+ return typeof state === "string" ? state : null
34
+ }