@oss-autopilot/core 3.13.1 → 3.13.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/dist/cli.bundle.cjs +85 -85
- package/dist/cli.js +14 -0
- package/dist/commands/daily.js +9 -0
- package/dist/commands/dashboard-data.js +4 -1
- package/dist/commands/list-move-tier.js +11 -1
- package/dist/core/auth.js +33 -6
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/state.d.ts +34 -1
- package/dist/core/state.js +79 -26
- package/dist/formatters/json.d.ts +4 -1
- package/dist/formatters/json.js +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -81,6 +81,20 @@ program.hook('preAction', async (thisCommand, actionCommand) => {
|
|
|
81
81
|
const { ensureGistPersistence } = await import('./core/index.js');
|
|
82
82
|
await ensureGistPersistence(token);
|
|
83
83
|
}
|
|
84
|
+
else {
|
|
85
|
+
// #1431: localOnly skips the AUTH GATE, not gist persistence. Mutating
|
|
86
|
+
// localOnly commands (shelve/move/dismiss/override/...) already call
|
|
87
|
+
// maybeCheckpoint, which silently no-ops when the singleton never
|
|
88
|
+
// bootstrapped — so a gist-configured user's CLI mutations were written
|
|
89
|
+
// local-only with no warning and never reached the Gist. Best-effort
|
|
90
|
+
// bootstrap; the warning semantics live (and are unit-tested) in
|
|
91
|
+
// bootstrapGistBestEffort.
|
|
92
|
+
const { bootstrapGistBestEffort } = await import('./core/index.js');
|
|
93
|
+
const localOnlyWarning = await bootstrapGistBestEffort(getGitHubTokenAsync);
|
|
94
|
+
if (localOnlyWarning) {
|
|
95
|
+
console.error(`Warning: ${localOnlyWarning}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
84
98
|
});
|
|
85
99
|
// First-run detection: if no subcommand was provided and no state file exists,
|
|
86
100
|
// show a quick-start guide and exit before Commander displays generic help.
|
package/dist/commands/daily.js
CHANGED
|
@@ -546,6 +546,15 @@ async function executeDailyCheckInternal(token) {
|
|
|
546
546
|
// One collector shared by every phase — threaded through explicitly so the
|
|
547
547
|
// callgraph documents which phases can produce non-fatal warnings. See #1042.
|
|
548
548
|
const warnings = [];
|
|
549
|
+
// Surface gist-mode degradation in the machine-readable envelope (#1431):
|
|
550
|
+
// a process whose config says `persistence: gist` but whose manager is
|
|
551
|
+
// local-only (transient init fallback, or a localOnly entry point that
|
|
552
|
+
// never bootstrapped) writes mutations that will not sync. Previously the
|
|
553
|
+
// only signal was a stderr warn, invisible to --json consumers.
|
|
554
|
+
const smForGistCheck = getStateManager();
|
|
555
|
+
if (smForGistCheck.getState().config.persistence === 'gist' && !smForGistCheck.isGistMode()) {
|
|
556
|
+
recordWarning(warnings, 'gist-init', 'Gist persistence degraded', new Error('configured for Gist but running local-only in this process; mutations will not sync until Gist init succeeds'));
|
|
557
|
+
}
|
|
549
558
|
// Surface Gist staleness up-front so consumers see it even if Phase 1 fails (#1193).
|
|
550
559
|
const staleness = getStateManager().getStateStaleness();
|
|
551
560
|
if (staleness) {
|
|
@@ -283,7 +283,10 @@ export async function fetchDashboardData(token) {
|
|
|
283
283
|
// Partitioned over overriddenPRs (#1416): the shelve decision must use
|
|
284
284
|
// the same post-override status the CLI partitions on.
|
|
285
285
|
const shelvedUrls = new Set(stateManager.getState().config.shelvedPRUrls || []);
|
|
286
|
-
|
|
286
|
+
// Single copy of the shelve predicate (#1421): isShelvedForDisplay is
|
|
287
|
+
// the same rule reconcileShelvePartition applies on rebuilds, so its
|
|
288
|
+
// regression tests now guard this line too.
|
|
289
|
+
const freshShelved = overriddenPRs.filter((pr) => isShelvedForDisplay(pr, shelvedUrls));
|
|
287
290
|
digest.shelvedPRs = freshShelved.map(toShelvedPRRef);
|
|
288
291
|
digest.autoUnshelvedPRs = [];
|
|
289
292
|
digest.summary.totalActivePRs = overriddenPRs.length - freshShelved.length;
|
|
@@ -184,10 +184,20 @@ export async function runListMoveTier(options) {
|
|
|
184
184
|
'Add the entry to the list first, then re-run list-move-tier.');
|
|
185
185
|
}
|
|
186
186
|
if (result.moved) {
|
|
187
|
+
// tmp+rename so a crash mid-write can't truncate the curated list —
|
|
188
|
+
// same atomic pattern as list-mark-done (#1421).
|
|
189
|
+
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
187
190
|
try {
|
|
188
|
-
fs.writeFileSync(
|
|
191
|
+
fs.writeFileSync(tmp, result.content, 'utf8');
|
|
192
|
+
fs.renameSync(tmp, filePath);
|
|
189
193
|
}
|
|
190
194
|
catch (error) {
|
|
195
|
+
try {
|
|
196
|
+
fs.unlinkSync(tmp);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// best-effort cleanup
|
|
200
|
+
}
|
|
191
201
|
throw new Error(`Failed to write file: ${errorMessage(error)}`, { cause: error });
|
|
192
202
|
}
|
|
193
203
|
}
|
package/dist/core/auth.js
CHANGED
|
@@ -13,6 +13,22 @@ const MODULE = 'auth';
|
|
|
13
13
|
// Cached GitHub token (fetched once per session)
|
|
14
14
|
let cachedGitHubToken = null;
|
|
15
15
|
let tokenFetchAttempted = false;
|
|
16
|
+
/**
|
|
17
|
+
* A `gh auth token` spawn that timed out is transient (#1415): the CLI is
|
|
18
|
+
* installed and may answer on the next call (slow disk, machine waking,
|
|
19
|
+
* momentary load). Everything else is definitive for the process lifetime —
|
|
20
|
+
* ENOENT (gh not installed) and a non-zero exit (not authenticated) will not
|
|
21
|
+
* change without user action, so those still latch `tokenFetchAttempted`.
|
|
22
|
+
* The async execFile timeout surfaces as `killed: true` (signal SIGTERM);
|
|
23
|
+
* the sync execFileSync timeout surfaces as `code: 'ETIMEDOUT'` (no
|
|
24
|
+
* `killed` property) — both arms are load-bearing, one per path.
|
|
25
|
+
*/
|
|
26
|
+
function isTransientTokenFetchError(err) {
|
|
27
|
+
if (!err || typeof err !== 'object')
|
|
28
|
+
return false;
|
|
29
|
+
const e = err;
|
|
30
|
+
return e.killed === true || e.code === 'ETIMEDOUT';
|
|
31
|
+
}
|
|
16
32
|
/**
|
|
17
33
|
* Retrieves a GitHub authentication token, checking sources in priority order.
|
|
18
34
|
*
|
|
@@ -29,7 +45,6 @@ export function getGitHubToken() {
|
|
|
29
45
|
if (tokenFetchAttempted) {
|
|
30
46
|
return null;
|
|
31
47
|
}
|
|
32
|
-
tokenFetchAttempted = true;
|
|
33
48
|
if (process.env.GITHUB_TOKEN) {
|
|
34
49
|
cachedGitHubToken = process.env.GITHUB_TOKEN;
|
|
35
50
|
return cachedGitHubToken;
|
|
@@ -40,6 +55,8 @@ export function getGitHubToken() {
|
|
|
40
55
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
41
56
|
timeout: 2000,
|
|
42
57
|
}).trim();
|
|
58
|
+
// Definitive outcome (a token, or authoritatively none) — latch.
|
|
59
|
+
tokenFetchAttempted = true;
|
|
43
60
|
if (token && token.length > 0) {
|
|
44
61
|
cachedGitHubToken = token;
|
|
45
62
|
debug(MODULE, 'Using GitHub token from gh CLI');
|
|
@@ -47,9 +64,14 @@ export function getGitHubToken() {
|
|
|
47
64
|
}
|
|
48
65
|
}
|
|
49
66
|
catch (err) {
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
67
|
+
// Latch only on definitive failures (#1415): a timeout must not
|
|
68
|
+
// permanently disable token fetch for a long-lived process (the MCP
|
|
69
|
+
// server), or gist-mode mutations silently degrade to local-only for
|
|
70
|
+
// the process lifetime. Promote to warn so a slow `gh` (2s timeout) or
|
|
71
|
+
// a misconfigured CLI is visible without DEBUG=1 (#1209 L6).
|
|
72
|
+
if (!isTransientTokenFetchError(err)) {
|
|
73
|
+
tokenFetchAttempted = true;
|
|
74
|
+
}
|
|
53
75
|
warn(MODULE, `gh auth token failed (CLI unavailable or not authenticated): ${err instanceof Error ? err.message : String(err)}`);
|
|
54
76
|
}
|
|
55
77
|
return null;
|
|
@@ -97,7 +119,6 @@ export async function getGitHubTokenAsync() {
|
|
|
97
119
|
if (tokenFetchAttempted) {
|
|
98
120
|
return null;
|
|
99
121
|
}
|
|
100
|
-
tokenFetchAttempted = true;
|
|
101
122
|
if (process.env.GITHUB_TOKEN) {
|
|
102
123
|
cachedGitHubToken = process.env.GITHUB_TOKEN;
|
|
103
124
|
return cachedGitHubToken;
|
|
@@ -113,6 +134,8 @@ export async function getGitHubTokenAsync() {
|
|
|
113
134
|
}
|
|
114
135
|
});
|
|
115
136
|
});
|
|
137
|
+
// Definitive outcome (a token, or authoritatively none) — latch.
|
|
138
|
+
tokenFetchAttempted = true;
|
|
116
139
|
if (token && token.length > 0) {
|
|
117
140
|
cachedGitHubToken = token;
|
|
118
141
|
debug(MODULE, 'Using GitHub token from gh CLI (async)');
|
|
@@ -120,7 +143,11 @@ export async function getGitHubTokenAsync() {
|
|
|
120
143
|
}
|
|
121
144
|
}
|
|
122
145
|
catch (err) {
|
|
123
|
-
// Same warn
|
|
146
|
+
// Same transient/definitive split and warn promotion as the sync
|
|
147
|
+
// version (#1415, #1209 L6).
|
|
148
|
+
if (!isTransientTokenFetchError(err)) {
|
|
149
|
+
tokenFetchAttempted = true;
|
|
150
|
+
}
|
|
124
151
|
warn(MODULE, `gh auth token failed (CLI unavailable or not authenticated): ${err instanceof Error ? err.message : String(err)}`);
|
|
125
152
|
}
|
|
126
153
|
return null;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Core module exports
|
|
3
3
|
* Re-exports all core functionality for convenient imports
|
|
4
4
|
*/
|
|
5
|
-
export { StateManager, getStateManager, getStateManagerAsync, ensureGistPersistence, maybeCheckpoint, resetStateManager, type Stats, } from './state.js';
|
|
5
|
+
export { StateManager, getStateManager, getStateManagerAsync, ensureGistPersistence, bootstrapGistBestEffort, type GistPersistenceStatus, maybeCheckpoint, resetStateManager, type Stats, } from './state.js';
|
|
6
6
|
export { GistStateStore } from './gist-state-store.js';
|
|
7
7
|
export { guidelinesFilename, repoFromGuidelinesFilename, GUIDELINES_FILE_PREFIX, GUIDELINES_MAX_BYTES, GuidelinesNotAvailableError, GuidelinesTooLargeError, } from './guidelines-store.js';
|
|
8
8
|
export { PRMonitor, type PRCheckFailure, type FetchPRsResult, computeDisplayLabel, classifyCICheck, classifyFailingChecks, } from './pr-monitor.js';
|
package/dist/core/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Core module exports
|
|
3
3
|
* Re-exports all core functionality for convenient imports
|
|
4
4
|
*/
|
|
5
|
-
export { StateManager, getStateManager, getStateManagerAsync, ensureGistPersistence, maybeCheckpoint, resetStateManager, } from './state.js';
|
|
5
|
+
export { StateManager, getStateManager, getStateManagerAsync, ensureGistPersistence, bootstrapGistBestEffort, maybeCheckpoint, resetStateManager, } from './state.js';
|
|
6
6
|
export { GistStateStore } from './gist-state-store.js';
|
|
7
7
|
export { guidelinesFilename, repoFromGuidelinesFilename, GUIDELINES_FILE_PREFIX, GUIDELINES_MAX_BYTES, GuidelinesNotAvailableError, GuidelinesTooLargeError, } from './guidelines-store.js';
|
|
8
8
|
export { PRMonitor, computeDisplayLabel, classifyCICheck, classifyFailingChecks, } from './pr-monitor.js';
|
package/dist/core/state.d.ts
CHANGED
|
@@ -441,7 +441,40 @@ export declare function getStateManagerAsync(token?: string): Promise<StateManag
|
|
|
441
441
|
* // CLI bootstrap
|
|
442
442
|
* await ensureGistPersistence(token);
|
|
443
443
|
*/
|
|
444
|
-
export
|
|
444
|
+
export type GistPersistenceStatus =
|
|
445
|
+
/** No state file yet, or config does not request gist mode. */
|
|
446
|
+
'local-mode'
|
|
447
|
+
/** The state file exists but could not be read/parsed for this attempt
|
|
448
|
+
* (permissions, transient FS error, corrupt JSON). Callers must NOT
|
|
449
|
+
* memoize this as "local mode chosen" — a later attempt may succeed. */
|
|
450
|
+
| 'state-unreadable'
|
|
451
|
+
/** Gist mode is configured but no token was available for this attempt. */
|
|
452
|
+
| 'no-token'
|
|
453
|
+
/** Gist mode active: the singleton is gist-backed. */
|
|
454
|
+
| 'gist'
|
|
455
|
+
/** Gist mode is configured and a token was available, but init fell back
|
|
456
|
+
* to local-only (transient network failure). A later call may recover. */
|
|
457
|
+
| 'degraded';
|
|
458
|
+
export declare function ensureGistPersistence(token: string | null): Promise<GistPersistenceStatus>;
|
|
459
|
+
/**
|
|
460
|
+
* Best-effort gist bootstrap for entry points WITHOUT the auth gate (#1431):
|
|
461
|
+
* the CLI's localOnly commands (shelve/move/dismiss/override/config/setup/...)
|
|
462
|
+
* skip token enforcement, but a gist-configured user's mutations must still
|
|
463
|
+
* reach the Gist — their maybeCheckpoint calls silently no-op when the
|
|
464
|
+
* singleton never bootstrapped.
|
|
465
|
+
*
|
|
466
|
+
* Returns a human-readable LOCAL-ONLY warning when the process will write
|
|
467
|
+
* local-only despite a gist config, or null when no warning is needed
|
|
468
|
+
* (local mode, or gist mode successfully activated).
|
|
469
|
+
*
|
|
470
|
+
* Ordering: peek first with no token (zero spawn cost for genuinely-local
|
|
471
|
+
* users), fetch a token only when the config asks for gist. Hard
|
|
472
|
+
* ConfigurationErrors are converted to a warning instead of thrown — the
|
|
473
|
+
* localOnly set includes config/setup, the very commands needed to REPAIR a
|
|
474
|
+
* broken gist setup, so they must not be bricked by it. (The auth-gated
|
|
475
|
+
* path keeps throwing per #1202.)
|
|
476
|
+
*/
|
|
477
|
+
export declare function bootstrapGistBestEffort(fetchToken: () => Promise<string | null>): Promise<string | null>;
|
|
445
478
|
/**
|
|
446
479
|
* Reset the singleton StateManager instance to null. Intended for test isolation.
|
|
447
480
|
*/
|
package/dist/core/state.js
CHANGED
|
@@ -924,13 +924,27 @@ export function getStateManager() {
|
|
|
924
924
|
* StateManager and Gist checkpoints will be no-ops.
|
|
925
925
|
*/
|
|
926
926
|
export async function getStateManagerAsync(token) {
|
|
927
|
-
|
|
927
|
+
// #1415: a LOCAL-mode singleton does not short-circuit when a token is
|
|
928
|
+
// provided. The only token-bearing caller is ensureGistPersistence, which
|
|
929
|
+
// already verified the config says `persistence: gist` — so a local
|
|
930
|
+
// singleton here means a previous transient init failure fell back (or a
|
|
931
|
+
// tool body lazily created the local manager before auth resolved), and
|
|
932
|
+
// this call is the retry that must be allowed to upgrade it. The old
|
|
933
|
+
// unconditional early return made every retry a dead no-op, permanently
|
|
934
|
+
// latching gist-configured processes into silent local-only writes.
|
|
935
|
+
if (stateManager && (!token || stateManager.isGistMode()))
|
|
928
936
|
return stateManager;
|
|
929
937
|
if (asyncManagerPromise)
|
|
930
938
|
return asyncManagerPromise;
|
|
931
939
|
if (token) {
|
|
932
940
|
asyncManagerPromise = StateManager.createWithGist(token)
|
|
933
941
|
.then((mgr) => {
|
|
942
|
+
// Upgrade note: replacing a transient-fallback local singleton fixes
|
|
943
|
+
// FUTURE operations. Mutations made during the degraded window stay
|
|
944
|
+
// in the local state.json only — when a Gist already exists they are
|
|
945
|
+
// NOT merged into it by this upgrade (bootstrapWithMigration seeds a
|
|
946
|
+
// Gist from local state only on first creation). The per-call MCP
|
|
947
|
+
// warning is the signal that those writes were at risk.
|
|
934
948
|
stateManager = mgr;
|
|
935
949
|
asyncManagerPromise = null;
|
|
936
950
|
return mgr;
|
|
@@ -949,6 +963,9 @@ export async function getStateManagerAsync(token) {
|
|
|
949
963
|
// marker stays in config, causing permanent cross-machine divergence.
|
|
950
964
|
if (!isTransientNetworkError(err))
|
|
951
965
|
throw err;
|
|
966
|
+
// Intentional CLI semantics: a one-shot process warns and proceeds
|
|
967
|
+
// local-only. Long-lived callers (MCP) detect this via the
|
|
968
|
+
// ensureGistPersistence return status and retry on later calls.
|
|
952
969
|
warn(MODULE, `Gist initialization failed (transient network error), falling back to local-only mode: ${err}`);
|
|
953
970
|
return getStateManager();
|
|
954
971
|
});
|
|
@@ -956,39 +973,75 @@ export async function getStateManagerAsync(token) {
|
|
|
956
973
|
}
|
|
957
974
|
return getStateManager();
|
|
958
975
|
}
|
|
959
|
-
/**
|
|
960
|
-
* Bootstrap helper for processes that may run in Gist persistence mode.
|
|
961
|
-
*
|
|
962
|
-
* Peeks at the state file to check if Gist mode is configured. If so and a
|
|
963
|
-
* valid token is provided, pre-sets the singleton via {@link getStateManagerAsync}
|
|
964
|
-
* so subsequent synchronous {@link getStateManager} calls return the Gist-backed
|
|
965
|
-
* instance. No-op when the state file is absent, unparseable, or not in Gist mode.
|
|
966
|
-
*
|
|
967
|
-
* Consolidates identical filesystem-peek + getStateManagerAsync logic that
|
|
968
|
-
* was duplicated between the CLI bootstrap (`cli.ts`) and MCP tool bootstrap
|
|
969
|
-
* (`mcp-server/src/tools.ts`) — #1000.
|
|
970
|
-
*
|
|
971
|
-
* @param token - GitHub token with `gist` scope, or `null` to skip activation
|
|
972
|
-
*
|
|
973
|
-
* @example
|
|
974
|
-
* // CLI bootstrap
|
|
975
|
-
* await ensureGistPersistence(token);
|
|
976
|
-
*/
|
|
977
976
|
export async function ensureGistPersistence(token) {
|
|
978
|
-
if (!token)
|
|
979
|
-
return;
|
|
980
977
|
let persistence;
|
|
981
978
|
try {
|
|
982
979
|
const raw = fs.readFileSync(getStatePath(), 'utf8');
|
|
983
980
|
persistence = JSON.parse(raw)?.config?.persistence;
|
|
984
981
|
}
|
|
985
|
-
catch {
|
|
986
|
-
//
|
|
987
|
-
|
|
982
|
+
catch (err) {
|
|
983
|
+
// A missing file is the genuine "fresh local-mode user" case. Anything
|
|
984
|
+
// else (EACCES, EMFILE, corrupt JSON) must not be silently classified
|
|
985
|
+
// as a local-mode CHOICE — that would re-create the #1415 latch through
|
|
986
|
+
// a third door when the caller memoizes the answer.
|
|
987
|
+
if (err.code === 'ENOENT')
|
|
988
|
+
return 'local-mode';
|
|
989
|
+
warn(MODULE, `State file unreadable during gist-persistence check (will retry): ${errorMessage(err)}`);
|
|
990
|
+
return 'state-unreadable';
|
|
991
|
+
}
|
|
992
|
+
if (persistence !== 'gist')
|
|
993
|
+
return 'local-mode';
|
|
994
|
+
// #1415: report the distinction the MCP layer needs — "gist configured but
|
|
995
|
+
// token missing" and "init fell back to local" both mean the process is
|
|
996
|
+
// NOT writing to the Gist despite the config saying it should, and a
|
|
997
|
+
// long-lived caller must keep retrying instead of memoizing the outcome.
|
|
998
|
+
if (!token)
|
|
999
|
+
return 'no-token';
|
|
1000
|
+
const mgr = await getStateManagerAsync(token);
|
|
1001
|
+
return mgr.isGistMode() ? 'gist' : 'degraded';
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Best-effort gist bootstrap for entry points WITHOUT the auth gate (#1431):
|
|
1005
|
+
* the CLI's localOnly commands (shelve/move/dismiss/override/config/setup/...)
|
|
1006
|
+
* skip token enforcement, but a gist-configured user's mutations must still
|
|
1007
|
+
* reach the Gist — their maybeCheckpoint calls silently no-op when the
|
|
1008
|
+
* singleton never bootstrapped.
|
|
1009
|
+
*
|
|
1010
|
+
* Returns a human-readable LOCAL-ONLY warning when the process will write
|
|
1011
|
+
* local-only despite a gist config, or null when no warning is needed
|
|
1012
|
+
* (local mode, or gist mode successfully activated).
|
|
1013
|
+
*
|
|
1014
|
+
* Ordering: peek first with no token (zero spawn cost for genuinely-local
|
|
1015
|
+
* users), fetch a token only when the config asks for gist. Hard
|
|
1016
|
+
* ConfigurationErrors are converted to a warning instead of thrown — the
|
|
1017
|
+
* localOnly set includes config/setup, the very commands needed to REPAIR a
|
|
1018
|
+
* broken gist setup, so they must not be bricked by it. (The auth-gated
|
|
1019
|
+
* path keeps throwing per #1202.)
|
|
1020
|
+
*/
|
|
1021
|
+
export async function bootstrapGistBestEffort(fetchToken) {
|
|
1022
|
+
let reason = null;
|
|
1023
|
+
try {
|
|
1024
|
+
let status = await ensureGistPersistence(null);
|
|
1025
|
+
if (status === 'no-token') {
|
|
1026
|
+
status = await ensureGistPersistence(await fetchToken());
|
|
1027
|
+
}
|
|
1028
|
+
if (status === 'no-token')
|
|
1029
|
+
reason = 'no GitHub token is available';
|
|
1030
|
+
else if (status === 'state-unreadable')
|
|
1031
|
+
reason = 'the state file could not be read';
|
|
1032
|
+
else if (status === 'degraded')
|
|
1033
|
+
reason = 'Gist initialization hit a transient network failure';
|
|
988
1034
|
}
|
|
989
|
-
|
|
990
|
-
|
|
1035
|
+
catch (err) {
|
|
1036
|
+
reason =
|
|
1037
|
+
err instanceof ConfigurationError
|
|
1038
|
+
? `Gist initialization failed (${errorMessage(err)}) — fix the Gist setup (check the token's gist scope, or run state-show / setup) before relying on sync`
|
|
1039
|
+
: `Gist initialization failed: ${errorMessage(err)}`;
|
|
991
1040
|
}
|
|
1041
|
+
if (reason === null)
|
|
1042
|
+
return null;
|
|
1043
|
+
return (`Gist persistence is configured but ${reason} — changes made by this command are ` +
|
|
1044
|
+
'LOCAL-ONLY and may be overwritten by the next successful Gist sync.');
|
|
992
1045
|
}
|
|
993
1046
|
/**
|
|
994
1047
|
* Reset the singleton StateManager instance to null. Intended for test isolation.
|
|
@@ -51,7 +51,7 @@ export interface CompactRepoGroup {
|
|
|
51
51
|
* See `DailyWarning` and issue #1042 for the rationale — keeping this a
|
|
52
52
|
* fixed union so downstream consumers can switch on it without drift.
|
|
53
53
|
*/
|
|
54
|
-
export type DailyWarningPhase = 'fetch' | 'repo-scores' | 'analytics' | 'scout-sync' | 'partition' | 'dismiss-filter' | 'gist-checkpoint' | 'gist-staleness' | 'state-load';
|
|
54
|
+
export type DailyWarningPhase = 'fetch' | 'repo-scores' | 'analytics' | 'scout-sync' | 'partition' | 'dismiss-filter' | 'gist-init' | 'gist-checkpoint' | 'gist-staleness' | 'state-load';
|
|
55
55
|
/**
|
|
56
56
|
* A single non-fatal failure surfaced from the `daily` pipeline. Unlike
|
|
57
57
|
* `PRCheckFailure` (which is scoped to per-PR fetch errors), this covers
|
|
@@ -179,6 +179,7 @@ export declare const StatusOutputSchema: z.ZodObject<{
|
|
|
179
179
|
"scout-sync": "scout-sync";
|
|
180
180
|
partition: "partition";
|
|
181
181
|
"dismiss-filter": "dismiss-filter";
|
|
182
|
+
"gist-init": "gist-init";
|
|
182
183
|
"gist-checkpoint": "gist-checkpoint";
|
|
183
184
|
"gist-staleness": "gist-staleness";
|
|
184
185
|
"state-load": "state-load";
|
|
@@ -394,6 +395,7 @@ export declare const DailyOutputSchema: z.ZodObject<{
|
|
|
394
395
|
"scout-sync": "scout-sync";
|
|
395
396
|
partition: "partition";
|
|
396
397
|
"dismiss-filter": "dismiss-filter";
|
|
398
|
+
"gist-init": "gist-init";
|
|
397
399
|
"gist-checkpoint": "gist-checkpoint";
|
|
398
400
|
"gist-staleness": "gist-staleness";
|
|
399
401
|
"state-load": "state-load";
|
|
@@ -541,6 +543,7 @@ export declare const CompactDailyOutputSchema: z.ZodObject<{
|
|
|
541
543
|
"scout-sync": "scout-sync";
|
|
542
544
|
partition: "partition";
|
|
543
545
|
"dismiss-filter": "dismiss-filter";
|
|
546
|
+
"gist-init": "gist-init";
|
|
544
547
|
"gist-checkpoint": "gist-checkpoint";
|
|
545
548
|
"gist-staleness": "gist-staleness";
|
|
546
549
|
"state-load": "state-load";
|
package/dist/formatters/json.js
CHANGED