peaks-loop 4.0.0-beta → 4.0.0-beta.3
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 +105 -87
- package/README-en.md +17 -4
- package/README.md +17 -4
- package/dist/src/cli/commands/asset-commands.d.ts +45 -0
- package/dist/src/cli/commands/asset-commands.js +404 -0
- package/dist/src/cli/commands/bee-commands.d.ts +26 -0
- package/dist/src/cli/commands/bee-commands.js +169 -0
- package/dist/src/cli/commands/{solo-commands.d.ts → code-commands.d.ts} +24 -24
- package/dist/src/cli/commands/{solo-commands.js → code-commands.js} +78 -78
- package/dist/src/cli/commands/core/skill-command.js +1 -1
- package/dist/src/cli/commands/dispatch-from-dag.js +1 -1
- package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
- package/dist/src/cli/commands/evolution-commands.js +393 -0
- package/dist/src/cli/commands/hook-handle.js +7 -7
- package/dist/src/cli/commands/job-commands.js +2 -2
- package/dist/src/cli/commands/loop-commands.d.ts +19 -13
- package/dist/src/cli/commands/loop-commands.js +147 -13
- package/dist/src/cli/commands/sediment-commands.js +9 -0
- package/dist/src/cli/commands/session-auto-compact-hook-command.js +2 -2
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
- package/dist/src/cli/commands/sub-agent-shared.d.ts +1 -1
- package/dist/src/cli/commands/user-touchpoint-commands.d.ts +4 -4
- package/dist/src/cli/commands/user-touchpoint-commands.js +14 -14
- package/dist/src/cli/commands/workflow-commands.js +22 -22
- package/dist/src/cli/program.js +23 -6
- package/dist/src/services/artifacts/repair-cycle-service.js +1 -1
- package/dist/src/services/audit/enforcers/active-skill-resolver.d.ts +1 -1
- package/dist/src/services/audit/enforcers/active-skill-resolver.js +1 -1
- package/dist/src/services/audit/enforcers/{solo-code-ban.d.ts → code-ban.d.ts} +6 -6
- package/dist/src/services/audit/enforcers/{solo-code-ban.js → code-ban.js} +6 -6
- package/dist/src/services/audit/red-line-catalog.d.ts +2 -2
- package/dist/src/services/audit/red-line-catalog.js +5 -5
- package/dist/src/services/audit/types.d.ts +2 -2
- package/dist/src/services/{solo → code}/auto-compact-orchestrator.d.ts +1 -1
- package/dist/src/services/{solo → code}/auto-compact-orchestrator.js +3 -3
- package/dist/src/services/{solo → code}/dag-orchestrator.d.ts +1 -1
- package/dist/src/services/{solo → code}/dag-orchestrator.js +1 -1
- package/dist/src/services/{solo → code}/emit-handoff.d.ts +1 -1
- package/dist/src/services/{solo → code}/emit-handoff.js +1 -1
- package/dist/src/services/{solo → code}/job-shape-decision.d.ts +1 -1
- package/dist/src/services/{solo → code}/job-shape-decision.js +5 -5
- package/dist/src/services/{solo → code}/mode-gate.d.ts +9 -9
- package/dist/src/services/{solo → code}/mode-gate.js +5 -5
- package/dist/src/services/{solo → code}/post-compact-detector.d.ts +3 -3
- package/dist/src/services/{solo → code}/post-compact-detector.js +4 -4
- package/dist/src/services/{solo → code}/step-08-gate.d.ts +4 -4
- package/dist/src/services/{solo → code}/step-08-gate.js +4 -4
- package/dist/src/services/{solo → code}/user-touchpoint-classifier.d.ts +1 -1
- package/dist/src/services/{solo → code}/user-touchpoint-classifier.js +1 -1
- package/dist/src/services/context/auto-compact-dispatcher.d.ts +2 -2
- package/dist/src/services/context/auto-compact-dispatcher.js +2 -2
- package/dist/src/services/context/auto-compact-types.d.ts +1 -1
- package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
- package/dist/src/services/crystallization/crystallization-service.js +397 -0
- package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
- package/dist/src/services/crystallization/crystallization-store.js +193 -0
- package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
- package/dist/src/services/crystallization/crystallization-types.js +299 -0
- package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
- package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
- package/dist/src/services/dispatch/slice-dag.d.ts +2 -2
- package/dist/src/services/dispatch/test-tool-detection.d.ts +1 -1
- package/dist/src/services/dispatch/test-tool-detection.js +1 -1
- package/dist/src/services/evolution/evolution-service.d.ts +137 -0
- package/dist/src/services/evolution/evolution-service.js +281 -0
- package/dist/src/services/evolution/evolution-store.d.ts +57 -0
- package/dist/src/services/evolution/evolution-store.js +232 -0
- package/dist/src/services/evolution/evolution-types.d.ts +706 -0
- package/dist/src/services/evolution/evolution-types.js +286 -0
- package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
- package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
- package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
- package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
- package/dist/src/services/feedback/feedback-promotion-service.js +2 -2
- package/dist/src/services/job/job-progress-store.d.ts +1 -1
- package/dist/src/services/job/job-progress-store.js +1 -1
- package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
- package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
- package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
- package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
- package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
- package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
- package/dist/src/services/loop/loop-release-service.d.ts +46 -0
- package/dist/src/services/loop/loop-release-service.js +66 -0
- package/dist/src/services/loop/loop-release-store.d.ts +55 -0
- package/dist/src/services/loop/loop-release-store.js +134 -0
- package/dist/src/services/loop/loop-release-types.d.ts +250 -0
- package/dist/src/services/loop/loop-release-types.js +162 -0
- package/dist/src/services/preferences/preferences-service.d.ts +1 -1
- package/dist/src/services/preferences/preferences-types.d.ts +1 -1
- package/dist/src/services/rd/standards-diagnostic.d.ts +1 -1
- package/dist/src/services/rd/standards-diagnostic.js +2 -2
- package/dist/src/services/recommendations/capability-seed-items.js +1 -1
- package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
- package/dist/src/services/recommendations/recommendation-service.js +1 -1
- package/dist/src/services/refactor/refactor-service.d.ts +1 -1
- package/dist/src/services/share/bundle-reader.d.ts +100 -0
- package/dist/src/services/share/bundle-reader.js +434 -0
- package/dist/src/services/share/bundle-types.d.ts +392 -0
- package/dist/src/services/share/bundle-types.js +318 -0
- package/dist/src/services/share/bundle-writer.d.ts +97 -0
- package/dist/src/services/share/bundle-writer.js +429 -0
- package/dist/src/services/share/run-state-contract.d.ts +133 -0
- package/dist/src/services/share/run-state-contract.js +138 -0
- package/dist/src/services/signal/cancel-handler.js +3 -3
- package/dist/src/services/skill/resume-detector.js +1 -1
- package/dist/src/services/skillhub/release-import.js +7 -2
- package/dist/src/services/skillhub/release-retain.js +6 -1
- package/dist/src/services/skillhub/sqlite-store.js +17 -1
- package/dist/src/services/skillhub/types.d.ts +10 -0
- package/dist/src/services/skills/skill-presence-service.d.ts +1 -1
- package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
- package/dist/src/services/standards/loop-engineering-lint.js +101 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
- package/dist/src/services/upgrade/1x-detector-service.js +1 -1
- package/dist/src/services/workflow/pipeline-verify-service.d.ts +1 -1
- package/dist/src/services/workflow/pipeline-verify-service.js +3 -3
- package/dist/src/services/workflow/workflow-autonomous-service.d.ts +3 -3
- package/dist/src/services/workflow/workflow-autonomous-service.js +2 -2
- package/dist/src/services/workflow/workflow-router-service.d.ts +6 -6
- package/dist/src/services/workflow/workflow-router-service.js +33 -33
- package/dist/src/services/workspace/claude-settings-template.d.ts +1 -1
- package/dist/src/services/workspace/claude-settings-template.js +5 -5
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/examples/video-demo/README.md +57 -0
- package/examples/video-demo/out/en-closing-960.png +0 -0
- package/examples/video-demo/out/zh-closing-960.png +0 -0
- package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
- package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
- package/output-styles/peaks-skill-swarm.md +3 -3
- package/package.json +6 -2
- package/skills/bee/peaks-qa/SKILL.md +1 -1
- package/skills/bee/peaks-qa/references/artifact-per-request.md +3 -3
- package/skills/bee/peaks-qa/references/qa-sub-agent-dispatch.md +6 -6
- package/skills/bee/peaks-rd/references/rd-fanout-contracts.md +1 -1
- package/skills/bee/peaks-rd/references/rd-runbook.md +1 -1
- package/skills/bee/peaks-rd/references/rd-sub-agent-dispatch.md +11 -11
- package/skills/bee/peaks-rd/references/rd-transition-gates.md +1 -1
- package/skills/bee/peaks-sc/SKILL.md +1 -1
- package/skills/bee/peaks-txt/SKILL.md +3 -3
- package/skills/bee/peaks-ui/SKILL.md +8 -8
- package/skills/peaks-code/SKILL.md +34 -21
- package/skills/peaks-code/references/anchoring-and-session-info.md +2 -2
- package/skills/peaks-code/references/artifact-contracts.md +1 -1
- package/skills/peaks-code/references/boundaries.md +3 -3
- package/skills/peaks-code/references/codegraph-orchestration.md +1 -1
- package/skills/peaks-code/references/dag-orchestrator.md +7 -7
- package/skills/peaks-code/references/external-references.md +2 -2
- package/skills/peaks-code/references/fanout-mandatory.md +3 -3
- package/skills/peaks-code/references/fast-mode.md +2 -2
- package/skills/peaks-code/references/frontend-only-mode.md +9 -9
- package/skills/peaks-code/references/job-loop.md +1 -1
- package/skills/peaks-code/references/local-artifact-workspace.md +2 -2
- package/skills/peaks-code/references/micro-cycle.md +14 -14
- package/skills/peaks-code/references/mode-selection-with-stale-presence.md +5 -5
- package/skills/peaks-code/references/mode-selection.md +3 -3
- package/skills/peaks-code/references/openspec-workflow.md +16 -16
- package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
- package/skills/peaks-code/references/quality-gate-cheatsheet.md +1 -1
- package/skills/peaks-code/references/refactor-mode.md +1 -1
- package/skills/peaks-code/references/runbook.md +15 -15
- package/skills/peaks-code/references/step-0-55-1x-detection.md +1 -1
- package/skills/peaks-code/references/step-0-8-gate.md +11 -11
- package/skills/peaks-code/references/sub-agent-dispatch.md +8 -8
- package/skills/peaks-code/references/swarm-dispatch-contract.md +17 -17
- package/skills/peaks-code/references/workflow-gates-and-types.md +2 -2
- package/skills/peaks-code/references/workflow.md +5 -5
- package/skills/peaks-content/SKILL.md +272 -0
- package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
- package/skills/peaks-resume/SKILL.md +2 -2
- package/skills/peaks-status/SKILL.md +2 -2
- package/skills/peaks-test/SKILL.md +2 -2
- /package/dist/src/services/{solo → code}/batch-heartbeat-poller.d.ts +0 -0
- /package/dist/src/services/{solo → code}/batch-heartbeat-poller.js +0 -0
- /package/dist/src/services/{solo → code}/status-line-renderer.d.ts +0 -0
- /package/dist/src/services/{solo → code}/status-line-renderer.js +0 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* peaks.bundle/1 — share-bundle format contract (spec §7A.2).
|
|
3
|
+
*
|
|
4
|
+
* M7 / spec §7A.2 / §10 RL-9.
|
|
5
|
+
*
|
|
6
|
+
* A bundle is a self-describing tar.gz whose root manifest
|
|
7
|
+
* (manifest.json) declares the format constant, the major/minor
|
|
8
|
+
* format version, the schema_version of every contained asset, the
|
|
9
|
+
* assets themselves (loop_release + related bee_release rows), the
|
|
10
|
+
* relation rows, and the evidence briefs that back the assets. The
|
|
11
|
+
* bundle excludes private run_state, `.peaks/memory/personal/`, and
|
|
12
|
+
* raw `state.db` rows.
|
|
13
|
+
*
|
|
14
|
+
* Hard rules enforced at THIS layer:
|
|
15
|
+
*
|
|
16
|
+
* - The literal constant `format_constant = "peaks.bundle/1"` is
|
|
17
|
+
* set inside the manifest at write time. The CLI is the only
|
|
18
|
+
* writer; a future format change is signaled by bumping the
|
|
19
|
+
* major field and shipping a new writer.
|
|
20
|
+
* - `format_version_major = 1` is required for any current
|
|
21
|
+
* receiver. A major-version mismatch is a HARD block at read
|
|
22
|
+
* time (the reader throws and refuses to import).
|
|
23
|
+
* - `format_version_minor` is informational; a major-compatible
|
|
24
|
+
* minor bump emits a non-fatal warning at read time.
|
|
25
|
+
* - `schema_versions` carries the canonical asset schema literal
|
|
26
|
+
* for each emitted asset: `peaks.loop/1`, `peaks.bee/1`, plus
|
|
27
|
+
* the cross-cutting `peaks.loop-bee-relation/1` and
|
|
28
|
+
* `peaks.crystallization/1`. The reader uses the values to
|
|
29
|
+
* inform a version-mismatch warning.
|
|
30
|
+
*
|
|
31
|
+
* The schema is intentionally permissive on the manifests (the
|
|
32
|
+
* manifest sub-objects are typed as `unknown` so each asset kind
|
|
33
|
+
* can validate with its own Zod schema at the service layer); the
|
|
34
|
+
* hard invariants (format constant, format_version_major, the
|
|
35
|
+
* schema_versions keys, and the inclusion/exclusion rules) are
|
|
36
|
+
* enforced here at the format boundary.
|
|
37
|
+
*
|
|
38
|
+
* On-the-wire shape (the rendered `manifest.json`):
|
|
39
|
+
*
|
|
40
|
+
* {
|
|
41
|
+
* "format_constant": "peaks.bundle/1",
|
|
42
|
+
* "format_version_major": 1,
|
|
43
|
+
* "format_version_minor": 0,
|
|
44
|
+
* "schema_versions": {
|
|
45
|
+
* "loop": "peaks.loop/1",
|
|
46
|
+
* "bee": "peaks.bee/1",
|
|
47
|
+
* "loop_bee_relation": "peaks.loop-bee-relation/1",
|
|
48
|
+
* "crystallization": "peaks.crystallization/1"
|
|
49
|
+
* },
|
|
50
|
+
* "kind": "loop" | "bee",
|
|
51
|
+
* "loop_release": <LoopRelease row or omitted for bee kind>,
|
|
52
|
+
* "bee_release": <BeeRelease row or omitted for loop kind>,
|
|
53
|
+
* "related_bee_releases": Array<BeeRelease row>,
|
|
54
|
+
* "loop_bee_relations": Array<LoopBeeRelation row>,
|
|
55
|
+
* "evidence_briefs": Array<CrystallizationEvent row>,
|
|
56
|
+
* "exclusion_manifest": { "private_run_state": "excluded",
|
|
57
|
+
* "personal_memory": "excluded",
|
|
58
|
+
* "state_db_rows": "excluded" }
|
|
59
|
+
* }
|
|
60
|
+
*
|
|
61
|
+
* Excludes (spec §7A.2 hard rules): private run_state, anything
|
|
62
|
+
* under `.peaks/memory/personal/`, raw `state.db` rows.
|
|
63
|
+
*/
|
|
64
|
+
import { z } from "zod";
|
|
65
|
+
/* ---------------------------------------------------------------------- */
|
|
66
|
+
/* Format constant + version */
|
|
67
|
+
/* ---------------------------------------------------------------------- */
|
|
68
|
+
/**
|
|
69
|
+
* The on-the-wire format constant, pinned to the literal
|
|
70
|
+
* `"peaks.bundle/1"`. The CLI is the only writer — see `bundle-writer.ts`.
|
|
71
|
+
* A future format change requires a major-version bump + a new writer.
|
|
72
|
+
*/
|
|
73
|
+
export const PEAKS_BUNDLE_FORMAT_CONSTANT = "peaks.bundle/1";
|
|
74
|
+
/**
|
|
75
|
+
* The required `format_version_major` for any current receiver.
|
|
76
|
+
* Bumped only on a breaking schema change. The reader throws when
|
|
77
|
+
* the manifest declares any value other than `1`.
|
|
78
|
+
*/
|
|
79
|
+
export const PEAKS_BUNDLE_FORMAT_VERSION_MAJOR = 1;
|
|
80
|
+
/**
|
|
81
|
+
* Default `format_version_minor`. Major-compatible minor bumps emit
|
|
82
|
+
* a soft warning at read time; they never block.
|
|
83
|
+
*/
|
|
84
|
+
export const PEAKS_BUNDLE_DEFAULT_MINOR_VERSION = 0;
|
|
85
|
+
/* ---------------------------------------------------------------------- */
|
|
86
|
+
/* Schema-version cross-reference (per asset table) */
|
|
87
|
+
/* ---------------------------------------------------------------------- */
|
|
88
|
+
/**
|
|
89
|
+
* The cross-cutting schema literals a bundle is allowed to declare.
|
|
90
|
+
* Each value must match the canonical Zod `literal(...)` literal in
|
|
91
|
+
* the corresponding type module. Used for the
|
|
92
|
+
* `SchemaVersionsMapping` enumeration below.
|
|
93
|
+
*/
|
|
94
|
+
export const PEAKS_BUNDLE_SCHEMA_VERSIONS = {
|
|
95
|
+
loop: "peaks.loop/1",
|
|
96
|
+
bee: "peaks.bee/1",
|
|
97
|
+
loop_bee_relation: "peaks.loop-bee-relation/1",
|
|
98
|
+
crystallization: "peaks.crystallization/1",
|
|
99
|
+
};
|
|
100
|
+
/* ---------------------------------------------------------------------- */
|
|
101
|
+
/* Schema-versions mapping — spec §7A.2 */
|
|
102
|
+
/* ---------------------------------------------------------------------- */
|
|
103
|
+
/**
|
|
104
|
+
* Schema-versions mapping. The writer writes the canonical literal
|
|
105
|
+
* for each asset kind it includes; the reader checks every key for
|
|
106
|
+
* presence (and that the value matches the canonical literal).
|
|
107
|
+
*
|
|
108
|
+
* `.strict()` refuses unknown keys; `.refine(...)` enforces that
|
|
109
|
+
* each value matches its canonical literal.
|
|
110
|
+
*/
|
|
111
|
+
export const SchemaVersionsMappingSchema = z
|
|
112
|
+
.object({
|
|
113
|
+
loop: z.literal(PEAKS_BUNDLE_SCHEMA_VERSIONS.loop),
|
|
114
|
+
bee: z.literal(PEAKS_BUNDLE_SCHEMA_VERSIONS.bee),
|
|
115
|
+
loop_bee_relation: z.literal(PEAKS_BUNDLE_SCHEMA_VERSIONS.loop_bee_relation),
|
|
116
|
+
crystallization: z.literal(PEAKS_BUNDLE_SCHEMA_VERSIONS.crystallization),
|
|
117
|
+
})
|
|
118
|
+
.strict();
|
|
119
|
+
/* ---------------------------------------------------------------------- */
|
|
120
|
+
/* Exclusion manifest — the explicit excludes per spec §7A.2 */
|
|
121
|
+
/* ---------------------------------------------------------------------- */
|
|
122
|
+
/**
|
|
123
|
+
* The bundle explicitly excludes private run-state, the user's
|
|
124
|
+
* personal memory directory, and raw `state.db` rows. The
|
|
125
|
+
* `ExclusionManifestSchema` is what the writer stamps into the
|
|
126
|
+
* manifest; the reader uses it as a self-declaration (the writer is
|
|
127
|
+
* the only place that can leak those payloads, but the read-time
|
|
128
|
+
* stamp lets the receiver confirm the source understood the
|
|
129
|
+
* exclusion rules).
|
|
130
|
+
*/
|
|
131
|
+
export const ExclusionManifestSchema = z
|
|
132
|
+
.object({
|
|
133
|
+
private_run_state: z.literal("excluded"),
|
|
134
|
+
personal_memory: z.literal("excluded"),
|
|
135
|
+
state_db_rows: z.literal("excluded"),
|
|
136
|
+
})
|
|
137
|
+
.strict();
|
|
138
|
+
/* ---------------------------------------------------------------------- */
|
|
139
|
+
/* Bundle kind — which asset the bundle is anchored on */
|
|
140
|
+
/* ---------------------------------------------------------------------- */
|
|
141
|
+
/**
|
|
142
|
+
* Bundle kind. A bundle is anchored on exactly one asset: either a
|
|
143
|
+
* `loop_release` (and its main bee + supporting bees) or a single
|
|
144
|
+
* `bee_release` (loop-scoped relations may follow but are not
|
|
145
|
+
* required).
|
|
146
|
+
*/
|
|
147
|
+
export const PEAKS_BUNDLE_KINDS = ["loop", "bee"];
|
|
148
|
+
/* ---------------------------------------------------------------------- */
|
|
149
|
+
/* Bundle manifest schema — the on-the-wire shape */
|
|
150
|
+
/* ---------------------------------------------------------------------- */
|
|
151
|
+
/**
|
|
152
|
+
* The full manifest schema. The asset sub-objects are typed as
|
|
153
|
+
* `unknown` here; each service layer validates them with the
|
|
154
|
+
* appropriate per-kind Zod schema (LoopReleaseSchema,
|
|
155
|
+
* BeeReleaseRow, LoopBeeRelationSchema, CrystallizationEventSchema).
|
|
156
|
+
*
|
|
157
|
+
* The hard invariants are enforced HERE:
|
|
158
|
+
* - `format_constant = "peaks.bundle/1"` literal.
|
|
159
|
+
* - `format_version_major = 1` literal (HARD block at read time
|
|
160
|
+
* on mismatch — enforced in `bundle-reader.ts`).
|
|
161
|
+
* - `schema_versions` carries every required key with the
|
|
162
|
+
* canonical literal.
|
|
163
|
+
* - `exclusion_manifest` declares the three hard excludes.
|
|
164
|
+
*/
|
|
165
|
+
export const BundleManifestSchema = z
|
|
166
|
+
.object({
|
|
167
|
+
/**
|
|
168
|
+
* The format constant. Pinned to `"peaks.bundle/1"`. A future
|
|
169
|
+
* format change is a major bump + a new constant value.
|
|
170
|
+
*/
|
|
171
|
+
format_constant: z.literal(PEAKS_BUNDLE_FORMAT_CONSTANT),
|
|
172
|
+
/**
|
|
173
|
+
* Major version. The reader requires `1`; anything else is a
|
|
174
|
+
* HARD block. Enforced at the read boundary, not here.
|
|
175
|
+
*/
|
|
176
|
+
format_version_major: z.literal(PEAKS_BUNDLE_FORMAT_VERSION_MAJOR),
|
|
177
|
+
/**
|
|
178
|
+
* Minor version. Defaults to `0`. Major-compatible bumps are a
|
|
179
|
+
* non-fatal warn at read time.
|
|
180
|
+
*/
|
|
181
|
+
format_version_minor: z.number().int().min(0).default(PEAKS_BUNDLE_DEFAULT_MINOR_VERSION),
|
|
182
|
+
/**
|
|
183
|
+
* Schema-version mapping. Every required key MUST be present
|
|
184
|
+
* with its canonical literal; unknown keys are rejected by
|
|
185
|
+
* `.strict()`.
|
|
186
|
+
*/
|
|
187
|
+
schema_versions: SchemaVersionsMappingSchema,
|
|
188
|
+
/**
|
|
189
|
+
* Anchor kind. Decides whether `loop_release` or `bee_release`
|
|
190
|
+
* is required below.
|
|
191
|
+
*/
|
|
192
|
+
kind: z.enum(PEAKS_BUNDLE_KINDS),
|
|
193
|
+
/**
|
|
194
|
+
* The loop_release row. Required when `kind === "loop"`,
|
|
195
|
+
* omitted (or absent) when `kind === "bee"`. The writer leaves
|
|
196
|
+
* it `undefined` for `bee` bundles; the JSON shape is allowed
|
|
197
|
+
* to omit it.
|
|
198
|
+
*/
|
|
199
|
+
loop_release: z.unknown().optional(),
|
|
200
|
+
/**
|
|
201
|
+
* The bee_release row. Required when `kind === "bee"`,
|
|
202
|
+
* optional for `kind === "loop"` (a loop bundle may include a
|
|
203
|
+
* main bee inline). When present, the reader uses the service
|
|
204
|
+
* layer to re-validate the row shape.
|
|
205
|
+
*/
|
|
206
|
+
bee_release: z.unknown().optional(),
|
|
207
|
+
/**
|
|
208
|
+
* Related bee_release rows for the loop kind (main + supporting
|
|
209
|
+
* + candidate + retired). Empty for `kind === "bee"`.
|
|
210
|
+
*/
|
|
211
|
+
related_bee_releases: z.array(z.unknown()).default([]),
|
|
212
|
+
/**
|
|
213
|
+
* Loop↔bee relation rows from `loop_bee_relation`. Always
|
|
214
|
+
* present (possibly empty).
|
|
215
|
+
*/
|
|
216
|
+
loop_bee_relations: z.array(z.unknown()).default([]),
|
|
217
|
+
/**
|
|
218
|
+
* Evidence briefs (crystallization_event rows) that back the
|
|
219
|
+
* bundle's assets. The receiver uses them to render the
|
|
220
|
+
* post-import crystallization prompt + a brief for any
|
|
221
|
+
* subsequent independent evaluation.
|
|
222
|
+
*/
|
|
223
|
+
evidence_briefs: z.array(z.unknown()).default([]),
|
|
224
|
+
/**
|
|
225
|
+
* Exclusion manifest — explicit declarations of the three
|
|
226
|
+
* hard excludes per spec §7A.2.
|
|
227
|
+
*/
|
|
228
|
+
exclusion_manifest: ExclusionManifestSchema,
|
|
229
|
+
})
|
|
230
|
+
.strict()
|
|
231
|
+
.refine((m) => {
|
|
232
|
+
// kind === 'loop' implies loop_release is required.
|
|
233
|
+
if (m.kind === "loop" && m.loop_release === undefined)
|
|
234
|
+
return false;
|
|
235
|
+
// kind === 'bee' implies bee_release is required.
|
|
236
|
+
if (m.kind === "bee" && m.bee_release === undefined)
|
|
237
|
+
return false;
|
|
238
|
+
return true;
|
|
239
|
+
}, {
|
|
240
|
+
message: "bundle manifest is inconsistent: kind='loop' requires loop_release; kind='bee' requires bee_release (spec §7A.2)",
|
|
241
|
+
path: [],
|
|
242
|
+
});
|
|
243
|
+
/* ---------------------------------------------------------------------- */
|
|
244
|
+
/* Validation helpers */
|
|
245
|
+
/* ---------------------------------------------------------------------- */
|
|
246
|
+
/**
|
|
247
|
+
* Strict-parse an unknown value as a BundleManifest. Throws
|
|
248
|
+
* `z.ZodError` on any failure — including:
|
|
249
|
+
* - format_constant !== "peaks.bundle/1"
|
|
250
|
+
* - format_version_major !== 1
|
|
251
|
+
* - schema_versions missing or carrying non-canonical literals
|
|
252
|
+
* - exclusion_manifest missing any of the three hard excludes
|
|
253
|
+
* - kind / anchor-mismatch (loop kind without loop_release, etc.)
|
|
254
|
+
*
|
|
255
|
+
* Note: a major-version mismatch on its own is NOT a Zod failure
|
|
256
|
+
* (the literal is enforced at the schema boundary so it is), but
|
|
257
|
+
* the `bundle-reader.ts` HARD block on major mismatch is layered on
|
|
258
|
+
* top of this parse for defense in depth (it lets the CLI emit its
|
|
259
|
+
* own specific error code without catching Zod errors).
|
|
260
|
+
*/
|
|
261
|
+
export function parseBundleManifest(input) {
|
|
262
|
+
return BundleManifestSchema.parse(input);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Safe-parse twin of `parseBundleManifest` — returns a Result-like
|
|
266
|
+
* envelope. Used by the CLI layer so a manifest-validation failure
|
|
267
|
+
* can be rendered as a structured error code rather than a thrown
|
|
268
|
+
* `ZodError`.
|
|
269
|
+
*/
|
|
270
|
+
export function safeParseBundleManifest(input) {
|
|
271
|
+
const r = BundleManifestSchema.safeParse(input);
|
|
272
|
+
if (r.success)
|
|
273
|
+
return { ok: true, manifest: r.data };
|
|
274
|
+
const findings = r.error.issues.map((i) => ({
|
|
275
|
+
path: i.path.join("."),
|
|
276
|
+
message: i.message,
|
|
277
|
+
}));
|
|
278
|
+
const joined = findings.map((f) => f.path + ":" + f.message).join("|");
|
|
279
|
+
const code = detectManifestFailureCode(joined);
|
|
280
|
+
return { ok: false, code, findings };
|
|
281
|
+
}
|
|
282
|
+
function detectManifestFailureCode(joinedIssues) {
|
|
283
|
+
if (joinedIssues.includes("format_constant")) {
|
|
284
|
+
return "BUNDLE_FORMAT_CONSTANT_MISMATCH";
|
|
285
|
+
}
|
|
286
|
+
if (joinedIssues.includes("format_version_major")) {
|
|
287
|
+
return "BUNDLE_MAJOR_VERSION_MISMATCH";
|
|
288
|
+
}
|
|
289
|
+
if (joinedIssues.includes("schema_versions")) {
|
|
290
|
+
return "BUNDLE_SCHEMA_VERSIONS_MISMATCH";
|
|
291
|
+
}
|
|
292
|
+
if (joinedIssues.includes("exclusion_manifest")) {
|
|
293
|
+
return "BUNDLE_EXCLUSION_MANIFEST_MISSING";
|
|
294
|
+
}
|
|
295
|
+
return "BUNDLE_KIND_ANCHOR_MISMATCH";
|
|
296
|
+
}
|
|
297
|
+
/* ---------------------------------------------------------------------- */
|
|
298
|
+
/* Hard-block error code consts */
|
|
299
|
+
/* ---------------------------------------------------------------------- */
|
|
300
|
+
/**
|
|
301
|
+
* Error code string consts. Centralised here so the writer + reader
|
|
302
|
+
* share a single source of truth for error codes; the CLI layer
|
|
303
|
+
* only needs to render them.
|
|
304
|
+
*/
|
|
305
|
+
export const SHARE_BUNDLE_ERROR_CODES = {
|
|
306
|
+
/** Major-version mismatch at read time — HARD block. */
|
|
307
|
+
MAJOR_VERSION_MISMATCH: "SHARE_BUNDLE_MAJOR_VERSION_MISMATCH",
|
|
308
|
+
/** Schema-version mapping is missing or carries non-canonical literals. */
|
|
309
|
+
SCHEMA_VERSIONS_MISMATCH: "SHARE_BUNDLE_SCHEMA_VERSIONS_MISMATCH",
|
|
310
|
+
/** Format constant is not the pinned "peaks.bundle/1". */
|
|
311
|
+
FORMAT_CONSTANT_MISMATCH: "SHARE_BUNDLE_FORMAT_CONSTANT_MISMATCH",
|
|
312
|
+
/** Source release has `shareable === false` — HARD block at write time. */
|
|
313
|
+
NOT_SHAREABLE: "SHARE_BUNDLE_NOT_SHAREABLE",
|
|
314
|
+
/** Receiver asked to land as `stable` (forbidden — bundles always land as candidate). */
|
|
315
|
+
IMPORT_TO_STABLE_FORBIDDEN: "SHARE_BUNDLE_IMPORT_TO_STABLE_FORBIDDEN",
|
|
316
|
+
/** Bundle tarball is malformed (missing manifest, bad payload). */
|
|
317
|
+
BUNDLE_MALFORMED: "SHARE_BUNDLE_MALFORMED",
|
|
318
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bundle-writer.ts — writeBundle(loopOrBeeId, outPath) (spec §7A.2).
|
|
3
|
+
*
|
|
4
|
+
* M7 / spec §7A.2 / §10 RL-9.
|
|
5
|
+
*
|
|
6
|
+
* Writes a `peaks.bundle/1` tar.gz that captures:
|
|
7
|
+
*
|
|
8
|
+
* - One anchor asset: a loop_release (kind='loop') OR a single
|
|
9
|
+
* bee_release (kind='bee'). A loop bundle additionally carries
|
|
10
|
+
* related_bee_releases (all loop↔bee relations resolved) and
|
|
11
|
+
* loop_bee_relations rows.
|
|
12
|
+
* - All evidence_briefs (crystallization_event rows) that
|
|
13
|
+
* reference the anchor (created_loop_release_id /
|
|
14
|
+
* updated_loop_release_id / created_bee_release_id /
|
|
15
|
+
* updated_bee_release_id).
|
|
16
|
+
*
|
|
17
|
+
* Hard rules enforced at THIS layer:
|
|
18
|
+
*
|
|
19
|
+
* - The source release MUST have `shareable !== false`. A
|
|
20
|
+
* `shareable=false` source THROWS
|
|
21
|
+
* `SHARE_BUNDLE_NOT_SHAREABLE` BEFORE the tarball is written.
|
|
22
|
+
* The CLI layer is the canonical gate (per spec §7A.2 /
|
|
23
|
+
* §10 RL-9); the writer enforces the same gate at the
|
|
24
|
+
* service boundary for defense in depth.
|
|
25
|
+
* - The bundle NEVER captures private run_state, the personal
|
|
26
|
+
* `.peaks/memory/personal/` directory, or raw `state.db`
|
|
27
|
+
* rows. The exclusion is declared in the manifest's
|
|
28
|
+
* `exclusion_manifest` field; physically, the writer only
|
|
29
|
+
* pulls rows from the structured tables.
|
|
30
|
+
* - The bundle is a tarball whose root contains `manifest.json`,
|
|
31
|
+
* `relations.json`, `evidence_briefs/*.json`, and
|
|
32
|
+
* `blobs/<sha256>` content-addressed blobs (mirroring the
|
|
33
|
+
* SkillHub release pattern).
|
|
34
|
+
*
|
|
35
|
+
* The writer runs `tar -czf <outPath> -C <stageDir> .` exactly the
|
|
36
|
+
* same way `release-export.ts` does — same layout, same tar
|
|
37
|
+
* invocation, so the `bundle-reader.ts` symmetrical side can
|
|
38
|
+
* extract via `runTar(['-xzf', inPath, '-C', stageDir])` with no
|
|
39
|
+
* extra plumbing.
|
|
40
|
+
*/
|
|
41
|
+
import type Database from "better-sqlite3";
|
|
42
|
+
import { SHARE_BUNDLE_ERROR_CODES, type PeaksBundleKind } from "./bundle-types.js";
|
|
43
|
+
/**
|
|
44
|
+
* Inputs to `writeBundle`. `kind` decides which asset table the
|
|
45
|
+
* `id` resolves against; the writer throws on unknown assets and
|
|
46
|
+
* on `shareable=false` sources.
|
|
47
|
+
*/
|
|
48
|
+
export type WriteBundleArgs = {
|
|
49
|
+
db: Database.Database;
|
|
50
|
+
/** Blobs root for content-addressed file lookup. */
|
|
51
|
+
blobsDir: string;
|
|
52
|
+
/** Bundle kind — `loop` or `bee`. */
|
|
53
|
+
kind: PeaksBundleKind;
|
|
54
|
+
/** The asset id — loop id (kebab-case) for `kind:'loop'`, integer bee_release.id for `kind:'bee'`. */
|
|
55
|
+
id: string | number;
|
|
56
|
+
/** Output `.tar.gz` path. */
|
|
57
|
+
outPath: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Thrown when the source release has `shareable === false`. The
|
|
61
|
+
* writer throws BEFORE any tarball work; the CLI layer surfaces
|
|
62
|
+
* `code = SHARE_BUNDLE_NOT_SHAREABLE`.
|
|
63
|
+
*/
|
|
64
|
+
export declare class BundleNotShareableError extends Error {
|
|
65
|
+
readonly code: typeof SHARE_BUNDLE_ERROR_CODES.NOT_SHAREABLE;
|
|
66
|
+
constructor(message: string);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Thrown when the writer cannot locate the source asset (loop id
|
|
70
|
+
* not present in `loop_release`, or bee_release.id not present).
|
|
71
|
+
* Includes both `LOOP_NOT_FOUND` and `BEE_NOT_FOUND` flavors —
|
|
72
|
+
* both fall under `BUNDLE_ASSET_NOT_FOUND` for the CLI envelope.
|
|
73
|
+
*/
|
|
74
|
+
export declare class BundleAssetNotFoundError extends Error {
|
|
75
|
+
readonly code: "BUNDLE_ASSET_NOT_FOUND";
|
|
76
|
+
readonly assetKind: PeaksBundleKind;
|
|
77
|
+
readonly assetId: string | number;
|
|
78
|
+
constructor(assetKind: PeaksBundleKind, assetId: string | number);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Write a `peaks.bundle/1` tar.gz to `outPath`. The bundle
|
|
82
|
+
* captures ONE anchor asset (`loop` or `bee`) plus its relations,
|
|
83
|
+
* supporting bees (loop kind only), and evidence briefs.
|
|
84
|
+
*
|
|
85
|
+
* Hard blocks raised at THIS layer:
|
|
86
|
+
*
|
|
87
|
+
* - `BundleNotShareableError`: the source has `shareable === false`.
|
|
88
|
+
* - `BundleAssetNotFoundError`: the source id was not present in the table.
|
|
89
|
+
*
|
|
90
|
+
* On success the call returns the resolved asset id and kind; the
|
|
91
|
+
* CLI layer uses this to render a one-line status.
|
|
92
|
+
*/
|
|
93
|
+
export declare function writeBundle(args: WriteBundleArgs): {
|
|
94
|
+
outPath: string;
|
|
95
|
+
kind: PeaksBundleKind;
|
|
96
|
+
assetId: string | number;
|
|
97
|
+
};
|