cloving 1.1.0 → 1.2.0

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 (213) hide show
  1. package/README.md +121 -21
  2. package/assets/watch-fonts/fira-code-OFL.md +93 -0
  3. package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
  4. package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
  5. package/assets/watch-fonts/heebo-OFL.md +93 -0
  6. package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
  7. package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
  8. package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
  9. package/assets/watch-fonts/manifest.json +112 -0
  10. package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
  11. package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
  12. package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
  13. package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
  14. package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
  15. package/dist/src/authority/commands.d.ts +1 -0
  16. package/dist/src/authority/commands.js +25 -4
  17. package/dist/src/authority/dispatch-decision.d.ts +1 -0
  18. package/dist/src/authority/dispatch-decision.js +7 -4
  19. package/dist/src/authority/events.js +2 -2
  20. package/dist/src/authority/handoff-chain.d.ts +24 -0
  21. package/dist/src/authority/handoff-chain.js +46 -0
  22. package/dist/src/authority/reconciliation.d.ts +1 -0
  23. package/dist/src/authority/reconciliation.js +18 -11
  24. package/dist/src/authority/transitions.d.ts +1 -1
  25. package/dist/src/authority/transitions.js +3 -0
  26. package/dist/src/broker/actor/authority-queries.d.ts +4 -0
  27. package/dist/src/broker/actor/authority-queries.js +51 -2
  28. package/dist/src/broker/actor/delivery-intents.d.ts +1 -0
  29. package/dist/src/broker/actor/effect-delivery.js +9 -0
  30. package/dist/src/broker/authority-admission.js +13 -5
  31. package/dist/src/chats/analysis-batches.d.ts +18 -0
  32. package/dist/src/chats/analysis-batches.js +15 -1
  33. package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
  34. package/dist/src/chats/analysis-checkpoint.js +31 -0
  35. package/dist/src/chats/analysis-input.d.ts +7 -1
  36. package/dist/src/chats/analysis-input.js +20 -6
  37. package/dist/src/chats/analysis-merge.d.ts +16 -0
  38. package/dist/src/chats/analysis-merge.js +134 -0
  39. package/dist/src/chats/analysis-prompt.d.ts +8 -0
  40. package/dist/src/chats/analysis-prompt.js +27 -1
  41. package/dist/src/chats/analysis-proposal.d.ts +2 -0
  42. package/dist/src/chats/analysis-proposal.js +9 -0
  43. package/dist/src/chats/analysis-shape.d.ts +1 -0
  44. package/dist/src/chats/analysis-shape.js +11 -4
  45. package/dist/src/chats/reference-mapping.d.ts +16 -0
  46. package/dist/src/chats/reference-mapping.js +153 -0
  47. package/dist/src/chats/workflow-generation-projection.d.ts +8 -0
  48. package/dist/src/chats/workflow-generation-projection.js +75 -0
  49. package/dist/src/chats/workflow-generation-source.d.ts +25 -0
  50. package/dist/src/chats/workflow-generation-source.js +124 -0
  51. package/dist/src/chats/workflow-generation-text.d.ts +23 -0
  52. package/dist/src/chats/workflow-generation-text.js +74 -0
  53. package/dist/src/chats/workflow-generation.d.ts +69 -0
  54. package/dist/src/chats/workflow-generation.js +142 -0
  55. package/dist/src/cli/render.d.ts +1 -0
  56. package/dist/src/cli/render.js +60 -13
  57. package/dist/src/cli/usage.js +5 -2
  58. package/dist/src/cli/watch-board-view.d.ts +12 -1
  59. package/dist/src/cli/watch-board-view.js +57 -11
  60. package/dist/src/cli/watch-board.d.ts +7 -1
  61. package/dist/src/cli/watch-board.js +42 -10
  62. package/dist/src/cli/watch-client.d.ts +1 -1
  63. package/dist/src/cli/watch-client.js +7 -3
  64. package/dist/src/cli/watch-model.d.ts +10 -4
  65. package/dist/src/cli/watch-model.js +35 -58
  66. package/dist/src/cli/watch-page.js +21 -4
  67. package/dist/src/cli/watch-phases.js +3 -3
  68. package/dist/src/cli/watch-pr-command.d.ts +5 -2
  69. package/dist/src/cli/watch-pr-command.js +41 -4
  70. package/dist/src/cli/watch-pr-identity.d.ts +14 -2
  71. package/dist/src/cli/watch-pr-identity.js +25 -0
  72. package/dist/src/cli/watch-pr-observer.d.ts +1 -0
  73. package/dist/src/cli/watch-pr-observer.js +48 -6
  74. package/dist/src/cli/watch-pull-request.d.ts +10 -0
  75. package/dist/src/cli/watch-pull-request.js +130 -0
  76. package/dist/src/cli/watch-reads.d.ts +7 -1
  77. package/dist/src/cli/watch-reads.js +42 -20
  78. package/dist/src/cli/watch-render.d.ts +14 -1
  79. package/dist/src/cli/watch-render.js +2 -1
  80. package/dist/src/cli/watch-server.js +33 -2
  81. package/dist/src/cli/watch-turn.js +1 -1
  82. package/dist/src/cli/watch-view.d.ts +7 -0
  83. package/dist/src/cli/watch-view.js +51 -3
  84. package/dist/src/daemon/analysis-worker.d.ts +0 -2
  85. package/dist/src/daemon/analysis-worker.js +71 -19
  86. package/dist/src/daemon/chats-batch-binding.d.ts +23 -0
  87. package/dist/src/daemon/chats-batch-binding.js +99 -0
  88. package/dist/src/daemon/chats-capture.d.ts +18 -0
  89. package/dist/src/daemon/chats-capture.js +194 -0
  90. package/dist/src/daemon/chats-checkpoints.d.ts +41 -0
  91. package/dist/src/daemon/chats-checkpoints.js +186 -0
  92. package/dist/src/daemon/chats-files.d.ts +29 -2
  93. package/dist/src/daemon/chats-files.js +142 -3
  94. package/dist/src/daemon/chats-follow-up.d.ts +38 -0
  95. package/dist/src/daemon/chats-follow-up.js +180 -0
  96. package/dist/src/daemon/chats-question.d.ts +15 -0
  97. package/dist/src/daemon/chats-question.js +93 -0
  98. package/dist/src/daemon/chats-worker.d.ts +1 -0
  99. package/dist/src/daemon/chats-worker.js +52 -51
  100. package/dist/src/daemon/claude-turn.d.ts +2 -1
  101. package/dist/src/daemon/claude-turn.js +1 -1
  102. package/dist/src/daemon/claude-worker.d.ts +0 -2
  103. package/dist/src/daemon/claude-worker.js +6 -11
  104. package/dist/src/daemon/daemon.d.ts +5 -1
  105. package/dist/src/daemon/daemon.js +38 -10
  106. package/dist/src/daemon/delivery-router.js +6 -0
  107. package/dist/src/daemon/github-calls.d.ts +4 -0
  108. package/dist/src/daemon/github-calls.js +16 -7
  109. package/dist/src/daemon/github-ci.d.ts +6 -0
  110. package/dist/src/daemon/github-ci.js +170 -0
  111. package/dist/src/daemon/github-merge-call.d.ts +14 -0
  112. package/dist/src/daemon/github-merge-call.js +73 -0
  113. package/dist/src/daemon/github-merge.d.ts +3 -5
  114. package/dist/src/daemon/github-merge.js +52 -95
  115. package/dist/src/daemon/github-methods.d.ts +28 -0
  116. package/dist/src/daemon/github-methods.js +80 -16
  117. package/dist/src/daemon/github-operation.d.ts +2 -0
  118. package/dist/src/daemon/github-retry.d.ts +6 -0
  119. package/dist/src/daemon/github-retry.js +49 -0
  120. package/dist/src/daemon/github-ticket-status.js +27 -1
  121. package/dist/src/daemon/github-worker.js +2 -1
  122. package/dist/src/daemon/handoff-worker.d.ts +10 -0
  123. package/dist/src/daemon/handoff-worker.js +232 -0
  124. package/dist/src/daemon/issue-queue.d.ts +1 -0
  125. package/dist/src/daemon/issue-queue.js +94 -42
  126. package/dist/src/daemon/notify-journal.d.ts +18 -0
  127. package/dist/src/daemon/notify-journal.js +108 -0
  128. package/dist/src/daemon/notify-message.js +2 -1
  129. package/dist/src/daemon/notify.js +176 -37
  130. package/dist/src/daemon/retrying-turn.d.ts +3 -0
  131. package/dist/src/daemon/retrying-turn.js +55 -9
  132. package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
  133. package/dist/src/daemon/ticket-dependency-waits.js +60 -0
  134. package/dist/src/daemon/ticket-registration.d.ts +8 -4
  135. package/dist/src/daemon/ticket-registration.js +76 -22
  136. package/dist/src/daemon/ticket-source.d.ts +4 -1
  137. package/dist/src/daemon/ticket-source.js +8 -2
  138. package/dist/src/decision-visibility.d.ts +2 -0
  139. package/dist/src/decision-visibility.js +10 -0
  140. package/dist/src/execution-pin.d.ts +4 -0
  141. package/dist/src/execution-pin.js +23 -2
  142. package/dist/src/host/start-delivery.d.ts +2 -1
  143. package/dist/src/host/start-delivery.js +1 -1
  144. package/dist/src/host/step-bridge-host.d.ts +1 -0
  145. package/dist/src/host/step-bridge-host.js +16 -0
  146. package/dist/src/host/world-reconciliation.d.ts +1 -0
  147. package/dist/src/host/world-reconciliation.js +3 -0
  148. package/dist/src/host/world-runs.js +5 -0
  149. package/dist/src/issue-identity.d.ts +6 -0
  150. package/dist/src/issue-identity.js +23 -0
  151. package/dist/src/service/queue-runs.d.ts +3 -0
  152. package/dist/src/service/queue-runs.js +39 -0
  153. package/dist/src/service/registry.d.ts +8 -2
  154. package/dist/src/service/registry.js +20 -8
  155. package/dist/src/service/replies.d.ts +2 -0
  156. package/dist/src/service/run-handlers.js +44 -12
  157. package/dist/src/service/service.d.ts +3 -0
  158. package/dist/src/service/service.js +3 -1
  159. package/dist/src/service/submission-handler.d.ts +1 -0
  160. package/dist/src/service/submission-handler.js +92 -13
  161. package/dist/src/service/worker-totals.js +25 -1
  162. package/dist/src/step-bridge.d.ts +9 -0
  163. package/dist/src/steps/handoff.d.ts +2 -0
  164. package/dist/src/steps/handoff.js +13 -0
  165. package/dist/src/ticket-dependencies.d.ts +1 -0
  166. package/dist/src/ticket-dependencies.js +15 -0
  167. package/dist/src/ticket-status.js +7 -4
  168. package/dist/src/token-prices.d.ts +2 -0
  169. package/dist/src/token-prices.js +41 -9
  170. package/dist/src/worker-usage.d.ts +9 -0
  171. package/dist/src/worker-usage.js +1 -1
  172. package/dist/src/workflow-admission.d.ts +1 -0
  173. package/dist/src/workflow-candidate.js +1 -0
  174. package/dist/src/workflow-contracts.d.ts +2 -0
  175. package/dist/src/workflow-contracts.js +8 -3
  176. package/dist/src/workflow-declaration.d.ts +11 -0
  177. package/dist/src/workflow-declaration.js +71 -15
  178. package/dist/src/workflow-discovery.d.ts +18 -0
  179. package/dist/src/workflow-discovery.js +33 -0
  180. package/dist/src/workflow-refusals.d.ts +6 -0
  181. package/dist/src/workflow-refusals.js +39 -0
  182. package/dist/src/workflows.d.ts +2 -1
  183. package/dist/src/workflows.js +1 -0
  184. package/dist/tools/admit-workflow.d.ts +13 -0
  185. package/dist/tools/admit-workflow.js +94 -0
  186. package/dist/tools/self-host-project.d.ts +17 -0
  187. package/dist/tools/self-host-project.js +177 -0
  188. package/dist/tools/self-host.js +27 -81
  189. package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
  190. package/dist/tools/workflow-bundle-dependencies.js +93 -0
  191. package/dist/tools/workflow-bundles.d.ts +20 -0
  192. package/dist/tools/workflow-bundles.js +173 -0
  193. package/dist/tools/workflow-candidate-counts.d.ts +8 -0
  194. package/dist/tools/workflow-candidate-counts.js +251 -0
  195. package/dist/tools/workflow-candidate-program.d.ts +11 -0
  196. package/dist/tools/workflow-candidate-program.js +78 -0
  197. package/dist/tools/workflow-candidate-source.d.ts +6 -0
  198. package/dist/tools/workflow-candidate-source.js +107 -0
  199. package/dist/tools/workflow-candidate-syntax.d.ts +15 -0
  200. package/dist/tools/workflow-candidate-syntax.js +219 -0
  201. package/dist/tools/workflow-folder-capture.d.ts +17 -0
  202. package/dist/tools/workflow-folder-capture.js +216 -0
  203. package/dist/tools/workflow-folders.d.ts +33 -0
  204. package/dist/tools/workflow-folders.js +150 -0
  205. package/dist/tools/workflow-source-effects.d.ts +10 -0
  206. package/dist/tools/workflow-source-effects.js +213 -0
  207. package/dist/workflows/analyze-chats.d.ts +6 -1
  208. package/dist/workflows/analyze-chats.declaration.json +14 -1
  209. package/dist/workflows/analyze-chats.js +188 -11
  210. package/dist/workflows/develop-prd.js +71 -3
  211. package/dist/workflows/develop-ticket.js +5 -0
  212. package/dist/workflows/ticket-prompts.js +12 -2
  213. package/package.json +21 -3
