@mediadatafusion/pi-workflow-suite 0.0.13 → 0.0.15
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 +18 -0
- package/README.md +9 -9
- package/VERSION +1 -1
- package/extensions/workflow-model-router.ts +4 -4
- package/extensions/workflow-modes.ts +29 -7
- package/package.json +4 -2
- package/scripts/prepare-package-readme.mjs +15 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable public releases will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.0.15] - 2026-06-09
|
|
6
|
+
|
|
7
|
+
### Improved
|
|
8
|
+
|
|
9
|
+
- Improved Plan Mode approval handoffs so approval-ready plans remain visible while action menus are open.
|
|
10
|
+
- Refined the Deep Plan preset so reviewer review remains available without automatically starting by default.
|
|
11
|
+
- Improved workflow recovery around transient connection interruptions so Plan, Mission, and Standard workflows are easier to resume after short transport failures.
|
|
12
|
+
|
|
13
|
+
### Hardened
|
|
14
|
+
|
|
15
|
+
- Expanded regression coverage for reviewer routing, sub-agent handoffs, package command surfaces, and interruption recovery.
|
|
16
|
+
|
|
17
|
+
## [0.0.14] - 2026-06-08
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Restored the npm/pi.dev publish preparation path so the package-safe README is active before npm publish starts, preserving the rendered package README while keeping media pinned to the published `0.0.12` assets.
|
|
22
|
+
|
|
5
23
|
## [0.0.13] - 2026-06-08
|
|
6
24
|
|
|
7
25
|
### Changed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](#installation) [](#quick-start) [](#core-commands) [](#settings-reference)
|
|
6
6
|
|
|
7
|
-
**Workflow Suite Version:** `v0.0.
|
|
7
|
+
**Workflow Suite Version:** `v0.0.15`
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
@@ -578,15 +578,15 @@ Mission: approval-gated, auto-run after approval, standard planning, milestone v
|
|
|
578
578
|
|
|
579
579
|
Deep — Careful
|
|
580
580
|
Plan: deep, asks clarification for non-trivial work
|
|
581
|
-
Review: automatic
|
|
582
|
-
Validation: automatic
|
|
581
|
+
Review: manual/optional; not automatic before execution
|
|
582
|
+
Validation: automatic after execution
|
|
583
583
|
Sub-agents: forced larger teams across planning/execution/repair/review/validation
|
|
584
584
|
Mission: deep planning with final validation
|
|
585
585
|
|
|
586
586
|
Maximum — Thorough
|
|
587
587
|
Plan: maximum
|
|
588
588
|
Review: automatic
|
|
589
|
-
Validation: automatic
|
|
589
|
+
Validation: automatic after execution
|
|
590
590
|
Sub-agents: forced maximum teams across planning/execution/repair/review/validation
|
|
591
591
|
Mission: supervised auto, final validation, higher retry budget
|
|
592
592
|
```
|
|
@@ -1007,8 +1007,8 @@ pi install -l npm:@mediadatafusion/pi-workflow-suite
|
|
|
1007
1007
|
### Installing specific versions
|
|
1008
1008
|
|
|
1009
1009
|
```bash
|
|
1010
|
-
pi install npm:@mediadatafusion/pi-workflow-suite@0.0.
|
|
1011
|
-
pi install -l npm:@mediadatafusion/pi-workflow-suite@0.0.
|
|
1010
|
+
pi install npm:@mediadatafusion/pi-workflow-suite@0.0.15
|
|
1011
|
+
pi install -l npm:@mediadatafusion/pi-workflow-suite@0.0.15
|
|
1012
1012
|
```
|
|
1013
1013
|
|
|
1014
1014
|
An unversioned install follows normal update behavior: `pi update` and `pi update --extensions` will pick up new package releases. A versioned install pins the package to that version. Pinned package specs are intentionally skipped by Pi's normal package update commands. To move a pinned install to a newer version, reinstall with the desired version. To switch back to latest tracking, use the unversioned install command without `@<version>`.
|
|
@@ -1214,10 +1214,10 @@ See `docs/TROUBLESHOOTING.md` for detailed diagnostics.
|
|
|
1214
1214
|
|
|
1215
1215
|
## Versioning
|
|
1216
1216
|
|
|
1217
|
-
The current preparation version is `v0.0.
|
|
1217
|
+
The current preparation version is `v0.0.15`. Version information is intentionally aligned across:
|
|
1218
1218
|
|
|
1219
|
-
- `VERSION` (`v0.0.
|
|
1220
|
-
- `package.json` (`0.0.
|
|
1219
|
+
- `VERSION` (`v0.0.15`),
|
|
1220
|
+
- `package.json` (`0.0.15`),
|
|
1221
1221
|
- `package-lock.json`,
|
|
1222
1222
|
- this README,
|
|
1223
1223
|
- Workflow Suite settings/about output.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.0.
|
|
1
|
+
v0.0.15
|
|
@@ -956,9 +956,9 @@ export function builtInWorkflowPresets(): Record<string, WorkflowPresetBundle> {
|
|
|
956
956
|
},
|
|
957
957
|
deep: {
|
|
958
958
|
displayName: "Deep",
|
|
959
|
-
description: "Careful end-to-end workflow for risky or codebase-heavy work with stronger clarification, automatic
|
|
959
|
+
description: "Careful end-to-end workflow for risky or codebase-heavy work with stronger clarification, manual Plan review, automatic validation, final mission validation, and larger worker teams.",
|
|
960
960
|
planning: { depth: "deep", clarificationMode: "always_for_nontrivial", maxClarificationQuestions: 5, interactiveClarificationEnabled: true, clarificationQualityGate: true, useSubagentsBeforeClarification: true },
|
|
961
|
-
workflow: { offerReviewerBeforeExecute: false, autoRunReviewerBeforeExecute:
|
|
961
|
+
workflow: { offerReviewerBeforeExecute: false, autoRunReviewerBeforeExecute: false, offerValidationAfterExecute: true, autoRunValidationAfterExecute: true, validateAfterExecution: true, requirePlanApprovalBeforeExecute: false, requireApprovalBeforeExecution: false, autoRepairReviewFailures: true, autoRepairValidationFailures: true, reviewRetryMode: "safe_only", validationRetryMode: "safe_only", maxReviewRetriesPerPlan: 3, maxReviewRetriesPerWorkflow: 6, maxValidationRetriesPerPlan: 3, maxValidationRetriesPerWorkflow: 6, pauseAfterReviewFailure: false, pauseAfterValidationFailure: false, planProgressEnabled: true, planRuntimeEnabled: true, planShowProgressBar: true },
|
|
962
962
|
standard: { enabled: true, autoTodoEnabled: true, todoProgressVisible: true, todoTriggerMode: "auto", clarificationEnabled: true, clarificationMode: "auto", maxClarificationQuestions: 2, interactiveClarificationEnabled: true, clarificationTiming: "after_initial_analysis", clarificationQualityGate: true, allowClarificationWithoutAnalysis: false, useSubagentsBeforeClarification: true, allowSubagents: true, subagentScope: "user", subagents: { planningPolicy: "forced", executionPolicy: "forced", repairPolicy: "forced", reviewPolicy: "forced", validationPolicy: "forced", autoUseDuringPlanning: true, autoUseDuringExecution: true, autoUseDuringRepair: true, autoUseDuringReview: true, autoUseDuringValidation: true, minPlanningWorkersForDeep: 2, minPlanningWorkersForMaximum: 2, minExecutionWorkersForDeep: 3, minExecutionWorkersForMaximum: 3, minRepairWorkersForDeep: 2, minRepairWorkersForMaximum: 2, minReviewWorkersForDeep: 3, minReviewWorkersForMaximum: 3, minValidationWorkersForDeep: 3, minValidationWorkersForMaximum: 3 }, statusWidgetVisible: true, useSharedExecutorModel: true, useStandardSpecificModels: false, modelRole: "executor" },
|
|
963
963
|
missions: { defaultAutonomy: "approval_gated", requireValidationPerMilestone: true, autoRunAfterApproval: true, continueAcrossMilestones: true, pauseBetweenMilestones: false, clarificationMode: "always_for_nontrivial", maxClarificationQuestions: 5, planningDepth: "deep", useSubagentsBeforeClarification: true, autoRepairReviewFailures: true, reviewRetryMode: "safe_only", maxReviewRetriesPerMission: 3, autoRepairValidationFailures: true, validationRetryMode: "safe_only", maxValidationRetriesPerMilestone: 3, maxValidationRetriesPerMission: 8, finalValidationEnabled: true, autoRepairFinalValidationFailures: true, maxFinalValidationRetries: 2, subagentPolicy: "forced", minWorkersForDeep: 3, minWorkersForMaximum: 3 },
|
|
964
964
|
subagents: { planningPolicy: "forced", executionPolicy: "forced", repairPolicy: "forced", reviewPolicy: "forced", validationPolicy: "forced", autoUseDuringPlanning: true, autoUseDuringExecution: true, autoUseDuringRepair: true, autoUseDuringReview: true, autoUseDuringValidation: true, minPlanningWorkersForDeep: 3, minPlanningWorkersForMaximum: 3, minExecutionWorkersForDeep: 3, minExecutionWorkersForMaximum: 3, minRepairWorkersForDeep: 2, minRepairWorkersForMaximum: 2, minReviewWorkersForDeep: 3, minReviewWorkersForMaximum: 3, minValidationWorkersForDeep: 3, minValidationWorkersForMaximum: 3, allowBackgroundSubagents: true },
|
|
@@ -1077,7 +1077,7 @@ export function workflowPresetPickerLabel(name: string, preset?: WorkflowPresetB
|
|
|
1077
1077
|
const summaries: Record<string, string> = {
|
|
1078
1078
|
simple: "fast autonomous validation, low repair retries, 1-worker phases",
|
|
1079
1079
|
standard: "balanced autonomous validation and safe repair",
|
|
1080
|
-
deep: "careful
|
|
1080
|
+
deep: "careful manual review, autonomous validation, and final mission validation",
|
|
1081
1081
|
maximum: "maximum autonomous rigor with bounded aggressive repair",
|
|
1082
1082
|
};
|
|
1083
1083
|
return summaries[name] ? `${title} — ${summaries[name]}` : title;
|
|
@@ -1122,7 +1122,7 @@ export function workflowPresetMeaningLines(name: string, preset?: WorkflowPreset
|
|
|
1122
1122
|
"Purpose: higher-rigor built-in profile for broad, risky, or codebase-heavy work that still should not stall unnecessarily.",
|
|
1123
1123
|
"Applies to: Standard Mode, Plan Mode, Mission Mode, and shared sub-agent intensity.",
|
|
1124
1124
|
"Standard Mode: requires a To Do for substantive work, uses stronger clarification, resumes automatically after answers, and uses deeper Standard worker coverage.",
|
|
1125
|
-
"Plan Mode: uses deep planning, clarifies non-trivial work, avoids a second execution-approval stop after the initial approval,
|
|
1125
|
+
"Plan Mode: uses deep planning, clarifies non-trivial work, avoids a second execution-approval stop after the initial approval, leaves review manual/optional, runs validation automatically, and retries safe repairs.",
|
|
1126
1126
|
"Mission Mode: starts after approval, auto-runs after approval, continues milestones without pause, keeps milestone validation on, and enables final comprehensive validation.",
|
|
1127
1127
|
"Shared sub-agents: forces larger teams across planning, execution, repair, review, and validation.",
|
|
1128
1128
|
"Does not change: models/providers/API keys/auth/session/runtime state/shared compaction settings.",
|
|
@@ -1750,7 +1750,7 @@ ${requiredSubagentPreflightSection(options.preflightBlock)}
|
|
|
1750
1750
|
|
|
1751
1751
|
${subagentCapabilityTable()}
|
|
1752
1752
|
|
|
1753
|
-
${priorPlan ? `Current draft/approved plan to revise:\n${priorPlan}\n\n` : ""}${feedbackBlock}${options.forceClarification ? `CLARIFICATION IS REQUIRED BEFORE FINAL PLANNING. Reason: ${options.forceReason ?? "always_for_nontrivial classified this as non-trivial"}\nYour job in this turn is to perform lightweight task analysis, then generate only high-value clarification questions from the actual task. Do not produce an implementation plan in this turn. ${subagentsBeforeClarification ? "If planning depth/policy calls for it and sub-agent use is available, use read-only planning/research sub-agents before asking clarification so the questions are context-aware." : "Do not call sub-agents in this clarification-generation turn unless forced by sub-agent policy."} Do not use generic reusable workflow boilerplate questions.\n\n` : ""}${options.qualityGateFeedback ? `The previous clarification output failed the clarification quality gate: ${options.qualityGateFeedback}\nRegenerate better task-specific clarification questions${options.forceClarification ? ". Do not produce a final plan in this retry." : ", or use PLAN_DECISION: plan if no high-value question exists."}\n\n` : ""}MANDATORY STRUCTURED HANDOFF: Before your final response, call workflow_plan_result with decision=clarify, plan, or blocked. The tool payload is the primary control plane
|
|
1753
|
+
${priorPlan ? `Current draft/approved plan to revise:\n${priorPlan}\n\n` : ""}${feedbackBlock}${options.forceClarification ? `CLARIFICATION IS REQUIRED BEFORE FINAL PLANNING. Reason: ${options.forceReason ?? "always_for_nontrivial classified this as non-trivial"}\nYour job in this turn is to perform lightweight task analysis, then generate only high-value clarification questions from the actual task. Do not produce an implementation plan in this turn. ${subagentsBeforeClarification ? "If planning depth/policy calls for it and sub-agent use is available, use read-only planning/research sub-agents before asking clarification so the questions are context-aware." : "Do not call sub-agents in this clarification-generation turn unless forced by sub-agent policy."} Do not use generic reusable workflow boilerplate questions.\n\n` : ""}${options.qualityGateFeedback ? `The previous clarification output failed the clarification quality gate: ${options.qualityGateFeedback}\nRegenerate better task-specific clarification questions${options.forceClarification ? ". Do not produce a final plan in this retry." : ", or use PLAN_DECISION: plan if no high-value question exists."}\n\n` : ""}MANDATORY STRUCTURED HANDOFF: Before your final response, call workflow_plan_result with decision=clarify, plan, or blocked. The tool payload is the primary control plane. After workflow_plan_result returns, print the user-facing markdown for that decision and stop: the approval-ready # Implementation Plan for decision=plan, the clarification questions for decision=clarify, or the blocker summary for decision=blocked. If workflow_plan_result is unavailable, output the parser-safe PLAN_DECISION fallback once and STOP immediately; do not call subagent as an acknowledgement, do not retry invalid tool names, and do not continue analysis after the fallback.
|
|
1754
1754
|
|
|
1755
1755
|
LEGACY FALLBACK: Your VERY FIRST LINE must be exactly one of:
|
|
1756
1756
|
${options.forceClarification ? "PLAN_DECISION: clarify" : "PLAN_DECISION: clarify\nPLAN_DECISION: plan"}
|
|
@@ -13742,6 +13742,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
13742
13742
|
showMissionPlanMenuFallback("Mission plan menu was skipped because the active mission state changed.");
|
|
13743
13743
|
return;
|
|
13744
13744
|
}
|
|
13745
|
+
showMissionPlanReadyCard(mission);
|
|
13745
13746
|
if (!ctx.hasUI) return;
|
|
13746
13747
|
const reviewChoice = ["PASS", "NOTES"].includes(mission.reviewerVerdict ?? "") ? [] : ["Review Mission Plan"];
|
|
13747
13748
|
const choices = mission.autonomy === "manual" || mission.autonomy === "approval_gated"
|
|
@@ -13750,6 +13751,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
13750
13751
|
const choice = await ctx.ui.select("Mission plan ready. Choose next action:", choices);
|
|
13751
13752
|
if (!choice) {
|
|
13752
13753
|
updateState({ mode: "mission_plan_ready", activeMissionId: mission.id, task: mission.goal, originalTask: mission.goal, draftPlan: mission.planText }, ctx);
|
|
13754
|
+
showMissionPlanMenuFallback("Mission plan menu was dismissed. The mission plan remains ready.");
|
|
13753
13755
|
return recordWorkflowInternalEvent(ctx, `Mission plan menu dismissed: ${mission.id}`);
|
|
13754
13756
|
}
|
|
13755
13757
|
if (choice === "Review Mission Plan") {
|
|
@@ -13785,12 +13787,31 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
13785
13787
|
show(pi, `# Mission Plan Ready\n\n${reason}\n\nUse one of:\n- \`/mission review\`\n- \`/mission approve\`\n- \`/mission revise <feedback>\`\n- \`/mission cancel\``);
|
|
13786
13788
|
}
|
|
13787
13789
|
|
|
13790
|
+
function showMissionPlanReadyCard(mission: MissionState): void {
|
|
13791
|
+
const planText = mission.planText?.trim() ? mission.planText : "(none recorded)";
|
|
13792
|
+
show(pi, `# Mission Plan Ready\n\n${planText}\n\nChoose an action in the Mission menu, or use:\n- \`/mission review\`\n- \`/mission approve\`\n- \`/mission revise <feedback>\`\n- \`/mission cancel\``);
|
|
13793
|
+
}
|
|
13794
|
+
|
|
13788
13795
|
// ── Menus ──────────────────────────────────────────────────────
|
|
13789
13796
|
|
|
13790
13797
|
function showPlanMenuCommandFallback(reason: string): void {
|
|
13791
13798
|
show(pi, `# Plan Ready\n\n${reason}\n\nUse one of:\n- \`/plan approve\`\n- \`/plan revise <feedback>\`\n- \`/plan cancel\``);
|
|
13792
13799
|
}
|
|
13793
13800
|
|
|
13801
|
+
function showPlanReadyForApprovalCard(snapshot: WorkflowHandoffSnapshot, options: { includePlanText?: boolean } = {}): void {
|
|
13802
|
+
const planText = snapshot.draftPlan?.trim()
|
|
13803
|
+
? snapshot.draftPlan
|
|
13804
|
+
: state.draftPlan?.trim()
|
|
13805
|
+
? state.draftPlan
|
|
13806
|
+
: state.approvedPlan?.trim()
|
|
13807
|
+
? state.approvedPlan
|
|
13808
|
+
: "(none recorded)";
|
|
13809
|
+
const body = options.includePlanText === true
|
|
13810
|
+
? `${planText}\n\nChoose an action in the approval menu, or use:`
|
|
13811
|
+
: "Choose an action in the approval menu. The native plan above is the source of truth, and the saved plan remains recoverable with:";
|
|
13812
|
+
show(pi, `# Plan Ready For Approval\n\n${body}\n- \`/plan approve\`\n- \`/plan revise <feedback>\`\n- \`/plan cancel\``);
|
|
13813
|
+
}
|
|
13814
|
+
|
|
13794
13815
|
function showPlanClarificationFallback(reason: string, questions?: ClarificationQuestion[]): void {
|
|
13795
13816
|
const rendered = questions?.length ? `\n\n${renderClarificationQuestionsForUser(questions)}` : "";
|
|
13796
13817
|
show(pi, `# Clarification Needed\n\n${reason}${rendered}\n\nAnswer with: /clarify answer 1A 2C\nSkip with: /clarify answer 1S\nCustom answer: /clarify answer 3D: your text`);
|
|
@@ -13845,9 +13866,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
13845
13866
|
return;
|
|
13846
13867
|
}
|
|
13847
13868
|
if (!ctx.hasUI) {
|
|
13848
|
-
|
|
13869
|
+
showPlanReadyForApprovalCard(snapshot, { includePlanText: true });
|
|
13849
13870
|
return;
|
|
13850
13871
|
}
|
|
13872
|
+
showPlanReadyForApprovalCard(snapshot);
|
|
13851
13873
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
13852
13874
|
const approveLabel = settings.models.reviewer.enabled ? "Approve and Run Workflow" : "Approve and Execute";
|
|
13853
13875
|
let menuChoice: string | undefined;
|
|
@@ -13857,6 +13879,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
13857
13879
|
showPlanMenuCommandFallback(`Interactive approval menu failed to open: ${error instanceof Error ? error.message : String(error)}`);
|
|
13858
13880
|
return;
|
|
13859
13881
|
}
|
|
13882
|
+
if (!menuChoice) {
|
|
13883
|
+
updateState({ mode: "plan_draft", activePlanId: snapshot.activePlanId ?? state.activePlanId, draftPlan: snapshot.draftPlan ?? state.draftPlan, task: snapshot.task ?? state.task }, ctx);
|
|
13884
|
+
showPlanMenuCommandFallback("Plan approval menu was dismissed. The plan remains ready for approval.");
|
|
13885
|
+
return;
|
|
13886
|
+
}
|
|
13860
13887
|
if (menuChoice === "Approve and Execute" || menuChoice === "Approve and Run Workflow") {
|
|
13861
13888
|
await approveCurrentPlan(ctx, "plan approved by user");
|
|
13862
13889
|
} else if (menuChoice === "Revise Plan") {
|
|
@@ -17432,11 +17459,6 @@ Public workflow commands:
|
|
|
17432
17459
|
else if (isMissionWorkflowMode(state)) updateState({ missionTokensUsed: (state.missionTokensUsed ?? 0) + turnTokens }, ctx);
|
|
17433
17460
|
}
|
|
17434
17461
|
|
|
17435
|
-
if (initialPlanParentSuppressed()) {
|
|
17436
|
-
traceWorkflowTracking(ctx, "typed-initial-plan-parent-message-suppressed", { mode: state.mode, lifecycleStatus: state.planProgress?.lifecycleStatus });
|
|
17437
|
-
return { message: { ...message, content: [{ type: "text" as const, text: "" }] } };
|
|
17438
|
-
}
|
|
17439
|
-
|
|
17440
17462
|
if (planReviewParentSuppressed()) {
|
|
17441
17463
|
traceWorkflowTracking(ctx, "typed-plan-review-parent-message-suppressed", { mode: state.mode, lifecycleStatus: state.planProgress?.lifecycleStatus });
|
|
17442
17464
|
return { message: { ...message, content: [{ type: "text" as const, text: "" }] } };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mediadatafusion/pi-workflow-suite",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Structured workflow orchestration suite for Pi with Standard, Plan, Mission, compaction, diagrams, web access, repo lock, and safety gates.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -114,7 +114,9 @@
|
|
|
114
114
|
"prepack": "node scripts/prepare-package-readme.mjs apply",
|
|
115
115
|
"postpack": "node scripts/prepare-package-readme.mjs restore --pack",
|
|
116
116
|
"restore:package-readme": "node scripts/prepare-package-readme.mjs restore",
|
|
117
|
-
"
|
|
117
|
+
"prepare:publish-readme": "node scripts/prepare-package-readme.mjs apply --publish && node scripts/prepare-package-readme.mjs check",
|
|
118
|
+
"cleanup:publish-readme": "node scripts/prepare-package-readme.mjs restore",
|
|
119
|
+
"prepublishOnly": "node scripts/prepare-package-readme.mjs ensure-publish-ready",
|
|
118
120
|
"postpublish": "node scripts/prepare-package-readme.mjs restore --publish",
|
|
119
121
|
"check:package-readme": "node scripts/prepare-package-readme.mjs check"
|
|
120
122
|
}
|
|
@@ -106,11 +106,25 @@ function check() {
|
|
|
106
106
|
assertPackageReadme(readFileSync(readmePath, 'utf8'));
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
function ensurePublishReady() {
|
|
110
|
+
check();
|
|
111
|
+
if (!existsSync(publishMarkerPath)) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
[
|
|
114
|
+
'package README is package-safe but publish marker is missing.',
|
|
115
|
+
'Run `npm run prepare:publish-readme` before `npm publish --access public` so npm sees the package README before publish starts.',
|
|
116
|
+
'If a previous publish failed, run `npm run cleanup:publish-readme` first.',
|
|
117
|
+
].join(' '),
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
109
122
|
const command = process.argv[2];
|
|
110
123
|
if (command === 'apply') apply();
|
|
111
124
|
else if (command === 'restore') restore();
|
|
112
125
|
else if (command === 'check') check();
|
|
126
|
+
else if (command === 'ensure-publish-ready') ensurePublishReady();
|
|
113
127
|
else {
|
|
114
|
-
console.error('Usage: prepare-package-readme.mjs apply|restore|check [--publish|--pack]');
|
|
128
|
+
console.error('Usage: prepare-package-readme.mjs apply|restore|check|ensure-publish-ready [--publish|--pack]');
|
|
115
129
|
process.exit(1);
|
|
116
130
|
}
|