peaks-loop 4.0.0-beta.20 → 4.0.0-beta.21
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 +84 -10
- package/dist/cli/commands/preferences-commands.js +23 -3
- package/dist/cli/commands/statusline-commands.d.ts +12 -0
- package/dist/cli/commands/statusline-commands.js +40 -16
- package/dist/services/standards/missing-standards-detector.d.ts +25 -0
- package/dist/services/standards/missing-standards-detector.js +43 -12
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,22 +5,96 @@
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
7
|
- Updated dependencies
|
|
8
|
-
- peaks-loop-shared@0.0.
|
|
9
|
-
- peaks-loop-audit-independent@0.0.
|
|
10
|
-
- peaks-loop-crystallization@0.0.
|
|
11
|
-
- peaks-loop-doctor@0.0.
|
|
12
|
-
- peaks-loop-final-review@0.0.
|
|
8
|
+
- peaks-loop-shared@0.0.15
|
|
9
|
+
- peaks-loop-audit-independent@0.0.11
|
|
10
|
+
- peaks-loop-crystallization@0.0.12
|
|
11
|
+
- peaks-loop-doctor@0.0.11
|
|
12
|
+
- peaks-loop-final-review@0.0.11
|
|
13
13
|
|
|
14
14
|
## 4.0.0
|
|
15
15
|
|
|
16
16
|
### Patch Changes
|
|
17
17
|
|
|
18
18
|
- Updated dependencies
|
|
19
|
-
- peaks-loop-shared@0.0.
|
|
20
|
-
- peaks-loop-audit-independent@0.0.
|
|
21
|
-
- peaks-loop-crystallization@0.0.
|
|
22
|
-
- peaks-loop-doctor@0.0.
|
|
23
|
-
- peaks-loop-final-review@0.0.
|
|
19
|
+
- peaks-loop-shared@0.0.15
|
|
20
|
+
- peaks-loop-audit-independent@0.0.11
|
|
21
|
+
- peaks-loop-crystallization@0.0.12
|
|
22
|
+
- peaks-loop-doctor@0.0.11
|
|
23
|
+
- peaks-loop-final-review@0.0.11
|
|
24
|
+
|
|
25
|
+
## 4.0.0-beta.21 — 2026-07-22 (ice-cola surface-check fixes, republish)
|
|
26
|
+
|
|
27
|
+
This release is the **republish** after the accidental 4.0.2
|
|
28
|
+
publish earlier on 2026-07-22. The 4.0.2 manifest is being
|
|
29
|
+
unpublished (`npm unpublish --force`, within 72h window). The
|
|
30
|
+
intended release is `4.0.0-beta.21`, the version that was
|
|
31
|
+
manually pinned but the publish workflow's `pnpm exec changeset
|
|
32
|
+
version` step overrode it to `4.0.2` due to a pending
|
|
33
|
+
`.changeset/*.md` in the tagged commit.
|
|
34
|
+
|
|
35
|
+
### Bug fixes
|
|
36
|
+
|
|
37
|
+
- **standardsMissing UX (`fix(standards)`)** — `peaks workspace init`
|
|
38
|
+
previously reported `standardsMissing.missing: true` with the
|
|
39
|
+
remediation text "no project-local standards found" whenever the
|
|
40
|
+
language overlay was empty, even when common was clearly populated
|
|
41
|
+
(ice-cola shape: common/\*.md + typescript overlay populated, but
|
|
42
|
+
no javascript/ dir). The detector now distinguishes three states
|
|
43
|
+
(`complete` / `common-missing` / `language-missing`) and the
|
|
44
|
+
remediation text calls out the precise failing component.
|
|
45
|
+
|
|
46
|
+
- **`peaks statusline` default action (`fix(statusline)`)** — `peaks
|
|
47
|
+
statusline` (no subcommand) was documented as "Run with no
|
|
48
|
+
subcommand to render" but commander was printing usage instead of
|
|
49
|
+
dispatching to the hidden `render` subcommand. The fix attaches
|
|
50
|
+
a default `.action(...)` on the parent `statusline` command that
|
|
51
|
+
delegates to a public `runDefaultStatuslineRender` body, and adds
|
|
52
|
+
`--project <path>` to the parent so the default path inherits the
|
|
53
|
+
project label.
|
|
54
|
+
|
|
55
|
+
- **release-pack test version pinning (`fix(release-tests)`)** —
|
|
56
|
+
five `tests/unit/release/*.test.ts` files hard-coded `'4.0.0-beta.17'`
|
|
57
|
+
and `'0.0.4'` literals. Root bumping from 4.0.0-beta.17 to
|
|
58
|
+
4.0.0-beta.20 made three tests fail immediately, demonstrating the
|
|
59
|
+
tests were carrying version knowledge the production code does not.
|
|
60
|
+
Expectations now derive from the on-disk `package.json` instead,
|
|
61
|
+
so future version bumps are a no-op for the suite.
|
|
62
|
+
|
|
63
|
+
- **`peaks preferences` unknown-key error (`fix(preferences)`)** —
|
|
64
|
+
the prior error was `PREFERENCES_KEY_UNKNOWN: <key>` which forced
|
|
65
|
+
the operator to look up valid keys elsewhere. All three sites
|
|
66
|
+
(`get` / `set` / `reset`) now throw via a shared `unknownKeyError`
|
|
67
|
+
helper that includes the sorted `ALLOWED_KEYS_LIST` inline.
|
|
68
|
+
|
|
69
|
+
### Chore
|
|
70
|
+
|
|
71
|
+
- **`chore(deps)`** — Migrate `onlyBuiltDependencies: [better-sqlite3]`
|
|
72
|
+
out of `package.json#pnpm` (no longer read by pnpm 10.11+) into
|
|
73
|
+
`.npmrc` as the canonical pnpm config key. Silences the per-package
|
|
74
|
+
`WARN The "pnpm" field in package.json is no longer read by pnpm`
|
|
75
|
+
log line without changing install behavior.
|
|
76
|
+
|
|
77
|
+
### CI
|
|
78
|
+
|
|
79
|
+
- **`ci(publish)`** — Add `workflow_dispatch` input
|
|
80
|
+
`skip_changeset_version` to `.github/workflows/publish.yml`. When
|
|
81
|
+
set, the conditional `pnpm exec changeset version` step is
|
|
82
|
+
skipped, so manual version pins in `package.json` survive the
|
|
83
|
+
registry-repair release path.
|
|
84
|
+
|
|
85
|
+
- **`ci(unpublish)`** — One-shot `unpublish-4-0-2` workflow that
|
|
86
|
+
uses Trusted Publishing + OIDC to remove peaks-loop@4.0.2 + 8
|
|
87
|
+
subpackages. Triggered by `gh workflow run` with
|
|
88
|
+
`confirm_destructive=yes-i-am-sure`. Retired (kept for audit)
|
|
89
|
+
once the unpublish completes (npm 72h propagation).
|
|
90
|
+
|
|
91
|
+
### Validation
|
|
92
|
+
|
|
93
|
+
- `vitest tests/unit/standards/missing-standards-detector.test.ts` — 18/18
|
|
94
|
+
- `vitest tests/unit/cli/commands/statusline-default-render.test.ts` — 3/3
|
|
95
|
+
- `vitest tests/unit/release` — 20/20
|
|
96
|
+
- `vitest tests/integration/preferences-cli.test.ts` — 5/5
|
|
97
|
+
- `PEAKS_DRY_RUN=1 node scripts/release-pack.mjs` — 9/9 packages, zero WARN
|
|
24
98
|
|
|
25
99
|
## 4.0.0-beta.17
|
|
26
100
|
|
|
@@ -12,6 +12,26 @@ const ALLOWED_KEYS = new Set([
|
|
|
12
12
|
'swarmSpeculative',
|
|
13
13
|
'loopAutonomousEnabled',
|
|
14
14
|
]);
|
|
15
|
+
/**
|
|
16
|
+
* Stable, sorted list of allowed preference keys. Used in error messages
|
|
17
|
+
* so a PREFERENCES_KEY_UNKNOWN throw is self-documenting (the operator
|
|
18
|
+
* sees exactly which keys are valid without reading the source).
|
|
19
|
+
*/
|
|
20
|
+
const ALLOWED_KEYS_LIST = Array.from(ALLOWED_KEYS).sort();
|
|
21
|
+
/**
|
|
22
|
+
* Build a PREFERENCES_KEY_UNKNOWN error with the allowed-keys list baked
|
|
23
|
+
* in. Throwing a plain Error here is the legacy path that the CLI
|
|
24
|
+
* surfaces verbatim on stderr; the helper exists so all three sites
|
|
25
|
+
* (`get` / `set` / `reset`) emit the same operator-facing message.
|
|
26
|
+
*
|
|
27
|
+
* Stage-3 follow-up (ice-cola surface check 2026-07-22, follow-on to
|
|
28
|
+
* report item 5.3): previously the message was just `PREFERENCES_KEY_UNKNOWN:
|
|
29
|
+
* <key>` which forced the operator to look up valid keys elsewhere. The
|
|
30
|
+
* new message lists the valid keys inline so the response is actionable.
|
|
31
|
+
*/
|
|
32
|
+
function unknownKeyError(key) {
|
|
33
|
+
return new Error(`PREFERENCES_KEY_UNKNOWN: ${key}. Allowed keys: ${ALLOWED_KEYS_LIST.join(', ')}.`);
|
|
34
|
+
}
|
|
15
35
|
export function registerPreferencesCommands(program) {
|
|
16
36
|
const prefs = program
|
|
17
37
|
.command('preferences')
|
|
@@ -25,7 +45,7 @@ export function registerPreferencesCommands(program) {
|
|
|
25
45
|
.action((opts) => {
|
|
26
46
|
try {
|
|
27
47
|
if (!ALLOWED_KEYS.has(opts.key)) {
|
|
28
|
-
throw
|
|
48
|
+
throw unknownKeyError(opts.key);
|
|
29
49
|
}
|
|
30
50
|
const all = loadPreferences(opts.project);
|
|
31
51
|
const value = all[opts.key];
|
|
@@ -71,7 +91,7 @@ export function registerPreferencesCommands(program) {
|
|
|
71
91
|
.action((opts) => {
|
|
72
92
|
try {
|
|
73
93
|
if (!ALLOWED_KEYS.has(opts.key)) {
|
|
74
|
-
throw
|
|
94
|
+
throw unknownKeyError(opts.key);
|
|
75
95
|
}
|
|
76
96
|
let parsed = opts.value;
|
|
77
97
|
try {
|
|
@@ -106,7 +126,7 @@ export function registerPreferencesCommands(program) {
|
|
|
106
126
|
.action((opts) => {
|
|
107
127
|
try {
|
|
108
128
|
if (!ALLOWED_KEYS.has(opts.key)) {
|
|
109
|
-
throw
|
|
129
|
+
throw unknownKeyError(opts.key);
|
|
110
130
|
}
|
|
111
131
|
const filePath = preferencesPath(opts.project);
|
|
112
132
|
// Read raw on-disk state (not the merged view) so removing a key
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { type ProgramIO } from '../cli-helpers.js';
|
|
3
|
+
type RenderOptions = {
|
|
4
|
+
project?: string;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Default-statusline render body. Reused by both the top-level default
|
|
9
|
+
* action (Bug-02 dispatch) and the explicit `render` subcommand. Exported
|
|
10
|
+
* so a unit test can exercise the JSON / text output paths without going
|
|
11
|
+
* through commander.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runDefaultStatuslineRender(options: RenderOptions, io: ProgramIO): Promise<void>;
|
|
3
14
|
export declare function registerStatusLineCommands(program: Command, io: ProgramIO): void;
|
|
15
|
+
export {};
|
|
@@ -54,6 +54,26 @@ function resolveIdeForCommand(options, projectRoot) {
|
|
|
54
54
|
}
|
|
55
55
|
return detectIdeFromContext({ env: process.env, cwd: projectRoot ?? process.cwd(), parsedStdin: null });
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Default-statusline render body. Reused by both the top-level default
|
|
59
|
+
* action (Bug-02 dispatch) and the explicit `render` subcommand. Exported
|
|
60
|
+
* so a unit test can exercise the JSON / text output paths without going
|
|
61
|
+
* through commander.
|
|
62
|
+
*/
|
|
63
|
+
export async function runDefaultStatuslineRender(options, io) {
|
|
64
|
+
const raw = await readStdin();
|
|
65
|
+
const stdin = parseStatusLineStdin(raw);
|
|
66
|
+
const seeded = options.project
|
|
67
|
+
? { ...(stdin ?? {}), workspace: { current_dir: options.project } }
|
|
68
|
+
: stdin;
|
|
69
|
+
const model = buildStatusLineModel(seeded, Date.now());
|
|
70
|
+
const text = renderStatusLine(model);
|
|
71
|
+
if (options.json === true) {
|
|
72
|
+
io.stdout(JSON.stringify({ ok: true, command: 'statusline.render', data: { text } }, null, 2));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
io.stdout(text);
|
|
76
|
+
}
|
|
57
77
|
export function registerStatusLineCommands(program, io) {
|
|
58
78
|
// Top-level `peaks statusline` — register as a group with subcommands
|
|
59
79
|
// (install | uninstall | status). When the user runs `peaks statusline` with
|
|
@@ -65,27 +85,31 @@ export function registerStatusLineCommands(program, io) {
|
|
|
65
85
|
// option-shadowing bug.
|
|
66
86
|
const statusline = addJsonOption(program
|
|
67
87
|
.command('statusline')
|
|
68
|
-
.description('Render the Peaks skill status line for the current session, or manage the adapter-driven statusLine entry. Run with no subcommand to render; with a subcommand (install | uninstall | status) to manage.')
|
|
69
|
-
|
|
70
|
-
// `peaks statusline` with no
|
|
71
|
-
//
|
|
88
|
+
.description('Render the Peaks skill status line for the current session, or manage the adapter-driven statusLine entry. Run with no subcommand to render; with a subcommand (install | uninstall | status) to manage.')
|
|
89
|
+
.option('--project <path>', 'project root path (used to label the status line when stdin is absent; applies to the default render path)'));
|
|
90
|
+
// Default behavior: when the user types `peaks statusline` with no
|
|
91
|
+
// subcommand, render the status line. Without this default action,
|
|
92
|
+
// commander falls back to printing usage (Bug-02, ice-cola surface check
|
|
93
|
+
// 2026-07-22). The hidden `render` subcommand is preserved so callers
|
|
94
|
+
// can still invoke it explicitly.
|
|
95
|
+
//
|
|
96
|
+
// Note (commander 12.x): when both a top-level `.action(...)` and
|
|
97
|
+
// subcommands exist, commander's option parser can conflate parent and
|
|
98
|
+
// child flags. We therefore parse `process.argv` for the bare `statusline`
|
|
99
|
+
// invocation here, and otherwise let the subcommand machinery handle the
|
|
100
|
+
// rest. The implementation is wrapped in `peekDefaultStatuslineRender` so
|
|
101
|
+
// it can be exercised in isolation by unit tests.
|
|
102
|
+
statusline.action(async (_parentOptions, command) => {
|
|
103
|
+
await runDefaultStatuslineRender(command.opts(), io);
|
|
104
|
+
});
|
|
105
|
+
// Hidden render subcommand. Preserved for callers that want to invoke
|
|
106
|
+
// render explicitly without going through the default-action dispatch.
|
|
72
107
|
statusline
|
|
73
108
|
.command('render', { hidden: true })
|
|
74
109
|
.description('Render the Peaks skill status line for the current session (reads session JSON on stdin; honors --project for the project label).')
|
|
75
110
|
.option('--project <path>', 'project root path (used to label the status line when stdin is absent)')
|
|
76
111
|
.action(async (options) => {
|
|
77
|
-
|
|
78
|
-
const stdin = parseStatusLineStdin(raw);
|
|
79
|
-
const seeded = options.project
|
|
80
|
-
? { ...(stdin ?? {}), workspace: { current_dir: options.project } }
|
|
81
|
-
: stdin;
|
|
82
|
-
const model = buildStatusLineModel(seeded, Date.now());
|
|
83
|
-
const text = renderStatusLine(model);
|
|
84
|
-
if (options.json === true) {
|
|
85
|
-
io.stdout(JSON.stringify({ ok: true, command: 'statusline.render', data: { text } }, null, 2));
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
io.stdout(text);
|
|
112
|
+
await runDefaultStatuslineRender(options, io);
|
|
89
113
|
});
|
|
90
114
|
addJsonOption(statusline
|
|
91
115
|
.command('install')
|
|
@@ -42,6 +42,31 @@ export type MissingProjectStandardsDiagnostic = {
|
|
|
42
42
|
readonly remediation: string;
|
|
43
43
|
readonly language: StandardsLanguage;
|
|
44
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* List which standards tree components are missing vs populated.
|
|
47
|
+
*
|
|
48
|
+
* Returns one of three stable shapes:
|
|
49
|
+
* - { kind: 'complete' } — both common + language overlay populated
|
|
50
|
+
* - { kind: 'common-missing' } — common dir absent/empty (universal)
|
|
51
|
+
* - { kind: 'language-missing', language } — common ok, language overlay absent/empty
|
|
52
|
+
*
|
|
53
|
+
* The detector previously returned a single boolean that flipped to
|
|
54
|
+
* "missing: true" the moment the language overlay was empty, but printed
|
|
55
|
+
* the remediation as if BOTH common AND language were missing — a UX bug
|
|
56
|
+
* that surfaced in ice-cola (common=4 .md files; typescript=1 .md file;
|
|
57
|
+
* javascript overlay absent → label said "no project-local standards found"
|
|
58
|
+
* even though common was clearly populated). This split lets the CLI emit
|
|
59
|
+
* a precise remediation string per kind.
|
|
60
|
+
*/
|
|
61
|
+
export type StandardsTreeDiagnostic = {
|
|
62
|
+
readonly kind: 'complete';
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'common-missing';
|
|
65
|
+
} | {
|
|
66
|
+
readonly kind: 'language-missing';
|
|
67
|
+
readonly language: StandardsLanguage;
|
|
68
|
+
};
|
|
69
|
+
export declare function diagnoseStandardsTree(projectRoot: string, language: StandardsLanguage): StandardsTreeDiagnostic;
|
|
45
70
|
/**
|
|
46
71
|
* Detect whether a consumer project's `.peaks/standards/` tree (2.0
|
|
47
72
|
* canonical) is missing or empty.
|
|
@@ -62,6 +62,26 @@ function hasPopulatedMarkdown(dir) {
|
|
|
62
62
|
const entries = readdirSync(dir);
|
|
63
63
|
return entries.some((entry) => entry.toLowerCase().endsWith('.md'));
|
|
64
64
|
}
|
|
65
|
+
export function diagnoseStandardsTree(projectRoot, language) {
|
|
66
|
+
if (!SUPPORTED_LANGUAGES.has(language)) {
|
|
67
|
+
throw new Error(`Unsupported standards language: ${String(language)}`);
|
|
68
|
+
}
|
|
69
|
+
const normalizedRoot = normalizeProjectRoot(projectRoot);
|
|
70
|
+
const commonDir = join(normalizedRoot, '.peaks', 'standards', 'common');
|
|
71
|
+
const languageDir = language === 'generic'
|
|
72
|
+
? null
|
|
73
|
+
: join(normalizedRoot, '.peaks', 'standards', language);
|
|
74
|
+
const commonOk = hasPopulatedMarkdown(commonDir);
|
|
75
|
+
const languageOk = languageDir === null ? true : hasPopulatedMarkdown(languageDir);
|
|
76
|
+
if (commonOk && languageOk) {
|
|
77
|
+
return { kind: 'complete' };
|
|
78
|
+
}
|
|
79
|
+
if (!commonOk) {
|
|
80
|
+
return { kind: 'common-missing' };
|
|
81
|
+
}
|
|
82
|
+
// common ok, language overlay empty/missing
|
|
83
|
+
return { kind: 'language-missing', language };
|
|
84
|
+
}
|
|
65
85
|
/**
|
|
66
86
|
* Detect whether a consumer project's `.peaks/standards/` tree (2.0
|
|
67
87
|
* canonical) is missing or empty.
|
|
@@ -84,18 +104,29 @@ export function detectMissingProjectStandards(projectRoot, language) {
|
|
|
84
104
|
}
|
|
85
105
|
const normalizedRoot = normalizeProjectRoot(projectRoot);
|
|
86
106
|
const renderedPath = renderForPlatform(normalizedRoot);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
const diagnostic = diagnoseStandardsTree(projectRoot, language);
|
|
108
|
+
// Bug-01 fix (ice-cola surface check 2026-07-22): the previous
|
|
109
|
+
// remediation said "no project-local standards found" whenever EITHER
|
|
110
|
+
// common or the language overlay was empty, which misrepresented
|
|
111
|
+
// projects that have common populated but a missing language overlay
|
|
112
|
+
// (e.g. ice-cola has common/*.md + typescript/coding-style.md but no
|
|
113
|
+
// javascript/coding-style.md). The remediation now distinguishes the
|
|
114
|
+
// three kinds so the operator gets a precise hint.
|
|
115
|
+
let missing;
|
|
116
|
+
let remediation;
|
|
117
|
+
if (diagnostic.kind === 'complete') {
|
|
118
|
+
missing = false;
|
|
119
|
+
remediation = `Project-local standards already present at ${renderedPath}. Re-run \`peaks standards init --project ${normalizedRoot} --apply\` to refresh from the curated baseline.`;
|
|
120
|
+
}
|
|
121
|
+
else if (diagnostic.kind === 'common-missing') {
|
|
122
|
+
missing = true;
|
|
123
|
+
remediation = `⚠ no project-local common standards at ${renderedPath} — run \`peaks standards init --project ${normalizedRoot} --apply\` to scaffold (language: ${language}), or pass --init-standards to peaks workspace init for one-shot auto-apply.`;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
missing = true;
|
|
127
|
+
const overlayName = diagnostic.language;
|
|
128
|
+
remediation = `⚠ common standards present at ${renderedPath}\\common but ${overlayName} language overlay is missing — run \`peaks standards init --project ${normalizedRoot} --apply\` to scaffold the ${overlayName} overlay (or pass --init-standards to peaks workspace init for one-shot auto-apply).`;
|
|
129
|
+
}
|
|
99
130
|
return {
|
|
100
131
|
missing,
|
|
101
132
|
path: renderedPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peaks-loop",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.21",
|
|
4
4
|
"description": "Loop Engineering CLI — workflow primitive / loop guards / evaluators / slice orchestration",
|
|
5
5
|
"author": "SquabbyZ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
"headroom-ai": "0.22.4",
|
|
55
55
|
"yaml": "^2.9.0",
|
|
56
56
|
"zod": "^3.25.76",
|
|
57
|
-
"peaks-loop-
|
|
58
|
-
"peaks-loop-
|
|
59
|
-
"peaks-loop-
|
|
60
|
-
"peaks-loop-
|
|
61
|
-
"peaks-loop-
|
|
62
|
-
"peaks-loop-
|
|
63
|
-
"peaks-loop-shared
|
|
64
|
-
"peaks-loop-shared": "0.0.
|
|
57
|
+
"peaks-loop-crystallization": "0.0.11",
|
|
58
|
+
"peaks-loop-audit-independent": "0.0.10",
|
|
59
|
+
"peaks-loop-doctor": "0.0.10",
|
|
60
|
+
"peaks-loop-final-review": "0.0.10",
|
|
61
|
+
"peaks-loop-mut": "0.1.0",
|
|
62
|
+
"peaks-loop-job-snapshot": "0.0.5",
|
|
63
|
+
"peaks-loop-shared": "0.0.14",
|
|
64
|
+
"peaks-loop-shared-channel": "0.0.5"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@alibaba-group/open-code-review": "1.3.1"
|