package/README.md CHANGED
@@ -77,19 +77,43 @@ Console output contains counts, fixed codes and an opaque import ID. Source path
77
77
 
78
78
  ### Protected chat analysis files
79
79
 
80
- The daemon provides `chats` capability methods `read-analysis` and `save-analysis` only to the registered `analyze-chats` workflow. A declaration must explicitly name `chats`; existing workflows retain their capabilities. Start one analysis with `cloving run analyze-chats --input input.json`, where the file contains exactly `{ "importId": "11111111-1111-4111-8111-111111111111" }` using your redacted import ID. The declared workflow charges three effect units for sequential read, one model turn and save. No evidence path is accepted.
80
+ The daemon provides `chats` capability methods `read-analysis` and `save-analysis` only to the registered `analyze-chats` workflow. A declaration must explicitly name `chats`; existing workflows retain their capabilities. Start one analysis with `cloving run analyze-chats --input input.json`, where the file contains exactly `{ "importId": "11111111-1111-4111-8111-111111111111" }` using your redacted import ID. The declaration allows eleven effect units: one capture, up to four restricted turns and four checkpoint saves, with two units reserved for question continuation. A run without a question charges one unit for capture and two per accepted batch. No evidence path is accepted.
81
81
 
82
- `read-analysis` takes `{ importId }`, with the same lowercase UUID v4 syntax as redaction and the import ID as its protected target. It reads only `redaction.json`, `redacted.jsonl` and `structure.json` from the resolved runtime import directory. Its completed result contains `{ snapshot }`, whose `importId`, `redaction`, `corpus` and `structure` fields are strings. Keep these strings in private durable state; parsing and serializing corpus numbers can lose their exact tokens. Original corpus, coverage, revision and transcript content are never analysis inputs.
82
+ `read-analysis` takes `{ importId }`, with the same lowercase UUID v4 syntax as redaction and the import ID as its protected target. It reads only `redaction.json`, `redacted.jsonl` and `structure.json` from the resolved runtime import directory. For one batch its completed result contains `{ snapshot }`, whose `importId`, `redaction`, `corpus` and `structure` fields are strings. Keep these strings in private durable state; parsing and serializing corpus numbers can lose their exact tokens. For multiple batches it returns the prepared batch snapshot, encoded context and captured-digest binding. Original corpus, coverage, revision and transcript content are never analysis inputs.
83
83
 
