@agent-plan/core 0.2.28 → 0.3.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.
- package/dist/accepted-decision-guard.d.ts +94 -0
- package/dist/accepted-decision-guard.d.ts.map +1 -0
- package/dist/accepted-decision-guard.js +110 -0
- package/dist/checklist.d.ts +28 -0
- package/dist/checklist.d.ts.map +1 -1
- package/dist/checklist.js +59 -0
- package/dist/feature-delete.d.ts +62 -0
- package/dist/feature-delete.d.ts.map +1 -0
- package/dist/feature-delete.js +49 -0
- package/dist/guard-decision.d.ts +118 -0
- package/dist/guard-decision.d.ts.map +1 -0
- package/dist/guard-decision.js +203 -0
- package/dist/handoff-context.d.ts +130 -1
- package/dist/handoff-context.d.ts.map +1 -1
- package/dist/handoff-context.js +167 -9
- package/dist/handoff-reply.d.ts +108 -0
- package/dist/handoff-reply.d.ts.map +1 -0
- package/dist/handoff-reply.js +279 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/mutation-reply.d.ts +105 -0
- package/dist/mutation-reply.d.ts.map +1 -0
- package/dist/mutation-reply.js +203 -0
- package/dist/naming.d.ts +1 -1
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +1 -1
- package/dist/pagination.d.ts +19 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +15 -0
- package/dist/payload-fallback.js +1 -1
- package/dist/plan-store.d.ts +141 -8
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +459 -87
- package/dist/project-context-migration.d.ts +5 -0
- package/dist/project-context-migration.d.ts.map +1 -1
- package/dist/project-context-migration.js +13 -0
- package/dist/project-context.d.ts +395 -0
- package/dist/project-context.d.ts.map +1 -0
- package/dist/project-context.js +295 -0
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +27 -0
- package/dist/recommend-reply.d.ts +51 -0
- package/dist/recommend-reply.d.ts.map +1 -0
- package/dist/recommend-reply.js +84 -0
- package/dist/refs.d.ts +16 -0
- package/dist/refs.d.ts.map +1 -1
- package/dist/refs.js +38 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/schema.d.ts +7 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +8 -3
- package/dist/stranded-phase.d.ts +73 -0
- package/dist/stranded-phase.d.ts.map +1 -0
- package/dist/stranded-phase.js +93 -0
- package/dist/task-completion-gate.d.ts +84 -0
- package/dist/task-completion-gate.d.ts.map +1 -0
- package/dist/task-completion-gate.js +72 -0
- package/dist/task-context.d.ts +1 -0
- package/dist/task-context.d.ts.map +1 -1
- package/dist/task-context.js +31 -13
- package/dist/task-lifecycle.d.ts +12 -0
- package/dist/task-lifecycle.d.ts.map +1 -0
- package/dist/task-lifecycle.js +23 -0
- package/dist/task-order-context.d.ts +72 -0
- package/dist/task-order-context.d.ts.map +1 -0
- package/dist/task-order-context.js +82 -0
- package/dist/task-selection.d.ts.map +1 -1
- package/dist/task-selection.js +14 -12
- package/dist/task-start-outcome.d.ts +26 -0
- package/dist/task-start-outcome.d.ts.map +1 -1
- package/dist/task-start-outcome.js +23 -0
- package/dist/text-bounds.d.ts +32 -0
- package/dist/text-bounds.d.ts.map +1 -0
- package/dist/text-bounds.js +43 -0
- package/dist/write-coordination.d.ts +2 -2
- package/dist/write-coordination.js +2 -2
- package/package.json +1 -1
- package/planner-skill.md +30 -12
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export * from "./naming.js";
|
|
2
2
|
export * from "./refs.js";
|
|
3
|
+
export * from "./render-utils.js";
|
|
4
|
+
export * from "./pagination.js";
|
|
5
|
+
export * from "./task-lifecycle.js";
|
|
3
6
|
export * from "./schema.js";
|
|
4
7
|
export * from "./checklist.js";
|
|
5
8
|
export * from "./recap.js";
|
|
@@ -7,18 +10,29 @@ export * from "./planner-rules.js";
|
|
|
7
10
|
export * from "./planner-skill.js";
|
|
8
11
|
export * from "./display-status.js";
|
|
9
12
|
export * from "./description-freshness.js";
|
|
13
|
+
export * from "./text-bounds.js";
|
|
10
14
|
export * from "./task-context.js";
|
|
11
15
|
export * from "./task-selection.js";
|
|
12
16
|
export * from "./task-start-outcome.js";
|
|
17
|
+
export * from "./task-order-context.js";
|
|
18
|
+
export * from "./task-completion-gate.js";
|
|
19
|
+
export * from "./stranded-phase.js";
|
|
13
20
|
export * from "./read-tracking.js";
|
|
14
21
|
export * from "./payload-fallback.js";
|
|
15
22
|
export * from "./handoff-context.js";
|
|
23
|
+
export * from "./handoff-reply.js";
|
|
24
|
+
export * from "./mutation-reply.js";
|
|
25
|
+
export * from "./recommend-reply.js";
|
|
26
|
+
export * from "./feature-delete.js";
|
|
27
|
+
export * from "./accepted-decision-guard.js";
|
|
16
28
|
export * from "./project-context-migration.js";
|
|
29
|
+
export * from "./project-context.js";
|
|
17
30
|
export * from "./requirement-macro-tasks.js";
|
|
18
31
|
export * from "./package-version.js";
|
|
19
32
|
export * from "./runtime-diagnostics.js";
|
|
20
33
|
export * from "./write-coordination.js";
|
|
21
|
-
export
|
|
34
|
+
export * from "./guard-decision.js";
|
|
35
|
+
export { PlanStore, PlanStoreError, PlanStaleWriteError, PlanUnsupportedAllocationKindError, assertPlannerRevision, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, nowISO, type IdeaCreateInput, type IdeaUpdateInput, type IdeaPromotionTargetInput, type AcceptedDecisionOwner, type AcceptedDecisionCreateInput, type AcceptedDecisionUpdateInput, type RecordProjectContextReadInput, type RecordProjectContextReadResult, type PhaseHandoffSummary, type OrphanPhaseSummary } from "./plan-store.js";
|
|
22
36
|
export { PlanRenderer } from "./renderer.js";
|
|
23
37
|
export { ExportService } from "./export-service.js";
|
|
24
38
|
export type { CodebaseProfile, ResumeFocus, ActivityEntry, ActivityLog, AmbientFacts } from "./schema.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,kCAAkC,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,wBAAwB,EAAE,KAAK,qBAAqB,EAAE,KAAK,2BAA2B,EAAE,KAAK,2BAA2B,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,kCAAkC,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,wBAAwB,EAAE,KAAK,qBAAqB,EAAE,KAAK,2BAA2B,EAAE,KAAK,2BAA2B,EAAE,KAAK,6BAA6B,EAAE,KAAK,8BAA8B,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC3hB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export * from "./naming.js";
|
|
2
2
|
export * from "./refs.js";
|
|
3
|
+
export * from "./render-utils.js";
|
|
4
|
+
export * from "./pagination.js";
|
|
5
|
+
export * from "./task-lifecycle.js";
|
|
3
6
|
export * from "./schema.js";
|
|
4
7
|
export * from "./checklist.js";
|
|
5
8
|
export * from "./recap.js";
|
|
@@ -7,17 +10,28 @@ export * from "./planner-rules.js";
|
|
|
7
10
|
export * from "./planner-skill.js";
|
|
8
11
|
export * from "./display-status.js";
|
|
9
12
|
export * from "./description-freshness.js";
|
|
13
|
+
export * from "./text-bounds.js";
|
|
10
14
|
export * from "./task-context.js";
|
|
11
15
|
export * from "./task-selection.js";
|
|
12
16
|
export * from "./task-start-outcome.js";
|
|
17
|
+
export * from "./task-order-context.js";
|
|
18
|
+
export * from "./task-completion-gate.js";
|
|
19
|
+
export * from "./stranded-phase.js";
|
|
13
20
|
export * from "./read-tracking.js";
|
|
14
21
|
export * from "./payload-fallback.js";
|
|
15
22
|
export * from "./handoff-context.js";
|
|
23
|
+
export * from "./handoff-reply.js";
|
|
24
|
+
export * from "./mutation-reply.js";
|
|
25
|
+
export * from "./recommend-reply.js";
|
|
26
|
+
export * from "./feature-delete.js";
|
|
27
|
+
export * from "./accepted-decision-guard.js";
|
|
16
28
|
export * from "./project-context-migration.js";
|
|
29
|
+
export * from "./project-context.js";
|
|
17
30
|
export * from "./requirement-macro-tasks.js";
|
|
18
31
|
export * from "./package-version.js";
|
|
19
32
|
export * from "./runtime-diagnostics.js";
|
|
20
33
|
export * from "./write-coordination.js";
|
|
21
|
-
export
|
|
34
|
+
export * from "./guard-decision.js";
|
|
35
|
+
export { PlanStore, PlanStoreError, PlanStaleWriteError, PlanUnsupportedAllocationKindError, assertPlannerRevision, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, nowISO } from "./plan-store.js";
|
|
22
36
|
export { PlanRenderer } from "./renderer.js";
|
|
23
37
|
export { ExportService } from "./export-service.js";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { PlannerPayloadEntity, PlannerPayloadOperation } from "./payload-fallback.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-field echo budget. A changed field is worth showing back so the caller
|
|
4
|
+
* can confirm what landed without a second call; a changed field the size of
|
|
5
|
+
* a task description is not. 2,000 characters is about three screens — long
|
|
6
|
+
* enough to read a title, a status, a checklist or a short note whole, short
|
|
7
|
+
* enough that echoing a full description is impossible.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MUTATION_ECHO_MAX_FIELD_CHARS = 2000;
|
|
10
|
+
/**
|
|
11
|
+
* Ceiling for the whole structured payload of a mutation reply. Chosen to
|
|
12
|
+
* match MAX_PHASE_WORK_MAP_CHARS and MAX_ACCEPTED_DECISION_CONTEXT_CHARS so
|
|
13
|
+
* an agent has one number in mind for planner payloads rather than four.
|
|
14
|
+
* When the assembled payload exceeds it, echoed values are dropped to names
|
|
15
|
+
* (see `boundMutationEcho`) — the caller still learns exactly which fields
|
|
16
|
+
* changed, which is the part it cannot get anywhere else.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MUTATION_REPLY_MAX_CHARS = 8000;
|
|
19
|
+
/**
|
|
20
|
+
* The long-text size a planner tool accepts in one call, stated up front so
|
|
21
|
+
* a caller does not discover it by being rejected. This is not a limit the
|
|
22
|
+
* planner imposes for its own sake: a long `description` can be dropped by
|
|
23
|
+
* the transport before it ever reaches the planner, which arrives here as
|
|
24
|
+
* "no mutable fields received" and is why DESCRIPTION_MARKDOWN_FALLBACK_REQUIRED
|
|
25
|
+
* exists. Measured: ~13,500 characters accepted, ~17,000 rejected. 12,000 is
|
|
26
|
+
* under the observed floor with room to spare.
|
|
27
|
+
*
|
|
28
|
+
* Above this, write the prose to a committed file under `.planner/docs/` and
|
|
29
|
+
* pass `descriptionRef` — see suggestedDescriptionRefPath in payload-fallback.ts.
|
|
30
|
+
*/
|
|
31
|
+
export declare const PLANNER_LONG_TEXT_FIELD_MAX_CHARS = 12000;
|
|
32
|
+
/**
|
|
33
|
+
* One sentence for a tool description, so the limit is discoverable at the
|
|
34
|
+
* point of the call instead of after it fails. Every tool taking a long text
|
|
35
|
+
* field appends this to its own description.
|
|
36
|
+
*/
|
|
37
|
+
export declare function longTextFieldLimitNotice(field?: string): string;
|
|
38
|
+
/** A tool reply as one result: the human-readable body and the structured
|
|
39
|
+
* payload, with no field present in both. */
|
|
40
|
+
export interface MutationReply {
|
|
41
|
+
text: string;
|
|
42
|
+
structured: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
/** Who was mutated, in the terms a caller refers to it by. The canonical
|
|
45
|
+
* `ref` is what travels — never the raw text the caller happened to type,
|
|
46
|
+
* which may be a short id, a title or a UUID. */
|
|
47
|
+
export interface MutationIdentity {
|
|
48
|
+
entity: PlannerPayloadEntity;
|
|
49
|
+
ref: string;
|
|
50
|
+
id?: string;
|
|
51
|
+
shortId?: string;
|
|
52
|
+
title?: string;
|
|
53
|
+
status?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface MutationReplyInput {
|
|
56
|
+
identity: MutationIdentity;
|
|
57
|
+
operation: PlannerPayloadOperation;
|
|
58
|
+
/** Fields the caller actually changed, in the order they were received. */
|
|
59
|
+
updatedFields: readonly string[];
|
|
60
|
+
/** The persisted values of those fields, to be echoed back within budget.
|
|
61
|
+
* Keys outside `updatedFields` are ignored: a mutation reply never carries
|
|
62
|
+
* a field the mutation did not touch. */
|
|
63
|
+
changedValues?: Record<string, unknown>;
|
|
64
|
+
/** Diagnostics that are not the entity — description freshness, stale
|
|
65
|
+
* parents, lost checklist ticks, resume-required notices. These are the
|
|
66
|
+
* reason to read a mutation result at all, so they are never trimmed. */
|
|
67
|
+
extras?: Record<string, unknown>;
|
|
68
|
+
/** Extra lines for the human channel, such as a lost-tick warning. */
|
|
69
|
+
notices?: readonly string[];
|
|
70
|
+
/** The command that returns the full entity, for a caller that wants what
|
|
71
|
+
* this reply deliberately leaves out. */
|
|
72
|
+
readBackCommand?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build the one reply every mutation tool returns.
|
|
76
|
+
*
|
|
77
|
+
* What a caller gets: that the write happened, which fields it touched, the
|
|
78
|
+
* canonical ref and identity of what it touched, the changed values within
|
|
79
|
+
* budget, and every diagnostic. What it does not get: the rest of the
|
|
80
|
+
* entity, which it can read with the command named in `readBack`.
|
|
81
|
+
*
|
|
82
|
+
* `updated` (or `discussed`), `updatedFields` and any `errorCode` keep their
|
|
83
|
+
* exact prior shape — mutation-integrity checking across the whole project
|
|
84
|
+
* reads those three and nothing else.
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildMutationReply(input: MutationReplyInput): MutationReply;
|
|
87
|
+
export interface DerivedStatusReadOnlyInput {
|
|
88
|
+
entity: "feature" | "phase";
|
|
89
|
+
ref: string;
|
|
90
|
+
attemptedStatus: string;
|
|
91
|
+
effectiveStatus: string;
|
|
92
|
+
/** Full "retry without the status field" instruction. Each adapter names
|
|
93
|
+
* its own update tool (`planner-feature-update` vs `feature_update`), so
|
|
94
|
+
* this one line stays adapter-supplied rather than templated here —
|
|
95
|
+
* moving it into the core would restate a tool name the core doesn't own. */
|
|
96
|
+
retryAction: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* A feature/phase `status` field cannot be set directly — it is derived
|
|
100
|
+
* from child phases/tasks. Both adapters carried an identical copy of this
|
|
101
|
+
* refusal for feature_update/phase_update; only the retry line's tool name
|
|
102
|
+
* differs, which is why it is the one caller-supplied piece.
|
|
103
|
+
*/
|
|
104
|
+
export declare function derivedStatusReadOnlyReply(input: DerivedStatusReadOnlyInput): MutationReply;
|
|
105
|
+
//# sourceMappingURL=mutation-reply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-reply.d.ts","sourceRoot":"","sources":["../src/mutation-reply.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAE3F;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,OAAQ,CAAC;AAEnD;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,SAAgB,GAAG,MAAM,CAEtE;AAED;6CAC6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;iDAEiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,uBAAuB,CAAC;IACnC,2EAA2E;IAC3E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;6CAEyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;6EAEyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,sEAAsE;IACtE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;6CACyC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAoED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CA6C3E;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB;;;kFAG8E;IAC9E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,0BAA0B,GAAG,aAAa,CA4B3F"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared reply shaping for every mutation tool (update, discuss, and the
|
|
3
|
+
* small mutations around them).
|
|
4
|
+
*
|
|
5
|
+
* The rule this file exists to hold: a mutation result says what changed.
|
|
6
|
+
* It does not say what the entity now contains. Before P104(F005)/T417 each
|
|
7
|
+
* adapter hand-built `{ ...entity, updated: true }`, so changing one field
|
|
8
|
+
* on this repository's own P104 returned 139,805 characters — every task
|
|
9
|
+
* body in the phase, echoed back to a caller who already knew them. A task
|
|
10
|
+
* update peaked at 33,499. The harness had to spill those results to a file,
|
|
11
|
+
* and reading back whether `updated` was true then needed jq.
|
|
12
|
+
*
|
|
13
|
+
* The bound lives here rather than in an adapter for the reason in AGENTS.md
|
|
14
|
+
* rule 4: both adapters render what the core returns, so neither can drift
|
|
15
|
+
* and a third harness inherits the bound without knowing it exists. Four
|
|
16
|
+
* separate defects in P104 came from logic duplicated per adapter.
|
|
17
|
+
*
|
|
18
|
+
* Channel discipline matches handoff-reply.ts: `text` is the human-readable
|
|
19
|
+
* body, `structured` is the machine-readable payload, and no field is
|
|
20
|
+
* carried by both.
|
|
21
|
+
*/
|
|
22
|
+
import { truncateAtSafeBoundary } from "./text-bounds.js";
|
|
23
|
+
/**
|
|
24
|
+
* Per-field echo budget. A changed field is worth showing back so the caller
|
|
25
|
+
* can confirm what landed without a second call; a changed field the size of
|
|
26
|
+
* a task description is not. 2,000 characters is about three screens — long
|
|
27
|
+
* enough to read a title, a status, a checklist or a short note whole, short
|
|
28
|
+
* enough that echoing a full description is impossible.
|
|
29
|
+
*/
|
|
30
|
+
export const MUTATION_ECHO_MAX_FIELD_CHARS = 2_000;
|
|
31
|
+
/**
|
|
32
|
+
* Ceiling for the whole structured payload of a mutation reply. Chosen to
|
|
33
|
+
* match MAX_PHASE_WORK_MAP_CHARS and MAX_ACCEPTED_DECISION_CONTEXT_CHARS so
|
|
34
|
+
* an agent has one number in mind for planner payloads rather than four.
|
|
35
|
+
* When the assembled payload exceeds it, echoed values are dropped to names
|
|
36
|
+
* (see `boundMutationEcho`) — the caller still learns exactly which fields
|
|
37
|
+
* changed, which is the part it cannot get anywhere else.
|
|
38
|
+
*/
|
|
39
|
+
export const MUTATION_REPLY_MAX_CHARS = 8_000;
|
|
40
|
+
/**
|
|
41
|
+
* The long-text size a planner tool accepts in one call, stated up front so
|
|
42
|
+
* a caller does not discover it by being rejected. This is not a limit the
|
|
43
|
+
* planner imposes for its own sake: a long `description` can be dropped by
|
|
44
|
+
* the transport before it ever reaches the planner, which arrives here as
|
|
45
|
+
* "no mutable fields received" and is why DESCRIPTION_MARKDOWN_FALLBACK_REQUIRED
|
|
46
|
+
* exists. Measured: ~13,500 characters accepted, ~17,000 rejected. 12,000 is
|
|
47
|
+
* under the observed floor with room to spare.
|
|
48
|
+
*
|
|
49
|
+
* Above this, write the prose to a committed file under `.planner/docs/` and
|
|
50
|
+
* pass `descriptionRef` — see suggestedDescriptionRefPath in payload-fallback.ts.
|
|
51
|
+
*/
|
|
52
|
+
export const PLANNER_LONG_TEXT_FIELD_MAX_CHARS = 12_000;
|
|
53
|
+
/**
|
|
54
|
+
* One sentence for a tool description, so the limit is discoverable at the
|
|
55
|
+
* point of the call instead of after it fails. Every tool taking a long text
|
|
56
|
+
* field appends this to its own description.
|
|
57
|
+
*/
|
|
58
|
+
export function longTextFieldLimitNotice(field = "description") {
|
|
59
|
+
return `Keep ${field} under ${PLANNER_LONG_TEXT_FIELD_MAX_CHARS.toLocaleString("en-US")} characters; above that the transport may drop it before it arrives. Put longer prose in a committed .planner/docs/ file and pass ${field}Ref instead.`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Bound one echoed value. A short string travels whole. A long one is cut at
|
|
63
|
+
* a safe boundary — paragraph, then line, then word, the same helper the
|
|
64
|
+
* handoff path uses — and reports its true length, so a caller can tell a
|
|
65
|
+
* 2,000-character field from a 20,000-character one without receiving either
|
|
66
|
+
* in full. Arrays and objects are measured by their serialized size and
|
|
67
|
+
* degrade to a count rather than a preview, because half an array read as
|
|
68
|
+
* whole is worse than no array at all.
|
|
69
|
+
*/
|
|
70
|
+
function boundEchoedValue(value) {
|
|
71
|
+
if (typeof value === "string") {
|
|
72
|
+
if (value.length <= MUTATION_ECHO_MAX_FIELD_CHARS)
|
|
73
|
+
return { value, truncated: false };
|
|
74
|
+
const bounded = truncateAtSafeBoundary(value, MUTATION_ECHO_MAX_FIELD_CHARS);
|
|
75
|
+
return {
|
|
76
|
+
value: { preview: bounded, fullLength: value.length, truncated: true },
|
|
77
|
+
truncated: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
81
|
+
return { value, truncated: false };
|
|
82
|
+
}
|
|
83
|
+
const serialized = JSON.stringify(value) ?? "";
|
|
84
|
+
if (serialized.length <= MUTATION_ECHO_MAX_FIELD_CHARS)
|
|
85
|
+
return { value, truncated: false };
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
return { value: { count: value.length, serializedLength: serialized.length, truncated: true }, truncated: true };
|
|
88
|
+
}
|
|
89
|
+
return { value: { keys: Object.keys(value), serializedLength: serialized.length, truncated: true }, truncated: true };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Assemble the echo of changed fields within the reply ceiling. Fields are
|
|
93
|
+
* taken in the order the caller changed them and the budget is shared, so
|
|
94
|
+
* one large field cannot crowd out the rest: what does not fit is named in
|
|
95
|
+
* `omittedValues` rather than silently dropped. Naming what was left out is
|
|
96
|
+
* the same degradation the prepare path uses — elided must never mean
|
|
97
|
+
* invisible.
|
|
98
|
+
*/
|
|
99
|
+
function boundMutationEcho(updatedFields, changedValues, budget) {
|
|
100
|
+
const changed = {};
|
|
101
|
+
const omittedValues = [];
|
|
102
|
+
const truncatedFields = [];
|
|
103
|
+
let remaining = budget;
|
|
104
|
+
for (const field of updatedFields) {
|
|
105
|
+
if (!(field in changedValues))
|
|
106
|
+
continue;
|
|
107
|
+
const bounded = boundEchoedValue(changedValues[field]);
|
|
108
|
+
const cost = (JSON.stringify(bounded.value) ?? "").length + field.length + 4;
|
|
109
|
+
if (cost > remaining) {
|
|
110
|
+
omittedValues.push(field);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
remaining -= cost;
|
|
114
|
+
changed[field] = bounded.value;
|
|
115
|
+
if (bounded.truncated)
|
|
116
|
+
truncatedFields.push(field);
|
|
117
|
+
}
|
|
118
|
+
return { changed, omittedValues, truncatedFields };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Build the one reply every mutation tool returns.
|
|
122
|
+
*
|
|
123
|
+
* What a caller gets: that the write happened, which fields it touched, the
|
|
124
|
+
* canonical ref and identity of what it touched, the changed values within
|
|
125
|
+
* budget, and every diagnostic. What it does not get: the rest of the
|
|
126
|
+
* entity, which it can read with the command named in `readBack`.
|
|
127
|
+
*
|
|
128
|
+
* `updated` (or `discussed`), `updatedFields` and any `errorCode` keep their
|
|
129
|
+
* exact prior shape — mutation-integrity checking across the whole project
|
|
130
|
+
* reads those three and nothing else.
|
|
131
|
+
*/
|
|
132
|
+
export function buildMutationReply(input) {
|
|
133
|
+
const { identity, operation, updatedFields } = input;
|
|
134
|
+
const fields = [...updatedFields];
|
|
135
|
+
const extras = input.extras ?? {};
|
|
136
|
+
const identityPayload = {
|
|
137
|
+
entity: identity.entity,
|
|
138
|
+
ref: identity.ref,
|
|
139
|
+
...(identity.id ? { id: identity.id } : {}),
|
|
140
|
+
...(identity.shortId ? { shortId: identity.shortId } : {}),
|
|
141
|
+
...(identity.title ? { title: identity.title } : {}),
|
|
142
|
+
...(identity.status ? { status: identity.status } : {}),
|
|
143
|
+
};
|
|
144
|
+
// Everything except the echo is non-negotiable, so the echo gets whatever
|
|
145
|
+
// the ceiling leaves once identity, fields and diagnostics are counted.
|
|
146
|
+
const fixedCost = (JSON.stringify({ ...identityPayload, updatedFields: fields, ...extras }) ?? "").length;
|
|
147
|
+
const { changed, omittedValues, truncatedFields } = boundMutationEcho(fields, input.changedValues ?? {}, Math.max(0, MUTATION_REPLY_MAX_CHARS - fixedCost));
|
|
148
|
+
const structured = {
|
|
149
|
+
...(operation === "discuss" ? { discussed: true } : { updated: true }),
|
|
150
|
+
...identityPayload,
|
|
151
|
+
updatedFields: fields,
|
|
152
|
+
...(Object.keys(changed).length > 0 ? { changed } : {}),
|
|
153
|
+
...(truncatedFields.length > 0 ? { truncatedFields } : {}),
|
|
154
|
+
...(omittedValues.length > 0 ? { omittedValues } : {}),
|
|
155
|
+
...extras,
|
|
156
|
+
...(input.readBackCommand ? { readBack: input.readBackCommand } : {}),
|
|
157
|
+
};
|
|
158
|
+
const descriptor = [identity.ref, identity.title].filter(Boolean).join(" — ");
|
|
159
|
+
const statusSuffix = identity.status ? ` (${identity.status})` : "";
|
|
160
|
+
const shortIdSuffix = identity.shortId ? ` · ${identity.shortId}` : "";
|
|
161
|
+
const verb = operation === "discuss" ? "discussed/updated" : "updated";
|
|
162
|
+
const entityLabel = identity.entity.charAt(0).toUpperCase() + identity.entity.slice(1);
|
|
163
|
+
const lines = [
|
|
164
|
+
`✅ ${entityLabel} ${verb}: ${descriptor}${statusSuffix}${shortIdSuffix}. Fields saved: ${fields.join(", ")}.`,
|
|
165
|
+
...(input.notices ?? []).filter((notice) => notice.trim().length > 0),
|
|
166
|
+
];
|
|
167
|
+
return { text: lines.join(" "), structured };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* A feature/phase `status` field cannot be set directly — it is derived
|
|
171
|
+
* from child phases/tasks. Both adapters carried an identical copy of this
|
|
172
|
+
* refusal for feature_update/phase_update; only the retry line's tool name
|
|
173
|
+
* differs, which is why it is the one caller-supplied piece.
|
|
174
|
+
*/
|
|
175
|
+
export function derivedStatusReadOnlyReply(input) {
|
|
176
|
+
const { entity, ref, attemptedStatus, effectiveStatus, retryAction } = input;
|
|
177
|
+
const childKind = entity === "feature" ? "phases" : "tasks";
|
|
178
|
+
const label = `${entity[0].toUpperCase()}${entity.slice(1)}`;
|
|
179
|
+
const nextActions = [
|
|
180
|
+
`${label} status is derived from child ${childKind}; update the child ${childKind} instead of setting ${entity}.status.`,
|
|
181
|
+
retryAction,
|
|
182
|
+
];
|
|
183
|
+
return {
|
|
184
|
+
text: [
|
|
185
|
+
`❌ ${entity.toUpperCase()} UPDATE FAILED [DERIVED_STATUS_READ_ONLY]`,
|
|
186
|
+
`${label} status is derived from child ${childKind} and cannot be set directly.`,
|
|
187
|
+
`Attempted status: ${attemptedStatus}`,
|
|
188
|
+
`Effective derived status: ${effectiveStatus}`,
|
|
189
|
+
"No planner data was changed.",
|
|
190
|
+
"Next required actions:",
|
|
191
|
+
...nextActions.map((action, index) => `${index + 1}. ${action}`),
|
|
192
|
+
].join("\n"),
|
|
193
|
+
structured: {
|
|
194
|
+
updated: false,
|
|
195
|
+
errorCode: "DERIVED_STATUS_READ_ONLY",
|
|
196
|
+
entity,
|
|
197
|
+
ref,
|
|
198
|
+
attemptedStatus,
|
|
199
|
+
effectiveStatus,
|
|
200
|
+
nextActions,
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
package/dist/naming.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare function createPhaseId(): string;
|
|
|
52
52
|
/** True for legacy phase ids that are NOT feature-scoped (e.g. `phase-01-...`). */
|
|
53
53
|
export declare function isLegacyPhaseId(phaseId: string): boolean;
|
|
54
54
|
/** Compute the feature-scoped id for a legacy phase, preserving featureId/number/slug. */
|
|
55
|
-
export declare function migratePhaseId(
|
|
55
|
+
export declare function migratePhaseId(_featureId: string, _number: number, _slug: string): string;
|
|
56
56
|
export declare function createTaskId(): string;
|
|
57
57
|
export declare function createRequirementId(): string;
|
|
58
58
|
export declare function createIdeaId(): string;
|
package/dist/naming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAKA;iFACiF;AACjF,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAErE,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,gBAAgB,QAAkB,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,QAAoE,CAAC;AAE9F,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEtD;AAED;;gEAEgE;AAChE,wBAAsB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,IAAI,EAAE,SAAS,GAAG,OAAO,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GACnC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAStD;AAGD;;;;;qCAKqC;AACrC,wBAAgB,aAAa,CAAC,QAAQ,GAAE,GAAG,CAAC,MAAM,CAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BtF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;8BAI8B;AAC9B,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,SAAa,GAAG,MAAM,CAGnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;iBAEiB;AACjB,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EAChD,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAKA;iFACiF;AACjF,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAErE,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,gBAAgB,QAAkB,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,QAAoE,CAAC;AAE9F,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEtD;AAED;;gEAEgE;AAChE,wBAAsB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,IAAI,EAAE,SAAS,GAAG,OAAO,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GACnC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAStD;AAGD;;;;;qCAKqC;AACrC,wBAAgB,aAAa,CAAC,QAAQ,GAAE,GAAG,CAAC,MAAM,CAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BtF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;8BAI8B;AAC9B,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,SAAa,GAAG,MAAM,CAGnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;iBAEiB;AACjB,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EAChD,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
|
package/dist/naming.js
CHANGED
|
@@ -110,7 +110,7 @@ export function isLegacyPhaseId(phaseId) {
|
|
|
110
110
|
return phaseId.startsWith("phase-") && !phaseId.startsWith("feature-");
|
|
111
111
|
}
|
|
112
112
|
/** Compute the feature-scoped id for a legacy phase, preserving featureId/number/slug. */
|
|
113
|
-
export function migratePhaseId(
|
|
113
|
+
export function migratePhaseId(_featureId, _number, _slug) {
|
|
114
114
|
// In UUID world, this is just randomUUID, but we keep signature for compatibility if needed
|
|
115
115
|
return randomUUID();
|
|
116
116
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared list-pagination primitive. Both adapters defined an identical
|
|
3
|
+
* `boundedPage` (page list tools: feature/phase/task/requirement listing,
|
|
4
|
+
* idea listing) with the same 1-25 page-size clamp and the same
|
|
5
|
+
* page-out-of-range clamp. One copy here so the bound is a single decision,
|
|
6
|
+
* not something each adapter must independently re-derive and keep in sync.
|
|
7
|
+
*/
|
|
8
|
+
export interface BoundedPage<T> {
|
|
9
|
+
items: T[];
|
|
10
|
+
page: number;
|
|
11
|
+
pageSize: number;
|
|
12
|
+
total: number;
|
|
13
|
+
totalPages: number;
|
|
14
|
+
}
|
|
15
|
+
/** Slice `items` into a bounded page. `pageSize` is clamped to [1, 25];
|
|
16
|
+
* `page` is clamped to [1, totalPages] so an out-of-range request degrades
|
|
17
|
+
* to the nearest valid page instead of an empty result. */
|
|
18
|
+
export declare function boundedPage<T>(items: T[], page: number, pageSize: number): BoundedPage<T>;
|
|
19
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;4DAE4D;AAC5D,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAWzF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Slice `items` into a bounded page. `pageSize` is clamped to [1, 25];
|
|
2
|
+
* `page` is clamped to [1, totalPages] so an out-of-range request degrades
|
|
3
|
+
* to the nearest valid page instead of an empty result. */
|
|
4
|
+
export function boundedPage(items, page, pageSize) {
|
|
5
|
+
const size = Math.min(25, Math.max(1, Math.trunc(pageSize)));
|
|
6
|
+
const totalPages = Math.max(1, Math.ceil(items.length / size));
|
|
7
|
+
const currentPage = Math.min(totalPages, Math.max(1, Math.trunc(page)));
|
|
8
|
+
return {
|
|
9
|
+
items: items.slice((currentPage - 1) * size, currentPage * size),
|
|
10
|
+
page: currentPage,
|
|
11
|
+
pageSize: size,
|
|
12
|
+
total: items.length,
|
|
13
|
+
totalPages,
|
|
14
|
+
};
|
|
15
|
+
}
|
package/dist/payload-fallback.js
CHANGED
|
@@ -8,7 +8,7 @@ export function isPlannerDescriptionRef(value) {
|
|
|
8
8
|
if (value.includes("\\") || value.includes("\0"))
|
|
9
9
|
return false;
|
|
10
10
|
const parts = value.split("/");
|
|
11
|
-
if (parts.length <
|
|
11
|
+
if (parts.length < 3)
|
|
12
12
|
return false;
|
|
13
13
|
if (parts[0] !== ".planner" || parts[1] !== "docs")
|
|
14
14
|
return false;
|