@nextclaw/x-harness 0.2.40 → 0.2.41

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/SOURCE.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Corresponding source
2
2
 
3
- Version 0.2.40, commit 26581c241d56f52365a0e1e903cb0e0122c6988d.
3
+ Version 0.2.41, commit abb1997d1e0d7208ed22a5b47d36c9b7dc3b6832.
4
4
 
5
- Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/26581c241d56f52365a0e1e903cb0e0122c6988d
5
+ Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/abb1997d1e0d7208ed22a5b47d36c9b7dc3b6832
6
6
 
7
7
  Clone this revision, run npm ci, npm run bootstrap and npm run release:build.
8
8
 
@@ -1,7 +1,9 @@
1
1
  export declare class DraftSchedule {
2
2
  resolve(action: any): {
3
3
  at?: string;
4
+ until?: string;
4
5
  invalid?: boolean;
6
+ invalidAfter?: boolean;
5
7
  };
6
8
  reason(action: any, now: number): string | null;
7
9
  }
@@ -12,20 +12,36 @@ export class DraftSchedule {
12
12
  action.notBefore,
13
13
  ...Array.from(metadata.matchAll(/^(?:notBefore\s*:\s*|最早发布窗口[::]\s*)([^\n;;]+)/gm), (m) => m[1].trim().replace(/^['"]|['"]$/g, "")),
14
14
  ].filter((v) => v !== undefined && v !== null);
15
+ const endings = [
16
+ action.notAfter,
17
+ ...Array.from(metadata.matchAll(/^(?:notAfter\s*:\s*|最晚发布窗口[::]\s*)([^\n;;]+)/gm), (m) => m[1].trim().replace(/^['"]|['"]$/g, "")),
18
+ ].filter((v) => v !== undefined && v !== null);
19
+ if (endings.some((v) => typeof v !== "string" ||
20
+ !/(?:Z|[+-]\d{2}:\d{2})$/.test(v) ||
21
+ !Number.isFinite(Date.parse(v))))
22
+ return { invalid: true, invalidAfter: true };
23
+ const until = endings.length
24
+ ? new Date(Math.min(...endings.map((v) => Date.parse(v)))).toISOString()
25
+ : undefined;
15
26
  if (!declared.length)
16
- return {};
27
+ return until ? { until } : {};
17
28
  if (declared.some((v) => typeof v !== "string" ||
18
29
  !/(?:Z|[+-]\d{2}:\d{2})$/.test(v) ||
19
30
  !Number.isFinite(Date.parse(v))))
20
31
  return { invalid: true };
21
- return {
22
- at: new Date(Math.max(...declared.map((v) => Date.parse(v)))).toISOString(),
23
- };
32
+ const at = new Date(Math.max(...declared.map((v) => Date.parse(v)))).toISOString();
33
+ if (until && Date.parse(until) <= Date.parse(at))
34
+ return { invalid: true, invalidAfter: true };
35
+ return { at, ...(until ? { until } : {}) };
24
36
  }
25
37
  reason(action, now) {
26
38
  const schedule = this.resolve(action);
27
39
  if (schedule.invalid)
28
- return "draft-not-before-invalid";
40
+ return schedule.invalidAfter
41
+ ? "draft-not-after-invalid"
42
+ : "draft-not-before-invalid";
43
+ if (schedule.until && now >= Date.parse(schedule.until))
44
+ return "draft-window-expired";
29
45
  return schedule.at && now < Date.parse(schedule.at)
30
46
  ? "draft-not-before-not-reached"
31
47
  : null;
package/dist/types.d.ts CHANGED
@@ -250,6 +250,8 @@ export type PreparedAction = PreparedActionBase & ({
250
250
  kind: "original";
251
251
  draftPath: string;
252
252
  notBefore?: string;
253
+ /** Exclusive publication deadline; does not block unknown recovery. */
254
+ notAfter?: string;
253
255
  text: string;
254
256
  composeURL: string;
255
257
  composeEvidenceRef: EvidenceRef;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/x-harness",
3
- "version": "0.2.40",
3
+ "version": "0.2.41",
4
4
  "type": "module",
5
5
  "description": "Typed X task harness with compact business results and explicit diagnostics.",
6
6
  "main": "./dist/index.js",
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "26581c241d56f52365a0e1e903cb0e0122c6988d"
45
+ "gitHead": "abb1997d1e0d7208ed22a5b47d36c9b7dc3b6832"
46
46
  }
@@ -14,6 +14,8 @@ Action APIs return status/actionId/publicURL/evidenceRef and reason/missing/resu
14
14
 
15
15
  Original action optional notBefore is an ISO timestamp with timezone. Explicit draft header notBefore or 最早发布窗口 is also enforced; the later constraint wins. Invalid metadata blocks, and before-window independent publishing returns waiting; scoped rounds report draft-not-before-not-reached. Both preserve no intent or submission. Recovery of an already submitted post is unaffected.
16
16
 
17
+ Original actions may pass `notAfter` as the calendar window’s exclusive ISO end. It is rechecked at intent and immediately before activation; expiration submits nothing. Unknown verification remains allowed after expiry.
18
+
17
19
  Additional fields: kind:'original', draftPath (existing .post.md), text (complete approved text), composeURL, composeEvidenceRef; optional assets:[{path,alt}], activation:'click'|'keyboard'. Every media path must exist and be reviewed. The DOM uploader supports one absolute PNG/JPEG/WebP image with required ALT, or one absolute MP4 video. Video uploads wait for a visible preview and public settlement requires a video on the exact fresh post; image ALT controls are not applied to videos.
18
20
 
19
21
  ```js