84
- Each evidence file is bounded before retention. The redacted corpus, serialized snapshot, complete escaped model document (`{ prompt: analysisModelInput(snapshot) }`) and final serialized save payload must each fit 65,536 UTF-8 bytes. The model-input formatter includes instructions and the full sidecar. Overflow returns `analysis-too-large`; transport limits are unchanged. Missing redaction manifest or corpus returns `redaction-required`, malformed nonempty import IDs return `invalid-import-id`, and invalid or unsafe evidence returns `analysis-input-refused`. Manifest counts and identity fields must match the corpus. Sidecar validation retains original copy/conflict classes, using class markers rather than redacted content to check structure consistency.
84
+ Each evidence file is bounded before retention. Capture streams up to 52,428,800 UTF-8 bytes of redacted corpus. Each metadata file, serialized batch document and save payload is bounded at 65,536 bytes. The complete model launch includes the fixed instruction, encoded batch evidence, projected structure and earlier accepted result. Overflow returns `analysis-too-large`; transport limits are unchanged. Missing redaction manifest or corpus returns `redaction-required`, malformed nonempty import IDs return `invalid-import-id`, and invalid or unsafe evidence returns `analysis-input-refused`. Manifest counts and identity fields must match the corpus. Sidecar validation retains original copy/conflict classes, using class markers rather than redacted content to check structure consistency.
85
85
 
86
- `save-analysis` takes `{ importId, cycleId, snapshot, reply }`. The reply is JSON text and validation uses the captured snapshot even if the files later change. Invalid JSON returns `analysis-invalid-json`; candidate refusal retains the validator's unique codes in declaration order. Accepted output writes and closes private `proposal-CYCLE_ID.txt` before creating `analysis-CYCLE_ID.json` as the completion marker. The JSON is the complete validator result, including every citation, counterevidence item and limitation. The deterministic plain-text proposal is at most 4,000 characters. Matching duplicate saves retain bytes and receipt identity; a matching proposal without a marker may finish. Conflicting or incomplete existing outputs remain unchanged and return `analysis-output-failed`. A proposal alone is not completed analysis. New files have mode `0600`; destinations and linked files use the import protections.
86
+ `save-analysis` takes `{ importId, cycleId, reply }`, with the captured-digest binding in `batch` for multiple batches and `followUp` for a question continuation. It resolves evidence from the run's private capture instead of resending it with the reply, keeping saves within the payload bound. Checkpoint saves verify any supplied legacy `snapshot` against the captured batch. The reply is JSON text and validation uses the captured snapshot even if the files later change. Invalid JSON returns `analysis-invalid-json`; candidate refusal retains the validator's unique codes in declaration order. Accepted output writes and closes private `proposal-CYCLE_ID.txt` before creating `analysis-CYCLE_ID.json` as the completion marker. The JSON is the complete validator result, including every citation, counterevidence item and limitation. The deterministic plain-text proposal is at most 4,000 characters. Matching duplicate saves retain bytes and receipt identity; a matching proposal without a marker may finish. Conflicting or incomplete existing outputs remain unchanged and return `analysis-output-failed`. A proposal alone is not completed analysis. New files have mode `0600`; destinations and linked files use the import protections.
87
87
 
88
- The pure batch preparer validates a captured snapshot, selects the longest consecutive whole-record prefix within 65,536-byte encoded launch and adapter documents, and refuses a fifth batch. It preserves record bytes, global occurrence indexes and captured copy/conflict classes, includes the earlier result as data, and measures the fixed instruction and prompt encoding shared with the restricted launcher. Raw metadata remains bounded at 65,536 bytes and the input corpus at 52,428,800 bytes. Workflow integration, streaming capture, cumulative merge, immutable coverage checkpoints, batch save bounds and restart across batches remain pending; the running workflow retains its single-snapshot limits above.
88
+ The pure batch preparer validates a captured snapshot, selects the longest consecutive whole-record prefix within 65,536-byte encoded launch and adapter documents, and refuses a fifth batch. It preserves record bytes, global occurrence indexes and captured copy/conflict classes, includes the earlier result as data, and measures the fixed instruction and prompt encoding shared with the restricted launcher. Raw metadata remains bounded at 65,536 bytes and the input corpus at 52,428,800 bytes. The workflow runs one restricted turn per batch and commits its checkpoint before preparing the next. Budget, batch, size, validation and worker stops leave the latest partial checkpoint available.
89
89
 
90
- Analysis reuse after an evidence revision is unavailable. `earlierAnalysisId` is not a supported analysis input, and `analysis:IMPORT_ID:CYCLE_ID` identifies a saved result without establishing checkpoint coverage. Import revisions classify source changes but do not map analysis citations or transfer analyzed record ranges. Reuse requires an implemented and verified batch pipeline with result merging, committed complete or partial coverage checkpoints, replay binding and durable question/answer follow-up. The pure batch preparer and saved validator results do not satisfy that prerequisite.
90
+ The internal pure `mergeAnalysisBatch({ previousResult, candidate, evidence, nextRecordIndex })` in `src/chats/analysis-merge.ts` merges one batch candidate into an earlier result, or starts with `previousResult: null`. Evidence contains the complete captured redacted records and their original structure; `nextRecordIndex` is the exclusive processed-prefix bound. References keep global indexes and source IDs. Unknown and future references are refused. Captured copy classes remain intact, and returned conflict groups retain only processed occurrences. Process ID, name and scope must match. New IDs append in first-seen order per collection; an existing ID must keep its collection and every non-reference field. Support and counterevidence references are deduplicated separately in record order. Disagreement returns only `analysis-merge-conflict`; neither input is changed. Callers remain responsible for retaining both variants privately.
91
91
 
