jg-plans 0.1.0 → 0.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.
- package/CHANGELOG.md +20 -0
- package/README.md +8 -8
- package/api/README.md +75 -12
- package/cli/README.md +24 -6
- package/dist/cli/arguments.js +18 -3
- package/dist/cli/commands.js +76 -17
- package/dist/cli/types.d.ts +3 -1
- package/dist/documents/fingerprints.d.ts +19 -0
- package/dist/documents/fingerprints.js +56 -0
- package/dist/documents/index.d.ts +2 -1
- package/dist/documents/index.js +1 -0
- package/dist/documents/milestones.js +44 -33
- package/dist/documents/plan.js +33 -68
- package/dist/documents/types.d.ts +22 -0
- package/dist/documents/utilities.d.ts +16 -2
- package/dist/documents/utilities.js +105 -4
- package/dist/edits/index.d.ts +2 -0
- package/dist/edits/index.js +2 -1
- package/dist/edits/preparations.d.ts +30 -0
- package/dist/edits/preparations.js +159 -0
- package/dist/edits/types.d.ts +14 -0
- package/dist/edits/utilities.d.ts +1 -0
- package/dist/edits/utilities.js +9 -2
- package/dist/errors/constants.d.ts +3 -1
- package/dist/errors/constants.js +4 -0
- package/dist/files/documents.d.ts +46 -0
- package/dist/files/documents.js +176 -0
- package/dist/files/index.d.ts +3 -1
- package/dist/files/index.js +2 -0
- package/dist/files/locks.d.ts +16 -0
- package/dist/files/locks.js +127 -0
- package/dist/files/mutations.d.ts +7 -3
- package/dist/files/mutations.js +32 -83
- package/dist/files/types.d.ts +19 -5
- package/dist/files/utilities.d.ts +4 -4
- package/dist/files/utilities.js +24 -7
- package/dist/index.d.ts +10 -8
- package/dist/index.js +5 -4
- package/dist/protocol/index.d.ts +4 -4
- package/dist/protocol/index.js +2 -2
- package/dist/protocol/types.d.ts +63 -0
- package/dist/protocol/types.js +53 -1
- package/docs/getting-started.md +4 -4
- package/docs/integrations.md +14 -14
- package/errors/README.md +6 -4
- package/examples/library.mjs +34 -2
- package/package.json +4 -3
- package/protocol/0.1/README.md +8 -2
package/errors/README.md
CHANGED
|
@@ -10,17 +10,19 @@ Document-format diagnostics are observations. They are separate from the operati
|
|
|
10
10
|
| UNSAFE_EDIT | JG_PLANS_UNSAFE_EDIT | The requested edit is unsupported or ambiguous | Unsupported affected YAML/marker structure, selector ambiguity, or invalid spans; nothing is written. |
|
|
11
11
|
| DESTINATION_EXISTS | JG_PLANS_DESTINATION_EXISTS | The plan destination already exists | Exclusive creation refuses an existing path. |
|
|
12
12
|
| SOURCE_CHANGED | JG_PLANS_SOURCE_CHANGED | The document changed before replacement | A prior-content comparison observed different bytes; no retry occurs. |
|
|
13
|
-
| WRITE_FAILED | JG_PLANS_WRITE_FAILED | The plan document could not be written | Creation or
|
|
13
|
+
| WRITE_FAILED | JG_PLANS_WRITE_FAILED | The plan document could not be written | Creation, replacement, or removal failed; inspect any cleanupFailedPaths. |
|
|
14
|
+
| LOCK_BUSY | JG_PLANS_LOCK_BUSY | The plan document is locked | Immediate participating-writer contention, including dead owners; no automatic recovery. |
|
|
15
|
+
| LOCK_FAILED | JG_PLANS_LOCK_FAILED | The plan document lock operation failed | Canonicalization/acquisition/release failed; release can follow durable writes. |
|
|
14
16
|
|
|
15
|
-
parsePlan, parseMilestones, checkPlan, and inspectPlan can throw INVALID_INPUT for incompatible operation arguments. Inspection returns file failures as diagnostics rather than throwing away another readable document.
|
|
17
|
+
parsePlan, parseMilestones, checkPlan, and inspectPlan can throw INVALID_INPUT for incompatible operation arguments. Inspection returns file failures as diagnostics rather than throwing away another readable document. Pure preparation can throw INVALID_INPUT, UNSUPPORTED_ENCODING, UNSAFE_EDIT, and SOURCE_CHANGED. createPlan adds DESTINATION_EXISTS/WRITE_FAILED and lock errors. updatePlan/writePlanDocument add READ_FAILED/WRITE_FAILED and lock errors. removeMilestones uses INVALID_INPUT, READ_FAILED, UNSUPPORTED_ENCODING, SOURCE_CHANGED, WRITE_FAILED, and lock errors. withPlanDocumentLocks validates arguments and reports lock failures while propagating callback errors after successful release. Mutation failures exit 2 in the CLI.
|
|
16
18
|
|
|
17
19
|
Stable messages exclude user text. Internal causes may retain detailed provider errors and are never emitted by the CLI. Public error.data may contain a safe provider/unsupported-edit reason, an affected core field, or cleanupFailedPaths. For example, unsupported-metadata-value means an affected scalar uses an unsupported form, and noncanonical-id-insertion means a new ID cannot be inserted after a canonical status marker. Reason details refine the stable operational code; they do not quote source. Failed JSON parsing also omits the unsafe syntax-error cause.
|
|
18
20
|
|
|
19
|
-
Failed creation cleans only still-recognizable owned partial files and its empty plan directory. If user edits or I/O failures prevent that cleanup, paths are reported without deleting intervening content. The selected storage root can remain empty.
|
|
21
|
+
Failed creation cleans only still-recognizable owned partial files and its empty plan directory. If user edits or I/O failures prevent that cleanup, paths are reported without deleting intervening content. The selected storage root can remain empty. Existing-target guards never recreate deleted documents. Explicit write operations can replace the selected body/source; they do not recover history. The [API](../api/README.md) documents conservative YAML forms and shared local locks. Acquisition failures report mutationOutcome not-applied. Release failures report operationCompleted and mutationOutcome uncertain if the callback started; inspect durable state before retrying. Internal AggregateError causes retain callback/release failures. Locks are not automatically recovered.
|
|
20
22
|
|
|
21
23
|
## Document diagnostics
|
|
22
24
|
|
|
23
|
-
- Plan structure: MISSING_FRONTMATTER, UNTERMINATED_FRONTMATTER, INVALID_YAML, YAML_WARNING, YAML_VALUE_UNAVAILABLE, METADATA_NOT_MAPPING, MISSING_METADATA_FIELD, INVALID_METADATA_FIELD.
|
|
25
|
+
- Plan structure: MISSING_FRONTMATTER, UNTERMINATED_FRONTMATTER, INVALID_YAML, YAML_WARNING, YAML_VALUE_UNAVAILABLE, METADATA_NOT_MAPPING, MISSING_METADATA_FIELD, INVALID_METADATA_FIELD, FINGERPRINT_UNAVAILABLE.
|
|
24
26
|
- Availability: MISSING_PLAN, MISSING_MILESTONES, ORPHAN_MILESTONES, UNREADABLE_DOCUMENT, FILE_TOO_LARGE, INVALID_ENCODING.
|
|
25
27
|
- Milestones: NO_MILESTONES, INVALID_ORDINAL, NONSEQUENTIAL_ORDINAL, DUPLICATE_ORDINAL, EMPTY_MILESTONE_TITLE, MISSING_STATUS, EMPTY_STATUS, DUPLICATE_STATUS, MISPLACED_STATUS, DUPLICATE_ID_MARKER, INVALID_MILESTONE_ID, DUPLICATE_ID, MISPLACED_ID, AMBIGUOUS_OVERVIEW, OVERVIEW_MISMATCH.
|
|
26
28
|
|
package/examples/library.mjs
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
checkPlan,
|
|
6
|
+
createPlan,
|
|
7
|
+
inspectPlan,
|
|
8
|
+
updatePlan,
|
|
9
|
+
writePlanDocument,
|
|
10
|
+
removeMilestones,
|
|
11
|
+
preparePlanDocumentWrite,
|
|
12
|
+
} from 'jg-plans';
|
|
5
13
|
|
|
6
14
|
// This example owns a temporary root. Never recursively remove a user's planning root.
|
|
7
15
|
const root = await mkdtemp(join(tmpdir(), 'jg-plans-example-'));
|
|
@@ -12,18 +20,42 @@ try {
|
|
|
12
20
|
body: '# A small change\n\nKeep the intent close to the work.\n',
|
|
13
21
|
milestones: '## Milestone 1: Implement\n**Status:** pending\n',
|
|
14
22
|
});
|
|
15
|
-
//
|
|
23
|
+
// A consumer journal stores exact prepared source/IDs once, then replays those bytes.
|
|
24
|
+
const prepared = preparePlanDocumentWrite(created.milestones.source, {
|
|
25
|
+
document: 'milestones',
|
|
26
|
+
expectedSha256: created.milestones.sha256,
|
|
27
|
+
source: created.milestones.source,
|
|
28
|
+
assignMissingIds: true,
|
|
29
|
+
});
|
|
30
|
+
const written = await writePlanDocument(created.directory, {
|
|
31
|
+
document: 'milestones',
|
|
32
|
+
expectedSha256: created.milestones.sha256,
|
|
33
|
+
source: prepared.source,
|
|
34
|
+
});
|
|
16
35
|
await updatePlan(created.directory, {
|
|
17
36
|
document: 'milestones',
|
|
37
|
+
expectedSha256: written.sha256,
|
|
18
38
|
changes: [{ select: { ordinal: 1 }, set: { status: 'done' } }],
|
|
19
39
|
});
|
|
20
40
|
const observed = await inspectPlan(created.directory);
|
|
41
|
+
// Body/core metadata can also be replaced together using the observed digest.
|
|
42
|
+
if (observed.plan.state === 'readable')
|
|
43
|
+
await writePlanDocument(created.directory, {
|
|
44
|
+
document: 'plan',
|
|
45
|
+
expectedSha256: observed.plan.sha256,
|
|
46
|
+
body: observed.plan.value.body,
|
|
47
|
+
set: { revision: 2 },
|
|
48
|
+
});
|
|
21
49
|
const result = checkPlan({
|
|
22
50
|
...(observed.plan.state === 'readable' ? { plan: observed.plan.value.source } : {}),
|
|
23
51
|
...(observed.milestones.state === 'readable'
|
|
24
52
|
? { milestones: observed.milestones.value.source }
|
|
25
53
|
: {}),
|
|
26
54
|
});
|
|
55
|
+
if (observed.milestones.state === 'readable')
|
|
56
|
+
await removeMilestones(created.directory, {
|
|
57
|
+
expectedSha256: observed.milestones.sha256,
|
|
58
|
+
});
|
|
27
59
|
console.log(JSON.stringify({ conforms: result.conforms, diagnostics: result.diagnostics }));
|
|
28
60
|
} finally {
|
|
29
61
|
await rm(root, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jg-plans",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A compact planning protocol for people and coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -49,7 +49,6 @@
|
|
|
49
49
|
"@eslint/js": "10.0.1",
|
|
50
50
|
"@types/node": "24.10.1",
|
|
51
51
|
"eslint": "10.12.0",
|
|
52
|
-
"jg-crypto": "0.3.0",
|
|
53
52
|
"jg-fetch": "0.5.0",
|
|
54
53
|
"prettier": "3.8.3",
|
|
55
54
|
"prettier-plugin-astro": "1.1.1",
|
|
@@ -71,9 +70,11 @@
|
|
|
71
70
|
"tailwindStylesheet": "./website/src/styles/global.css"
|
|
72
71
|
},
|
|
73
72
|
"dependencies": {
|
|
73
|
+
"jg-crypto": "0.3.0",
|
|
74
74
|
"jg-exception": "1.7.0",
|
|
75
|
-
"jg-fs": "1.
|
|
75
|
+
"jg-fs": "1.7.0",
|
|
76
76
|
"jg-process": "1.6.1",
|
|
77
|
+
"jg-utilities": "1.7.0",
|
|
77
78
|
"yaml": "2.9.1",
|
|
78
79
|
"zod": "4.6.7"
|
|
79
80
|
},
|
package/protocol/0.1/README.md
CHANGED
|
@@ -89,6 +89,12 @@ An optional Overview table with Milestone, Name, and Status columns is derived f
|
|
|
89
89
|
|
|
90
90
|
Caller-supplied milestone source remains verbatim. A caller generating that source follows writer rules; nonconforming supplied source receives diagnostics rather than automatic normalization. Updating a recognizable misplaced marker may preserve its location with a diagnostic; it does not claim to have repaired conformance.
|
|
91
91
|
|
|
92
|
+
## Source observations
|
|
93
|
+
|
|
94
|
+
Optional milestone frontmatter is a project-owned mapping; it does not require the plan's five preferred fields. Readers preserve it and exclude it from Markdown heading/marker scanning. Both document kinds retain complete original source, including BOM and line endings. The reference library exposes preamble and heading/body ranges, milestone heading ends, and recognized Overview table ranges so consumers can retain requirements outside numbered milestone bodies.
|
|
95
|
+
|
|
96
|
+
Exact-byte document hashes and optional structural fingerprints are library observations, not protocol approval fields. Structural fingerprints cover exact body text and raw metadata after explicitly requested top-level exclusions; the generic default excludes nothing. Unavailable structure is reported without discarding useful text or inferring authority. Consumer profiles choose their own policy.
|
|
97
|
+
|
|
92
98
|
## Revisions, history, and deletion
|
|
93
99
|
|
|
94
100
|
For substantive agent revisions, recommend a short inline summary explaining actual scope changes and preserving known progress. Do not silently reset completed work to pending.
|
|
@@ -101,13 +107,13 @@ Inspection explicitly distinguishes a missing plan, missing milestone file, orph
|
|
|
101
107
|
|
|
102
108
|
## Reference mutation boundary
|
|
103
109
|
|
|
104
|
-
The
|
|
110
|
+
The reference library supports creation, narrow core-metadata/marker patches, guarded plan-body/core-metadata replacement, complete milestone-source replacement with explicit missing-ID assignment, and guarded milestone removal. Pure preparation supplies exact output for consumer persistence. It never remaps progress, normalizes unrelated extension fields, maintains a snapshot service, or migrates repositories.
|
|
105
111
|
|
|
106
112
|
For existing documents, preserve the original bytes outside the exact requested values or inserted field/marker lines, including unknown data, comments, whitespace, BOM, Unicode, CRLF, and final-newline state. Decode UTF-8 strictly and map character positions to original byte spans correctly. Unsupported or ambiguous affected YAML, unsupported encoding, invalid UTF-8, or unencodable replacement text leaves that file unchanged with a specific failure.
|
|
107
113
|
|
|
108
114
|
A malformed plan must not prevent independent milestone observations or an unambiguous marker edit. Update does not recreate a missing/deleted target. Creation never overwrites an existing destination.
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
Library and CLI filesystem mutations share short local document locks, acquired in plan-then-milestones order and released in reverse. The public lock callback allows consumers to prepare and persist under that same namespace. Busy/dead owners fail immediately; recovery is an explicit operator decision. Atomic replacement and byte guards detect observed changes, but nonparticipating editors retain a comparison-to-replacement/deletion race. No cross-document transaction, automatic retry, or completion inference is supplied. See the [API](../../api/README.md#shared-document-locks) for lock names and uncertain release outcomes.
|
|
111
117
|
|
|
112
118
|
## Consumer-owned policy
|
|
113
119
|
|