@cleocode/cleo 2026.5.110 → 2026.5.111

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.
package/dist/cli/index.js CHANGED
@@ -16199,10 +16199,12 @@ import {
16199
16199
  getCleoDirAbsolute,
16200
16200
  getProjectRoot as getProjectRoot5,
16201
16201
  memoryObserve as memoryObserve2,
16202
+ parseChangesetFrontmatter,
16202
16203
  releaseReservedSlug,
16203
16204
  reserveSlugForDispatch,
16204
16205
  resolveAttachmentBackend,
16205
- SlugCollisionError
16206
+ SlugCollisionError,
16207
+ writeChangesetEntry
16206
16208
  } from "@cleocode/core/internal";
16207
16209
  function getDocKindRegistry() {
16208
16210
  const root = getProjectRoot5();
@@ -16709,6 +16711,105 @@ var init_docs2 = __esm({
16709
16711
  }
16710
16712
  type2 = rawType;
16711
16713
  }
16714
+ if (type2 === "changeset") {
16715
+ if (!filePath) {
16716
+ return lafsError(
16717
+ "E_INVALID_INPUT",
16718
+ "changeset writes require a --file path (URL attachments are not supported for changesets)",
16719
+ "add"
16720
+ );
16721
+ }
16722
+ const absPath = resolve2(filePath);
16723
+ let bytes;
16724
+ try {
16725
+ bytes = await readFile(absPath);
16726
+ } catch {
16727
+ return lafsError("E_FILE_ERROR", `Cannot read file: ${absPath}`, "add");
16728
+ }
16729
+ const parsed = parseChangesetFrontmatter(bytes.toString("utf-8"));
16730
+ if (!parsed.ok) {
16731
+ let message;
16732
+ if (parsed.error === "missing-frontmatter") {
16733
+ message = "changeset file is missing the `---`-fenced YAML frontmatter. Required fields: id, tasks, kind, summary.";
16734
+ } else if (parsed.error === "missing-required") {
16735
+ message = `changeset frontmatter is missing required fields: ${parsed.missing.join(", ")}.`;
16736
+ } else if (parsed.error === "yaml-invalid") {
16737
+ const lineHint = parsed.line !== void 0 ? ` (line ${parsed.line})` : "";
16738
+ message = `changeset frontmatter YAML is invalid${lineHint}: ${parsed.parserMessage}`;
16739
+ } else {
16740
+ message = `changeset frontmatter failed schema validation: ${parsed.issues.join("; ")}`;
16741
+ }
16742
+ return {
16743
+ success: false,
16744
+ error: {
16745
+ code: "E_REQUIRES_CHANGESET_VERB",
16746
+ message,
16747
+ details: {
16748
+ fix: "Use `cleo changeset add --slug <id> --tasks <T####> --kind <kind> --summary <text>` for guided authoring.",
16749
+ parserError: parsed.error,
16750
+ ...parsed.error === "missing-required" ? { missing: parsed.missing } : {},
16751
+ ...parsed.error === "schema-invalid" ? { issues: parsed.issues } : {}
16752
+ }
16753
+ }
16754
+ };
16755
+ }
16756
+ if (slug !== void 0 && slug !== parsed.entry.id) {
16757
+ return {
16758
+ success: false,
16759
+ error: {
16760
+ code: "E_SLUG_MISMATCH",
16761
+ message: `--slug '${slug}' does not match changeset frontmatter id '${parsed.entry.id}'. The frontmatter is canonical \u2014 drop --slug or align it.`
16762
+ }
16763
+ };
16764
+ }
16765
+ const outcome = await writeChangesetEntry(parsed.entry, {
16766
+ projectRoot: getProjectRoot5(),
16767
+ attachedBy: typeof rawAttachedBy === "string" && rawAttachedBy.length > 0 ? rawAttachedBy : "cleo-docs-add"
16768
+ });
16769
+ if (!outcome.ok) {
16770
+ const err = outcome.error;
16771
+ if (err.code === "E_SLUG_PATTERN_MISMATCH") {
16772
+ const hint = err.example ? ` (example: ${err.example})` : "";
16773
+ return lafsError("E_SLUG_PATTERN_MISMATCH", `${err.message}${hint}`, "add");
16774
+ }
16775
+ if (err.code === "E_INVALID_ENTRY") {
16776
+ return lafsError("E_INVALID_INPUT", err.message, "add");
16777
+ }
16778
+ if (err.code === "E_FILE_WRITE_FAILED") {
16779
+ return lafsError("E_FILE_ERROR", err.message, "add");
16780
+ }
16781
+ return lafsError("E_SSOT_WRITE_FAILED", err.message, "add");
16782
+ }
16783
+ const changesetPayload = {
16784
+ kind: "doc-attachment",
16785
+ attachmentId: outcome.result.attachmentId,
16786
+ ownerId: outcome.result.ownerId,
16787
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
16788
+ slug: outcome.result.slug,
16789
+ type: "changeset"
16790
+ };
16791
+ emitDocAttachmentObservation(changesetPayload, getProjectRoot5());
16792
+ return lafsSuccess(
16793
+ {
16794
+ attachmentId: outcome.result.attachmentId,
16795
+ sha256: outcome.result.sha256,
16796
+ // writeChangesetEntry returns a freshly-minted ref so refCount is 1
16797
+ // (or more if the same content was already addressed by another
16798
+ // owner). The store sets the canonical value; mirroring it here
16799
+ // keeps the envelope shape identical to the file/url branches.
16800
+ refCount: 1,
16801
+ kind: "blob",
16802
+ ownerId: outcome.result.ownerId,
16803
+ ownerType: "task",
16804
+ // Changeset writes land in the legacy attachment store; v2 mirror
16805
+ // is not applicable to the dual-write transaction.
16806
+ attachmentBackend: "legacy",
16807
+ slug: outcome.result.slug,
16808
+ type: "changeset"
16809
+ },
16810
+ "add"
16811
+ );
16812
+ }
16712
16813
  if (type2 !== void 0 && slug !== void 0) {
16713
16814
  const patternCheck = getDocKindRegistry().validateSlug(type2, slug);
16714
16815
  if (!patternCheck.ok) {