92
- A candidate with `openQuestion` currently returns `analysis-input-refused` from `save-analysis`, reconciliation and stop without creating output. The pure question validator is implemented; private drafts, durable analysis questions, expiry and answer follow-up are pending. The workflow still uses one turn and three effect units.
92
+ The merge revalidates the cumulative process, including repetition, global ID uniqueness, links, non-gates and question citations. It accepts references and links to earlier processed evidence and items without requiring the new batch to stand alone. A valid `openQuestion` remains unresolved data in the returned result; a prior result with an unresolved question is refused as `analysis-input-refused`. The pure merge saves no checkpoint, establishes no coverage or completion, and grants no action authority.
93
+
94
+ Capture atomically publishes a private version 1 `checkpoint-0.json` and `proposal-0.txt` alongside its evidence. The initial checkpoint is partial, with a null result, zero covered records and the entire captured total uncovered. Each committed batch saves its own immutable `analysis-checkpoint-N.json` and `proposal-checkpoint-N.txt` inside that capture. Checkpoints bind the run, import, captured digest and zero-based batch index, and retain the cumulative accepted result, covered and uncovered counts, completed batch count and next record index. Proposals put status and counts before shortened inference text. Full coverage with an accepted result and no unresolved question is complete; other checkpoints remain partial.
95
+
96
+ The final batch save writes the complete checkpoint and final output without another effect. The one-batch path retains its three effect charges. Matching retries retain checkpoint bytes and receipts; conflicting batch writes fail with `analysis-output-failed`. Storage uses the pure merge and privately retains both variants of an `analysis-merge-conflict`, leaving the earlier checkpoint accepted and partial. A private conflict envelope binds digests and references to that accepted checkpoint and a separately retained incoming candidate, so each variant keeps its own file bound. Checkpoint files use the existing private file protections. These records grant no execution or publication authority. Completed turns and saves are reused after restart without repeated charges or usage. Interrupted or unknown turns start no replacement. One question may pause any batch before its checkpoint commits. Its answer permits one follow-up on the same captured batch and earlier accepted result; processing then continues with the remaining batches. A second question leaves the earlier accepted checkpoint partial and blocks the run. The CLI five-dollar cap applies to each turn, not the run.
97
+
98
+ Analysis reuse after an evidence revision is unavailable. `earlierAnalysisId` is not a supported analysis input, and `analysis:IMPORT_ID:CYCLE_ID` identifies a saved result without establishing checkpoint coverage. The batch pipeline and its checkpoints do not establish reuse across an evidence revision. Protected reuse capture, conclusion invalidation, coverage transfer and workflow integration remain unimplemented.
99
+
100
+ The internal pure `mapEvidenceReferences` helper in `src/chats/reference-mapping.ts` maps occurrences from two supplied coverage manifests and corpora plus revision entries. It validates each manifest's record counts against its corpus before assigning selection ranges, resolves root indexes separately and pairs repeated path/root selections in manifest order. Matches use source digests and canonical byte offsets within each pair, never UUIDs or redacted text. The returned pairs rewrite both `recordIndex` and `sourceId` in earlier record order, without modifying inputs. Invalid or inconsistent inputs return `analysis-reference-map-refused`.
101
+
102
+ Only unchanged selections and provably preserved records of extended selections map. An extension must retain the earlier occurrence offsets below the old byte count. A record maps only when a later current occurrence starts at or before that count, proving the record ended within the verified prefix. An unterminated final record, or a final record whose boundary cannot be proved from captured occurrences, stays unmapped. Refused and subtree entries contribute no records; changed, truncated, missing and new selections transfer none. The helper checks recorded revision metadata without rereading source bytes. It establishes neither checkpoint coverage nor authority and is not connected to `analyze-chats`.
103
+
104
+ A valid candidate with `openQuestion` writes only private `draft-CYCLE_ID.json`. This version 1 record binds the worker intent's run ID, cycle ID, operation ID and input digest, the captured snapshot's SHA-256 digest, the exact reply and its SHA-256 candidate digest. Batched drafts also bind the captured digest, batch index and exclusive next record index; their questions are validated against the captured processed prefix. Saving a draft does not commit that batch or advance coverage. Its `expiresAt` is fixed at 24 hours after the first draft save. The completed private result contains `{ kind: "analysis_draft", cycleId, candidateDigest, expiresAt, question }` for the durable question. Matching delivery, reconciliation and stop preserve the record's bytes, receipt and deadline, including after restart and deadline passage. Absent reconciliation and stop create nothing. Conflicting or incomplete drafts return `analysis-output-failed`. A draft cannot replace accepted output. A final save alongside a retained draft requires the same run, cycle, captured snapshot and draft candidate, plus an exact listed answer.
105
+
106
+ The first draft or final write creates a shared private `claim-CYCLE_ID.json` with the output kind and a digest of its bound input. A follow-up final save verifies that draft claim and creates a separate `final-claim-CYCLE_ID.json` bound to the draft and validated output. Exclusive creation admits only one output for that cycle, including concurrent conflicting saves. An incomplete or conflicting claim fails closed. Matching retries reuse the claim; older matching final outputs remain readable without one. This storage claim carries no execution authority.
107
+
108
+ The gate helper accepts optional `expiresAt` and forwards that exact deadline to the durable decision service. Replayed gate openings retain the existing deadline. The service preserves deadlines across restart, expires unanswered questions and refuses late answers without reopening settled gates. Opening a gate uses no protected-effect unit. Existing callers that omit the field retain their current behavior.
109
+
110
+ A saved private draft opens one durable question. Its private prompt contains the candidate digest and listed choices. The deadline remains 24 hours after the first draft save, including across restart. Use `cloving questions` to read the prompt. Answer with exactly one listed choice ID; case changes, surrounding whitespace and extra text are invalid. Operational watch views and automatic notifications use fixed text.
111
+
112
+ An exact choice runs one restricted follow-up turn with the same captured batch, earlier accepted result, original draft candidate and answer as encoded data. The reply passes the same cumulative merge and checkpoint rules before the next batch starts. The one-batch path retains round 2 follow-up scopes and five effect units. Batched follow-ups use round 5 scopes, separate from batch rounds 1–4. A batched run uses one capture plus two effect units for each accepted batch, with two more for a question draft save and its follow-up turn, within the existing limit of eleven. The question and its answer use no effect unit. There is no additional follow-up or automatic repair. The complete encoded follow-up must still fit the existing byte bounds; a size refusal keeps the accepted coverage partial.
113
+
114
+ The committed answer survives a host restart before continuation delivery. Recovery delivers one continuation, reuses the original read, turn and draft save, and preserves their scopes, payloads and charges. Changed evidence files do not replace the captured snapshot. A repeated answer command returns its original receipt without another continuation. The compiled Local World restart tests verify the one-batch path and a three-batch question path with four turns, nine charged units and each batch committed once, using synthetic data and fake workers. A restart between draft persistence and gate opening also keeps the original deadline.
115
+
116
+ Expiry blocks with `analysis-answer-missing`; an answer outside the exact listed IDs blocks with `analysis-answer-invalid`. Another question blocks with `analysis-question-limit`. Follow-up validation refusal blocks with `analysis-follow-up-refused`, and validator details stay private. Exhausted effect units block with `budget-exhausted`. Expiry, an invalid answer, follow-up refusal or a second question leaves the earlier accepted checkpoint and proposal partial, without committing the questioned batch. Draft persistence does not resolve a question or grant action authority.
93
117
 
94
118
  Success returns `{ kind: "handoff_requested", cycleId, promotionId }`, where `promotionId` is an opaque analysis reference. It grants no execution or publication authority. The file adapter performs no git work, network request or model call. Redaction can leave private values, and validator acceptance checks shape and cited occurrences rather than factual accuracy. History completeness remains unknown and independent observations remain unestablished.
95
119
 
@@ -103,9 +127,9 @@ To configure subscription login:
103
127
 
104
128
  The fetched token goes only to the analysis process as `CLAUDE_CODE_OAUTH_TOKEN`. Cloving does not put it in its environment, development workers, logs or stored results, and does not fetch it for CLI probes or completed-turn replay. Analysis excludes `ANTHROPIC_API_KEY`, including a key present in the daemon environment. Cloving does not read the macOS keychain.
105
129
 
106
- The fixed launch removes built-in tools with `--tools ""` and denies MCP tools separately, with an empty strict MCP configuration. Safe and restricted modes disable discovery; skills, hooks, project instructions, plugins, session persistence and Chrome integration are disabled. The command runs once with a five-dollar budget in an empty private directory and uses a separate fixed system instruction and encoded evidence input. Only this turn contacts the model. See the [Claude CLI controls](https://code.claude.com/docs/en/cli-reference) and [subscription authentication](https://code.claude.com/docs/en/authentication).
130
+ The fixed launch removes built-in tools with `--tools ""` and denies MCP tools separately, with an empty strict MCP configuration. Safe and restricted modes disable discovery; skills, hooks, project instructions, plugins, session persistence and Chrome integration are disabled. Each turn runs with a five-dollar cap in an empty private directory and uses a separate fixed system instruction and encoded evidence input. Only these restricted turns contact the model. See the [Claude CLI controls](https://code.claude.com/docs/en/cli-reference) and [subscription authentication](https://code.claude.com/docs/en/authentication).
107
131
 
108
- Replies of at most 16,000 UTF-8 bytes are retained completely for validation. Larger replies return `analysis-reply-too-large`; unsuccessful turns return `analysis-turn-failed`. Both retain available usage. A completed private worker result is written before its report, so durable replay can reuse it. An interrupted or unknown completion never starts a replacement turn. Analysis creates no raw stdout/stderr turn logs or generic text summary. Worker records and accepted outputs remain private; operational views expose codes, counts, usage and opaque identities. Temporary CLI data is removed when the turn completes. Acceptance grants no execution, publication or workflow-generation authority.
132
+ Each CLI turn has its own five-dollar cap; effect units do not define a dollar budget for the run. Each complete escaped document, including any draft and answer, is limited to 65,536 bytes. Replies of at most 16,000 UTF-8 bytes are retained completely for validation. Larger replies return `analysis-reply-too-large`; unsuccessful turns return `analysis-turn-failed`. Both retain available usage. A completed private worker result is written before its report, so durable replay can reuse it. An interrupted or unknown completion never starts a replacement turn. Analysis creates no raw stdout/stderr turn logs or generic text summary. Worker records and accepted outputs remain private; operational views expose codes, counts, usage and opaque identities. Temporary CLI data is removed when the turn completes. Acceptance grants no execution, publication or workflow-generation authority.
109
133
 
110
134
  ### Redact an imported corpus
111
135
 
@@ -133,6 +157,20 @@ Version 1 also accepts an optional `openQuestion` object containing only `claimI
133
157
 
134
158
  Acceptance returns the candidate plus limitations preserving conflict groups, unknown history and unestablished independence. Refusal returns only fixed, unique codes in declaration order. Candidate fields are closed; authority and executable fields are refused, and descriptions remain inert. Validation does not certify redaction, evidence authenticity, inference quality, publication safety or permission for any action. Evidence content and exact numeric tokens remain unchanged. Full product admission remains pending CLV-002 through CLV-004.
135
159
 
160
+ The internal pure `inspectWorkflowGenerationText(analysis)` check in `src/chats/workflow-generation-text.ts` inspects the identifiers and prose of an `AnalysisResult`, including branch and loop links, condition descriptions and optional question choices. Each inspected field must contain 1–240 printable ASCII characters. It returns unique codes in this fixed order: `text-length`, `text-characters`, `machine-path`, `parent-traversal`, `email-form`, `user-mention`, `access-token-form`, `credential-form`. Known disclosure forms include absolute and home-relative paths, Windows paths and home placeholders, literal and percent-encoded parent traversal, addresses and mentions, common token prefixes, authorization values, credential assignments, private-key headers and URL user information. Pattern checks run only on fields within the length bound; text is never truncated, decoded or sanitized.
161
+
162
+ The text check takes no corpus input and never reads source references, counterevidence or limitations. It makes no file, process, network or model call and returns no inspected text or artifact. Empty codes establish only that these fixed checks found no violation; arbitrary prose can still contain private information. Callers must validate the analysis separately and retain provenance privately. This check grants no admission, execution or publication authority.
163
+
164
+ The internal pure `generateWorkflow(analysis, availability)` entry point in `src/chats/workflow-generation.ts` accepts one structurally validated `AnalysisResult` and a serializable snapshot `{ exports, methods }`. `exports` maps public module names to available named exports; `methods` maps capability names to available methods. No snapshot provider or installation command is supplied. The result is `generated` with one TypeScript source, candidate declaration and versioned JSON prompt assets plus a separate private report; `gap` with a private report and no artifact; or `refused` with fixed text-check codes only. Generation performs no I/O or model call. Availability, analysis and generation confer no authority; source admission and run authorization remain separate requirements.
165
+
166
+ The fixed `review-repair/v1` projection accepts exactly two executable stages in array order: an explicit-human-instruction or observed-repetition work stage, then a routine-repair stage with one of those claim kinds. One branch must link review to repair with the exact condition `Defect found.`. One explicit-human-instruction loop must list those stages in that order, use the exact exit condition `Checks and review pass.`, and reference an existing exhaustion stop. These phrases select this fixed protocol; arbitrary condition prose is never evaluated. The analysis iteration count is preserved, with two possible one-unit `claude` / `run-turn` effects per iteration and a declaration bound of 100 effects. Other work claims remain annotations; any extra executable stage, ambiguous control flow or unresolved analysis question returns a gap. Historical exceptions, rejected approaches, assistant claims, uncertainty, interruptions and tool confirmations cannot select executable work.
167
+
168
+ The projection permits at most one design question or configured action approval associated with the review stage, opened after a successful review. Gates on other stages return a gap. Factual decisions become required string inputs after the analysis inputs. Fields, functions, assets, stages and gates use reserved ordinal names. Submission fields resolve through the existing `{ cycleId, repository, input }` envelope without historical defaults. Worker completion requires an outer JSON result envelope whose `summary` is itself a JSON object with status `complete`, `repair` or `blocked`; malformed or unknown statuses block. Routine repair consumes the declared loop; exhaustion blocks. A gate returns `waiting_for_decision`. A host-authorized fresh SDK segment supplies the optional typed `{ gateId, decision, answer }` continuation. The generated code validates it before requesting effects and reconstructs the same bounded visits; existing durable operation receipts and run spending prevent accepted effects from repeating. After reconstructing the successful review, a design answer enters the remaining iterations as the `decision` payload slot. The worker must apply and check that answer before reporting completion, and subsequent repair receives it too. With no iterations remaining, the continuation blocks. An answer supplies no publication permission.
169
+
170
+ Generated declarations limit serialized submission fields to 16,384 UTF-8 bytes. Before requesting any effects, the workflow checks both stage payloads, including assets and the resolved workspace, against a 32,758-byte budget. This reserves 32,768 bytes for the JSON-encoded completed review envelope and 10 bytes for its property separator within the worker's 65,536-byte payload limit. The final summary JSON has a separate 16,000-byte limit, fitting within the worker's 16,000-character retention limit; oversized summaries block as `worker-blocked`. Repair receives the retained completed review without further truncation. An oversized review envelope blocks with `review-too-large` before a repair request; oversized run data blocks with `invalid-run-input` before spending. Both final payloads, including any design answer, are checked against 65,536 bytes before delivery. These limits include UTF-8 encoding and JSON escaping.
171
+
172
+ The report retains the process and stage summaries, ordinal name map, excluded annotations, non-gates, claim kinds, source references, counterevidence, conflicts and uncertainty limitations. **Retain it privately and exclude it from public source and assets.** The generator does not save it and never reads corpus records. Only checked descriptions enter assets, embedded identically as escaped JSON literals in the source. Synthetic tests exercise source checking, real SDK compilation, compiled-artifact admission, declaration loading, worker status handling, gates and continuation across process termination. Product admission remains subject to the separate accepted verification policy.
173
+
136
174
  ## Install
137
175
 
138
176
  Cloving supports macOS and Linux on arm64 and x64, with the Node and npm ranges in `package.json`. Workflow admission still requires exactly Node 26.9.0. CI runs the developer gate and packed-install checks on macOS 15 arm64 and Ubuntu 24.04 x64 with Node 26.9.0 and npm 11.19.1. Chat import and redaction currently require macOS; other platforms return `platform-unsupported` before file access. Windows is unsupported.
@@ -280,7 +318,11 @@ The form sends the same run request as the CLI and retains its random command ID
280
318
 
281
319
  A command setting is a JSON list of texts, for example `CLOVING_CHECK_COMMAND='["npm", "test"]'`.
282
320
 
283
- The notify command receives no added argument. Its standard input receives one JSON object with `event`, `runId`, `workflowId`, `subject` and `body`. The body contains the decision or outcome text already shown by `cloving questions` or `cloving status`, with complete response commands, up to 4000 characters. The daemon checks every 15 seconds and records each event before calling the command. The first check with no notification record only records existing events. Records survive restarts; a failed command is logged once and never retried. Commands have 30 seconds to finish. A stop after recording an event but before sending it can lose that notification, and decisions opened and closed between checks can be missed.
321
+ The notify command receives no added argument. Its standard input receives one JSON object with `event`, `runId`, `workflowId`, `subject` and `body`. The body contains the decision or outcome text already shown by `cloving questions` or `cloving status`, with complete response commands, up to 4000 characters. The daemon checks every 15 seconds. The first check with no notification record only records existing events.
322
+
323
+ The private `notify-events.json` journal records a notification as `pending` before calling the command and as `sent` after exit code 0. A failed command retries the same message after 1, 5, 15 and 60 minutes, with five attempts in total and a 30-second limit per attempt. The journal records attempt times and fixed failure reasons without command arguments or output. Pending and retryable failed entries resume after restart. Exhausted delivery logs one line naming its key. Old key-only records migrate as sent without sending them again.
324
+
325
+ Journal updates use a temporary file and rename. Sent and exhausted failed delivery details expire after seven days; their keys remain to prevent later duplicate delivery. Unfinished deliveries remain until resolved. A crash after command success but before recording that success can repeat delivery. Decisions opened and closed between checks can be missed.
284
326
 
285
327
  ## Daily development
286
328
 
@@ -289,7 +331,7 @@ The notify command receives no added argument. Its standard input receives one J
289
331
  - `develop-prompt` takes the text of a task. Use it for a small task with no ticket, or for a first try in a new repository.
290
332
  - `develop-ticket` takes a ticket ID and reads the ticket itself. Use it for the normal work on a ticket, when you want to read each diff and merge the branch yourself.
291
333
  - `develop-issue` takes a ticket ID too, and sends the work through a GitHub pull request. Use it for a small ticket with clear criteria, in a GitHub repository that Greptile reviews and that has a check command. It is the workflow of the continuous process.
292
- - `develop-prd` takes an idea, researches the code and web, reviews a draft PRD, and posts it as a GitHub issue. Set `CLOVING_PRIVATE_TEXTS` to a nonempty JSON list before starting the daemon. A refused post preserves the worktree and draft. A successful post removes the worktree and adds no label; read the issue and add `cloving: ready` when it is ready for implementation.
334
+ - `develop-prd` takes an idea, researches the code and web, reviews a draft PRD, and posts it as a GitHub issue. It then hands the issue number to `develop-issue` to build automatically. Set `CLOVING_PRIVATE_TEXTS` to a nonempty JSON list before starting the daemon. A refused post preserves the worktree and draft. If the handoff is refused, it adds `cloving: ready` so the issue queue can build it later. The PRD run retains `issue-N` as its promotion, shows the refusal code in its outcome reason, and removes its worktree after posting. If the fallback label fails, status also shows `issueUpdate: failed`; inspect the GitHub operation and queue the issue after resolving the failure.
293
335
 
294
336
  ```sh
295
337
  cloving start # terminal 1, in the repository
@@ -308,6 +350,8 @@ The rule: read the diff before you approve.
308
350
 
309
351
  Claude turns have web research tools by default, an empty GitHub CLI configuration folder, and no GitHub token environment variables. This is not a sandbox: a turn can still find other credentials. The PRD refusal rules catch the listed private text and common sensitive forms; unlisted private names can pass. A `post-uncertain` result requires checking GitHub before trying another run.
310
352
 
353
+ `cloving status RUN_ID --json` includes `run.input`, and `cloving status --json` includes `input` on each listed run. It is the normalized submission admitted with the run, such as `{"ticket":"297"}` for `develop-issue` or the submitted fields of a declared workflow. It survives service restarts and excludes resolver-added ticket text and repository paths. Older runs without a stored submission show `null`. The text status of one run shows `Input:` as compact JSON, limited to the first 200 characters with `…` appended when longer. Terminal control and hidden format characters are escaped.
354
+
311
355
  ### The ticket command
312
356
 
313
357
  `CLOVING_TICKET_COMMAND` (a JSON list of texts) names the ticket command. The contract of a ticket command:
@@ -337,11 +381,21 @@ CLOVING_TICKET_COMMAND='["github-ticket"]' cloving start
337
381
 
338
382
  `cloving run develop-issue --next` and `cloving run develop-ticket --next` use the reserved ticket ID `next`, just like `--ticket next`. Set `CLOVING_NEXT_COMMAND` to a JSON list naming your selection command and its arguments. The daemon adds no argument. The command chooses a ready ticket in your tracker and prints its ID; the daemon trims it and reads the ticket with `CLOVING_TICKET_COMMAND`. Both commands share the resolver's 30-second deadline. Selection logic stays in your command, and each invocation submits only one run.
339
383
 
384
+ Set `CLOVING_QUEUE_SECONDS` to a whole number from 10 to 3600 to poll for ready issues. It requires both ticket commands. `CLOVING_QUEUE_LANES` sets the number of simultaneous `develop-issue` runs, from 1 to 4, and requires `CLOVING_QUEUE_SECONDS`; its default is 1. For example, `CLOVING_QUEUE_LANES=4` admits at most one new ticket each cycle until four lanes are busy. Each run has its own branch and work tree. Manual issue submissions share this limit and receive `workflow-active` when all lanes are busy. A ticket already being developed receives `ticket-active`.
385
+
386
+ Before enabling more than one lane, update the next-ticket command to honor `CLOVING_SKIP_TICKETS`. Cloving sets this environment variable to space-separated IDs of active tickets and tickets waiting for dependencies. The command must never print an ID from that list. It should print nothing when no eligible ticket remains. The service also checks selected tickets before admission.
387
+
388
+ In the ticket text returned by `CLOVING_TICKET_COMMAND`, each `#N` in a sentence starting with **Needs** inside `## Dependencies` is a hard dependency. For example, `Needs #123 and #124.` waits until both GitHub issues close. Other references and sections do not create dependencies. Cloving reads dependency state with `CLOVING_GH_COMMAND` (default `gh`); an unavailable or invalid response prevents admission. An open dependency returns `ticket-dependency-open` and puts the ticket in the skip list. Waiting tickets are checked again each cycle with a free lane, so a closed dependency makes its ticket eligible again.
389
+
390
+ `cloving status` and watch display busy lanes and skipped tickets with their reasons. A pending self-update holds new admissions while active lanes drain. Three unsuccessful runs in a row, counted in the order they finish, stop the queue; a successful handoff clears the streak. Ordinary restarts preserve it. After inspecting and reconciling the failures, start with `--reset-queue` to clear the streak. A conflict caused by an earlier lane's merge returns its diagnostics to a fix round. Lanes do not add CI runners or parallelize turns within one run.
391
+
340
392
  An empty selection gives `no-ready-ticket`; a failed command gives `next-ticket-not-available`. Missing configuration gives `next-source-not-configured`. Multiple IDs, an invalid ID, or `next` as the selected ID give `invalid-ticket-id`. Use only one of `--next`, `--ticket`, `--prompt` and `--input`.
341
393
 
342
394
  ### Review rounds of `develop-ticket` and `develop-prompt`
343
395
 
344
- Worker turns retry an exact Codex capacity refusal or a Claude overload after 60 seconds, then 180 seconds, for at most three attempts. Each retry keeps the work tree, profile, model, budget and limits, and asks the worker to continue from the current work. The step keeps one operation identity and sums usage across attempts. Private turn journals retain each attempt. Stopping during a wait returns `stopped`; a daemon restart fails the recorded operation for existing recovery. The same retry rule applies to the restricted analysis turn in `analyze-chats`. Other failures are not retried.
396
+ Worker turns retry an exact Codex capacity refusal or a Claude overload after 60 seconds, then 180 seconds, for at most three attempts. Each retry keeps the work tree, profile, budget and limits, and asks the worker to continue from the current work. The step keeps one operation identity and sums usage across attempts. Private turn journals and turn usage retain each attempt's model, token counts and cost estimate. Stopping during a wait returns `stopped`; a daemon restart fails the recorded operation for existing recovery. The same retry waits apply to the restricted analysis turn in `analyze-chats`. Other failures are not retried.
397
+
398
+ `CLOVING_FALLBACK_MODELS` accepts a JSON array of at most three nonempty model names, for example `'["gpt-6-astra"]'`. Without the setting or with `[]`, every attempt keeps the main model. The first attempt and first retry use the main model; each later attempt uses the next configured fallback within the existing attempt limit. With three attempts, only the first fallback can be used. The worker command must explicitly name a model with `-m NAME`, `--model NAME` or `--model=NAME`; otherwise it stays unchanged and the private journal records `fallback-model-unavailable`. Fallbacks apply only after capacity refusals and never change the fixed analysis model of `analyze-chats`. A fallback model can have a higher price. Each attempt's estimate uses its own model's price; an unknown price or missing token count leaves the total estimate unknown. Malformed settings refuse daemon start with `invalid-fallback-models`.
345
399
 
346
400
  A run of `develop-ticket` or `develop-prompt` has one to three review rounds. Each round does one Claude Code turn in the work tree of the run, on the branch `cloving/<ticket id>-…`, and then opens one approval. The first round makes the work tree. The approval text has the round, the ticket ID, the branch, the commits, the changed files and the report of the worker. Read the diff before you decide. The decision has these results:
347
401
 
@@ -355,10 +409,10 @@ Single-run status (`cloving status RUN_ID`, also with `--json`) and watch show e
355
409
 
356
410
  The built-in table uses standard short-context prices read on **2026-10-18** from the [OpenAI pricing page](https://openai.com/api/pricing/), in USD per million tokens:
357
411
 
358
- | Model | Input | Cached input | Output |
359
- | --- | ---: | ---: | ---: |
360
- | `gpt-6.1-sol` | 2.00 | 0.10 | 10.00 |
361
- | `gpt-6-astra` | 10.00 | 1.00 | 50.00 |
412
+ | Model | Input | Cached input | Output |
413
+ | ------------- | ----: | -----------: | -----: |
414
+ | `gpt-6.1-sol` | 2.00 | 0.10 | 10.00 |
415
+ | `gpt-6-astra` | 10.00 | 1.00 | 50.00 |
362
416
 
363
417
  `CLOVING_TOKEN_PRICES` accepts a JSON object mapping model names to non-negative finite `input`, `cachedInput` and `output` prices per million tokens. Its entries override matching built-in entries and retain the others. Estimates use the reported model or the worker command's model argument, with `estimatedCostUsd` totals only when every ended turn has an estimate. There is no live price lookup; estimates do not change budgets or limits.
364
418
 
@@ -424,9 +478,15 @@ Merged runs retain `handoff_requested` with `ticketStatus: complete` or `partial
424
478
 
425
479
  To resume a queue stopped at this limit, stop the service with Control-C, inspect the failures and reconcile the affected issues, then run `cloving start --reset-queue` with the same repository, runtime and queue settings. This clears the failure streak once and preserves tracked commands. Ordinary restarts, including automatic self-updates, preserve the count. Resetting the queue does not change issue labels or retry blocked issues.
426
480
 
427
- At the confidence score 5/5, the worker merges the pull request with a merge commit, with no human approval. Then it removes the remote branch, the work tree and the local branch. With a lower score, the Claude worker gets the summary and the findings of the review for one more round. After three such rounds, or after 60 minutes with no review, the run stops and the pull request stays open.
481
+ At the confidence score 5/5, the worker runs the local merge check and waits for CI of the exact head it will merge, including an updated head pushed after merging the default branch. When CI passes, it merges the pull request with a merge commit, with no human approval. Then it removes the remote branch, the work tree and the local branch. With a lower score, the Claude worker gets the summary and the findings of the review for one more round. After three such rounds, or after 60 minutes with no review, the run stops and the pull request stays open.
482
+
483
+ Set `CLOVING_REQUIRED_CHECKS` to a JSON list of check run names, such as `["quality", "quality_linux"]`, to require those checks. Without the setting, all GitHub Actions checks on the head commit are required. The newest run of each name decides; `success`, `neutral` and `skipped` pass. With no setting and no Actions checks after a 60-second grace period, a repository without CI can merge. A configured missing check keeps waiting. CI is polled every 30 seconds with a separate 90-minute limit. A timeout returns `ci-pending` and blocks without a fix round.
484
+
485
+ A failed check returns `ci-failed` with failed check names, failed steps and failed log tails, with private texts hidden and at most 6,000 characters. It starts a worker fix round that must repair CI, including failures the pull request did not cause, and commit the fix. The new commit receives a new Greptile review and CI gate. Review, local check, conflict and CI repairs share the existing limit of three fix rounds. Cloving does not retry failed CI jobs.
428
486
 
429
- The watch board keeps blocked `develop-issue` runs in `Stopped`. A qualifying later local run shows `Done in a later run`. Otherwise, the board reads the recorded pull request with `CLOVING_GH_COMMAND` (default `gh`). The service supplies its repository, and the board checks the local origin and the recorded PR identity. A confirmed merge shows `PR merged #N`; a read failure shows `PR status unavailable`. Other PR states keep `Needs attention`. These marks do not change the run outcome.
487
+ The watch board keeps blocked `develop-issue` runs in `Stopped`. A validated local merge report shows `PR merged · #N`. A later completed run for the same established GitHub issue must have its own validated merge report to show `Ticket completed by later run`. The original and later run have separate links. Either local proof prevents a GitHub read. These marks preserve the recorded run outcome.
488
+
489
+ Otherwise, the board reads the recorded pull request with `CLOVING_GH_COMMAND` (default `gh`). It validates the PR and issue identities against the configured repository's local origin. The first queued or active read shows `Checking PR`. A confirmed merge shows `PR merged · #N`; a failed read shows `PR status unavailable`. An unmerged PR shows `Needs attention`. A separate `Stale` mark appears when the last successful unmerged observation is older than 120 seconds, including after a failed refresh. A successful refresh resets its age. Confirmed merges never become stale.
430
490
 
431
491
  Reads run in the background, one at a time, with a five-second limit. Board loads can refresh unresolved PRs at least 60 seconds after the previous attempt started. Confirmed merges remain cached until the watch process stops. A later normal page load shows each result.
432
492
 
@@ -560,10 +620,12 @@ A workflow is a TypeScript file in the form of `workflows/develop-ticket.ts`:
560
620
 
561
621
  - An exported async function with the directive `"use workflow"` as its first statement. The directive needs the compiler of the Workflow SDK, not only TypeScript.
562
622
  - The first argument is the input of the run. A resolver of the daemon makes it, for example `cycleId`, `ticketId`, `ticket` and `repository`. After a decision, the host calls the function again with the decision (`gateId`, `decision` and `answer`) as the second argument. The function must examine the decision before it asks for an effect, as `decided()` in `workflows/develop-ticket.ts` does. If it does not, it does the work of round 1 again.
563
- - The step helpers come from the subpaths of `cloving/workflows`: `protectedEffect` from `cloving/workflows/steps/protected-effect`, `decisionGate` from `cloving/workflows/steps/decision-gate` and `loadCycle` from `cloving/workflows/steps/load-cycle`. The type `CycleOutcome` comes from `cloving/workflows`. An import of `cloving/workflows` starts no service.
623
+ - The step helpers come from the subpaths of `cloving/workflows`: `protectedEffect` from `cloving/workflows/steps/protected-effect`, `decisionGate` from `cloving/workflows/steps/decision-gate` and `loadCycle` from `cloving/workflows/steps/load-cycle` and `handoff` from `cloving/workflows/steps/handoff`. The type `CycleOutcome` comes from `cloving/workflows`. An import of `cloving/workflows` starts no service.
564
624
  - `protectedEffect` asks the daemon for one effect of a capability, for example a Claude turn. `decisionGate` opens a decision for a person.
565
625
  - The function returns a `CycleOutcome`: `waiting_for_decision`, `handoff_requested` or `blocked`.
566
626
 
627
+ For `handoff_requested`, the daemon retains the workflow's `promotionId` in the completion event. An optional bounded `reason` records a handoff refusal while preserving the promotion. `cloving status <runId>` shows the promotion as `Promotion:` and the reason beside the outcome; JSON status includes `run.outcome.promotionId` and `run.outcome.reason`. Watch retains the promotion in the run model and completed-run details. This identifier is an opaque reference and grants no authority.
628
+
567
629
  ```ts
568
630
  import type { CycleOutcome } from "cloving/workflows";
569
631
  import { decisionGate } from "cloving/workflows/steps/decision-gate";
@@ -643,7 +705,12 @@ To register another workflow, put `<name>.declaration.json` beside `<name>.ts`:
643
705
  "maximumBytes": 65536,
644
706
  "fields": {
645
707
  "prompt": { "type": "string" },
646
- "rounds": { "type": "integer", "minimum": 1, "maximum": 10, "optional": true }
708
+ "rounds": {
709
+ "type": "integer",
710
+ "minimum": 1,
711
+ "maximum": 10,
712
+ "optional": true
713
+ }
647
714
  }
648
715
  }
649
716
  }
@@ -651,8 +718,33 @@ To register another workflow, put `<name>.declaration.json` beside `<name>.ts`:
651
718
 
652
719
  The ID accepts 1–64 letters, digits or hyphens. The effect limit is 1–100; capabilities must contain `claude`, `github`, or both. The input byte limit is 1–1048576, subject to the service's own limit. Fields accept nonempty strings, integers with optional inclusive bounds, or booleans. Fields are required unless `optional` is `true`; unknown fields are rejected. Bounds apply only to integers.
653
720
 
721
+ Optional `handoffs` lists distinct registered workflow IDs. Registration refuses unknown targets. The execution pin retains these permissions with each run: target order does not affect the pin, while adding or removing a target changes it. Omitted and empty lists keep existing pins. Stored permissions survive restart and retained workflow versions. The built-in `develop-prd` declares `develop-issue` as its only handoff target and calls it after creating an issue; the other built-in workflows declare none. A refused PRD handoff adds `cloving: ready` for the queue and records the refusal in the PRD run's outcome.
722
+
723
+ Use `handoff` inside a workflow to submit input to a declared target:
724
+
725
+ ```typescript
726
+ import { handoff } from "cloving/workflows/steps/handoff";
727
+
728
+ const runId = await handoff({
729
+ workflowId: "develop-issue",
730
+ input: { ticket: "CLV-123" },
731
+ });
732
+ ```
733
+
734
+ The step returns the target run ID after admission through the operator submission path. It spends one protected-effect unit. The caller’s pinned `handoffs` list must include the target; otherwise the step fails with `handoff-not-declared`. The target validates and resolves the input through its normal submission contract. Refusal fails with `handoff-input-refused` and admits no target run. If the target returns `workflow-active`, the worker makes at most ten attempts, one second apart, then fails with `handoff-start-timeout`. The worker retains the active-target refusal count across restarts. Replays reuse command ID `handoff:<operation ID>` and return the same run ID; separate step calls have distinct operation IDs. After a lost submission reply, recovery replays that same command ID only while the source run, lease, budget and workflow pin still permit dispatch. Status checks and stop never start a target run.
735
+
736
+ Hand-offs record `parentRunId` and `chainId` (the first run's ID) in the new run's admission. A chain permits at most five runs, including the first; attempting a sixth fails with `chain-limit` and starts no run. This fixed limit follows ancestry, so separate children of the same parent do not consume each other's chain length. The records and limit survive service restarts. `cloving status` shows the parent, chain and child run IDs in text and JSON; watch cards link to parent and child runs across workflows.
737
+
738
+ Optional `stages` contains 1–12 entries in board order. Each entry has a unique `name` (1–64 ASCII letters, digits or hyphens), a unique `label` (1–40 printable characters on one line, without outer spaces), and `operations`, `gateKinds`, or both. At least one selector array must be nonempty. Operations match the `scope.operation` passed to `protectedEffect`, using 1–128 ASCII letters, digits or `._:/-`; gate kinds are `approval` and `question`. Selectors cannot repeat within an array or belong to two stages of the same selector type. Unknown fields and labels `Other`, `Done` and `Stopped` are rejected.
739
+
740
+ For declared stages, the board uses the latest committed `effect.requested` or `gate.opened` sequence, preserving that event's start time. Unmatched events and runs without a relevant event use Other. Decisions and worker output do not advance a card; later requests can move it back. Declared labels are followed by Other, Done and Stopped. Existing terminal retention rules take precedence. Unstaged workflows and `develop-issue` keep their existing columns and placement. Declarations load at service startup; stages provide display metadata and grant no capabilities.
741
+
742
+ The bundled `analyze-chats` stages are Read input (`read-analysis`), Analyze (`turn-analysis`) and Save result (`save-analysis`). The Analyze selector names its operation; the model method remains `run-turn:analyze-chats`.
743
+
654
744
  After startup, `cloving status` lists the declared ID. Submit JSON with `cloving run review-run --input input.json`. The function receives `{ cycleId, repository, input }`, where `cycleId` is `task-` followed by 12 characters derived from the command ID, `repository` is the service repository, and `input` retains the checked JSON values. Invalid input is rejected before a run starts. Invalid declarations or duplicate workflow IDs or function names stop startup.
655
745
 
746
+ Startup retains each complete compiled project under `workflow-bundles` in private daemon state, beside the generated `project` directory. Each content-addressed snapshot includes workflow sources, declarations, registration manifests, all compiler artifacts, and the installed dependency graph and Node identity. Snapshots bind to the canonical repository and survive later source edits or removal. Storage lookup validates every captured file and returns `pinned-workflow-unavailable` for missing or changed bytes; startup refuses reuse of a matching damaged snapshot without repairing it. No retained generation is deleted automatically. Routing pinned runs through these stored generations remains pending.
747
+
656
748
  Candidate policy checking is available internally through `checkWorkflowCandidate` in `src/workflow-candidate.ts`. It takes serializable analysis facts, an export snapshot and a candidate declaration containing `workflow` and `methods`. Each declared capability requires a nonempty list of distinct method names. The existing workflow sidecar format is unchanged. Results are sorted, unique refusal codes; an empty list grants no admission or execution authority.
657
749
 
658
750
  The caller supplies imported symbol names, literal effect pairs (`null` represents a dynamic value), direct-effect and unsupported-form findings, and known call and unit totals. Unknown portions of a total still require runtime budget enforcement. This pure checker does not analyze source or verify these facts. Source-to-facts analysis, SDK candidate compilation and the installed candidate admission adapter remain unimplemented.
@@ -667,7 +759,7 @@ node dist/src/cli.js --help
667
759
  npm pack --ignore-scripts
668
760
  ```
669
761
 
670
- `npm pack` prints the file name of the tarball. Install it into a separate project with `npm install --ignore-scripts --omit=dev /absolute/path/to/TARBALL`, then run `./node_modules/.bin/cloving --version` or `./node_modules/.bin/cloving start`. The package includes the emitted CLI, start program, compiler and bundled workflows; startup uses the installed runtime dependencies. The package has no installation hooks. An import of `cloving/workflows` gives the step helpers `loadCycle`, `protectedEffect` and `decisionGate`, and starts no service.
762
+ `npm pack` prints the file name of the tarball. Install it into a separate project with `npm install --ignore-scripts --omit=dev /absolute/path/to/TARBALL`, then run `./node_modules/.bin/cloving --version` or `./node_modules/.bin/cloving start`. The package includes the emitted CLI, start program, compiler and bundled workflows; startup uses the installed runtime dependencies. The package has no installation hooks. An import of `cloving/workflows` gives the step helpers `loadCycle`, `protectedEffect`, `decisionGate` and `handoff`, and starts no service.
671
763
 
672
764
  `npm run check` and `npm run test:concurrency` currently reject admission because the complete quality policy is not implemented. Setup checks are not product acceptance. State and retained releases will live outside the package installation; installing or updating the package does not activate a daemon or migrate state.
673
765
 
@@ -675,10 +767,18 @@ Run `npm run test:scale` on an otherwise idle machine to measure authority openi
675
767
 
676
768
  `npm run check:quality` checks the npm manifest, lock and installed versions, regenerates TypeScript output in memory, inventories first-party files, and runs strict compilation, the proposed module catalog, workflow/effect boundaries, suppression and test-integrity checks, formatting, typed lint, structural checks, clone detection and the regular local test suite. Production modules require at least 90% line, statement and function coverage and 85% branch coverage per file. Coverage uses native V8 ranges mapped to the syntax tree of the exact Node-stripped source; unimported production files fail. Class and named object types allow at most 24 callable members; interfaces allow 10. Clone checks support ordinary TypeScript and JavaScript; JSX is rejected until separately qualified. `npm run check:lint`, `npm run check:format` and `npm run test:quality` run individual development checks.
677
769
 
770
+ The quality report includes elapsed time and the effective limit in milliseconds for each bounded command: npm inventory, clone detection, tests and coverage conversion. Commands using more than 80 percent of their limit produce a warning in the JSON report and on stderr after the report. Failed checks print the collected timings and warnings with the original error and a failing exit status. Warnings preserve a passing result. If your change made the check slower, address the warning in the same ticket.
771
+
678
772
  The watch scrolling tests launch an isolated headless Chrome process at desktop and phone widths. They require Chrome on the test machine. Run them with `node --test test/watch-scrolling.test.ts`. The fixture serves bundled Preact and board data over loopback and blocks external page resources.
679
773
 
774
+ Before a ticket report, commit your work and run `npm run check:clean`. It refuses uncommitted changes, archives the committed tree of `HEAD` into a temporary directory, copies the worktree's `node_modules`, and runs `node tools/check-quality.ts` there with the same environment and exit code. Ignored build output such as `dist/` is absent, so tests that rely on stale local files fail. The temporary copy is removed after success, failure or SIGINT/SIGTERM interruption.
775
+
680
776
  Set `CLOVING_CHECK_TIME_FACTOR` to a whole number from 1 to 5 (default 1) to multiply the developer gate test and coverage command time limits, the inner hook check limit (5 seconds by default), and the installed hook limit (10 seconds by default). With factor 3, the hook limits are 15 and 30 seconds, respectively.
681
777
 
778
+ Set `CLOVING_TEST_CONCURRENCY` to a whole number from 1 to 8 to override the developer gate's test worker count. Without the setting, the gate uses one fewer worker than the available cores, with a minimum of 2 and a maximum of 4. macOS CI sets it to 3 and Ubuntu CI sets it to 4. Pull requests from branches of this repository run both jobs on local runners with the label `cloving-ci` (macOS arm64 and Linux arm64) with 8 workers; the local macOS runner accepts the macOS version of its machine. Invalid values fail with an error.
779
+
780
+ Tests that stop a child process should await `stopChild` from `test/stop-child.ts`. Use `stopChildGroup` for a detached process group, including descendants whose leader has exited. Both helpers send `SIGTERM`, wait up to five seconds times `CLOVING_CHECK_TIME_FACTOR` for exit, then escalate to `SIGKILL`. When a test requires a hard crash or an unresponsive child, start that child with `NODE_V8_COVERAGE` omitted so a kill cannot interrupt its coverage recording. Keep coverage enabled for ordinary child runs and recovery runs.
781
+
682
782
  The catalog and checker configuration are local proposals. The bounded SDK artifact, dependency-surface, production-coverage and mandatory-test inventory components have local qualification fixtures. Protected activation of their records, verifier execution and hooks remain pending. Dependency snapshots and supplied review records cannot activate a candidate. The local quality command cannot accept a product candidate. Static workflow checks are not isolation or replay proof. Deterministic sequencing fixtures qualify the test mechanism; they do not prove ownership or storage concurrency in the service.
683
783
 
684
784
  The coverage profile supports strip-only TypeScript and JavaScript (`ts`, `mts`, `cts`, `js`, `mjs`, `cjs`). It rejects source-map and coverage-ignore patterns interpreted by the provider, including patterns inside strings. Native V8 limitations around throwing calls and default arguments remain; coverage does not replace behavioral assertions. Production roles come from the complete module catalog, independently of which files tests import. Nested npm workspaces and unsupported dependency directory links fail explicitly until qualified.
@@ -0,0 +1,93 @@
1
+ Copyright 2014-2020 The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2014 The Heebo Project Authors (https://github.com/OdedEzer/heebo)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.