@remits/remits-cli 0.1.137 → 0.1.139
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/README.md +4 -3
- package/index.js +242 -5
- package/package.json +1 -1
- package/skills/remits-cli/SKILL.md +28 -3
- package/skills/remits-cli/references/account-targeting.md +7 -5
- package/skills/remits-cli/references/branch-variants.md +37 -1
- package/skills/remits-cli/references/command-reference.md +19 -1
- package/skills/remits-cli/references/component-integrity.md +1 -0
- package/skills/remits-cli/references/component-resolution.md +11 -0
- package/skills/remits-cli/references/development-loop.md +37 -8
- package/skills/remits-cli/references/troubleshooting.md +1 -0
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ git add -A
|
|
|
33
33
|
git commit -m "sync passing changes"
|
|
34
34
|
git push
|
|
35
35
|
remits-cli components sync --safe # variant branch: gated, dry-runs first, refuses surprises
|
|
36
|
+
remits-cli components sync doctor # read-only sync/promotion/staging diagnosis
|
|
36
37
|
remits-cli components sync
|
|
37
38
|
remits-cli components sync --branch feature_branch --dry-run
|
|
38
39
|
remits-cli components sync --branch feature_branch --dry-run --summary
|
|
@@ -84,7 +85,7 @@ remits-cli install --skills --overwrite true
|
|
|
84
85
|
- `components sync` performs a server-side sync from the git remote into the Remits platform for the selected branch. It does not run local git commands. After a successful non-dry-run sync, the platform clears the branch/user staging scope so staged aliases cannot keep shadowing the newly synced DB rows.
|
|
85
86
|
- On trunk, `components sync` performs the full repo-to-DB reconcile. On a non-trunk branch, it writes `ComponentVariant` overlays only and may refresh branch-local `account-info.json`, `account-hierarchy.json`, and `account-configurations.json` for the subscribing account that initiated the sync. `--dry-run` is accepted only for non-trunk variant syncs and reports overrides/additions/tombstones without writing variants, caching the sync SHA, updating metadata, or clearing staging. Add `--summary` to dry-run output when you only need counts, removals/tombstones, errors, skipped items, and warnings. `--force-tombstones` is accepted only for non-trunk variant syncs and should be used only when missing trunk component files are intentional tombstone overrides.
|
|
86
87
|
- `components commit` is a convenience wrapper that performs local git commit/push, then `components sync`, then local `git fetch`/`git pull --ff-only`.
|
|
87
|
-
- `components sync` returns the post-sync branch SHA produced by the platform. `components commit` verifies that `origin/<branch>` and local `HEAD` both match
|
|
88
|
+
- `components sync` returns the post-sync branch SHA produced by the platform. `components sync doctor` is read-only and assembles local HEAD, origin HEAD, platform last-sync SHA, staging shadow risk, promotion freshness, repository mismatch, and the next safe action when sync state is confusing. `components commit` verifies that `origin/<branch>` and local `HEAD` both match the exact synced SHA after the final pull.
|
|
88
89
|
- `components push` is deprecated and currently behaves the same as `components stage`.
|
|
89
90
|
- `accountId` resolution for CLI commands: explicit `--account-id` flag wins, then the current repo's `account-info.json` (`resolution.accountId`, then the short-lived `repoContext.accountInfoAccountId`, then the legacy top-level id — legacy files are rooted at the hierarchy ROOT, so their top-level `id` may be an ancestor), then the active session.
|
|
90
91
|
- For `remits-cli tool`, read/discovery tools treat that resolved account as the **scope root**. You do not need the owning child account id for an exact document/record lookup: pass `--scope children`, or put `scope:"children"` in `--input`, and use the returned `resolvedTargetAccountId` for follow-up writes/runs. Use `--target-account-id` when you already know the exact owner, `--account-ids` for an explicit bounded owner list, and `--anchor-account-id` only to disambiguate multi-parent paths. Mutating tools still require an exact target.
|
|
@@ -100,8 +101,8 @@ remits-cli install --skills --overwrite true
|
|
|
100
101
|
- Branch defaults to the current local git branch.
|
|
101
102
|
- Data mode defaults to `test`. For `remits-cli test run`, that default is now enforced even if the most-recent authenticated session for the account is `prod`; a production test run therefore requires an explicit `--data-mode prod` on the command line. Use `remits-cli data-mode set prod` only for production investigation.
|
|
102
103
|
- If the same account is authenticated against more than one host and you omit `--base-url`, the CLI auto-resolves the best matching session and now prints the resolved host. Pass `--base-url` explicitly whenever the target host matters.
|
|
103
|
-
- `--names` is `|`-delimited and may be repeated. A comma
|
|
104
|
-
|
|
104
|
+
- `--names` is `|`-delimited and may be repeated. A comma is part of the selector, so comma-bearing case
|
|
105
|
+
names can be passed literally.
|
|
105
106
|
- Nested help is available before required-argument validation, including `remits-cli test run --help`, `remits-cli components sync --help`, and `remits-cli tool --help`.
|
|
106
107
|
- `components sync --safe` is the recommended agent path on a variant branch. It expands to `--summary --changed-only --fail-on-errors --fail-on-removed`, resolves `--changed-since` from the branch's merge base with trunk when you did not name one (local refs only; it never runs an implicit `git fetch`), and prints the planned writes before mutating unless `--yes` is passed. On trunk there is no plan to gate, so it states what a trunk reconcile does and requires `--yes`.
|
|
107
108
|
- `components sync` has fail-closed safety gates for unattended/agent use. Each exits non-zero instead of printing a wall of JSON: `--changed-only` (fail unless every planned write is a component this checkout edited), `--names-only` (print only `BUCKET type:id name` lines), `--fail-on-removed`, `--fail-on-errors`, and `--expected-removed <type:id>` (repeatable or comma-delimited; implies `--fail-on-removed`, so any removal you did not name fails). `--changed-only` also fails closed when the checkout is not a git working tree, because "git could not answer" must never be read as "nothing changed".
|
package/index.js
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
- L4107 Skill Delivery And TOC Resolution
|
|
12
12
|
- L4417 Auth And Component Staging
|
|
13
13
|
- L5032 Component Summaries, Status, And Sync Gates
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
14
|
+
- L7332 Branches, Promotion, Commit, And Test Runs
|
|
15
|
+
- L9421 Tokens, Tools, Verification, And Config
|
|
16
|
+
- L10848 Service Dashboard And WebSocket Listener
|
|
17
|
+
- L12971 Agent And Ticket Workflows
|
|
18
|
+
- L16566 Help, Auto Update, And Command Dispatch
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/*
|
|
@@ -5994,6 +5994,234 @@ async function clearComponentsCommand(flags) {
|
|
|
5994
5994
|
return response;
|
|
5995
5995
|
}
|
|
5996
5996
|
|
|
5997
|
+
async function syncDoctorComponentsCommand(rawFlags) {
|
|
5998
|
+
const cwd = process.cwd();
|
|
5999
|
+
const flags = Object.assign({}, rawFlags);
|
|
6000
|
+
ensureLocalState(cwd);
|
|
6001
|
+
const sessionContext = resolveSessionContext(cwd, flags);
|
|
6002
|
+
requireAccountRepoContext(cwd, flags, 'components sync doctor', sessionContext);
|
|
6003
|
+
const { session, accountId } = sessionContext;
|
|
6004
|
+
const baseUrl = flags['base-url'] || session.baseUrl || DEFAULT_BASE_URL;
|
|
6005
|
+
const branchName = flags.branch || currentBranch(cwd);
|
|
6006
|
+
const workspace = resolveWorkspace(cwd, flags);
|
|
6007
|
+
const dataMode = resolveDataMode(flags, session);
|
|
6008
|
+
const api = buildAxios(baseUrl, session.token);
|
|
6009
|
+
|
|
6010
|
+
const statusResponse = await loggedPost(api, cwd, '/cli/components', {
|
|
6011
|
+
token: session.token,
|
|
6012
|
+
accountId,
|
|
6013
|
+
branchName,
|
|
6014
|
+
workspace,
|
|
6015
|
+
dataMode,
|
|
6016
|
+
mode: 'status'
|
|
6017
|
+
}).then((r) => r.data);
|
|
6018
|
+
|
|
6019
|
+
if (!statusResponse.success) {
|
|
6020
|
+
throw new Error(statusResponse.message || 'Staging status failed');
|
|
6021
|
+
}
|
|
6022
|
+
|
|
6023
|
+
statusResponse.freshness = stagingFreshness({
|
|
6024
|
+
head: safeGitValue(cwd, 'git rev-parse HEAD'),
|
|
6025
|
+
originHead: safeGitValue(cwd, 'git rev-parse ' + shellQuote('origin/' + branchName)),
|
|
6026
|
+
lastSyncedSha: statusResponse.branchContext && statusResponse.branchContext.lastSyncedSha,
|
|
6027
|
+
entries: statusResponse.entries,
|
|
6028
|
+
laneSummary: statusResponse.laneSummary,
|
|
6029
|
+
isAncestor: (a, b) => gitIsAncestor(cwd, a, b)
|
|
6030
|
+
});
|
|
6031
|
+
statusResponse.repositoryCheck = repositoryCheck(cwd, statusResponse.branchContext);
|
|
6032
|
+
|
|
6033
|
+
let promotionResponse = null;
|
|
6034
|
+
try {
|
|
6035
|
+
promotionResponse = await loggedPost(api, cwd, '/cli/branches', {
|
|
6036
|
+
token: session.token,
|
|
6037
|
+
accountId,
|
|
6038
|
+
mode: 'promotion',
|
|
6039
|
+
branchName
|
|
6040
|
+
}, { skipSessionLog: true }).then((r) => r.data);
|
|
6041
|
+
} catch (err) {
|
|
6042
|
+
const data = err && err.response && err.response.data;
|
|
6043
|
+
promotionResponse = {
|
|
6044
|
+
success: false,
|
|
6045
|
+
message: data && data.message ? data.message : describeError(err)
|
|
6046
|
+
};
|
|
6047
|
+
}
|
|
6048
|
+
|
|
6049
|
+
const report = buildSyncDoctorReport({
|
|
6050
|
+
accountId,
|
|
6051
|
+
branchName,
|
|
6052
|
+
workspace,
|
|
6053
|
+
dataMode: statusResponse.dataMode || dataMode,
|
|
6054
|
+
baseUrl: normalizeBaseUrl(baseUrl),
|
|
6055
|
+
local: {
|
|
6056
|
+
head: safeGitValue(cwd, 'git rev-parse HEAD'),
|
|
6057
|
+
originHead: safeGitValue(cwd, 'git rev-parse ' + shellQuote('origin/' + branchName)),
|
|
6058
|
+
upstream: safeGitValue(cwd, 'git rev-parse --abbrev-ref --symbolic-full-name @{u}'),
|
|
6059
|
+
aheadBehind: safeGitValue(cwd, 'git rev-list --left-right --count HEAD...origin/' + shellQuote(branchName))
|
|
6060
|
+
},
|
|
6061
|
+
status: statusResponse,
|
|
6062
|
+
promotion: promotionResponse
|
|
6063
|
+
});
|
|
6064
|
+
|
|
6065
|
+
if (flagEnabled(flags.json)) {
|
|
6066
|
+
console.log(JSON.stringify(report, null, 2));
|
|
6067
|
+
return report;
|
|
6068
|
+
}
|
|
6069
|
+
|
|
6070
|
+
printSessionResolutionWarning(sessionContext);
|
|
6071
|
+
printResolvedBaseUrl(baseUrl);
|
|
6072
|
+
printSyncDoctorReport(report);
|
|
6073
|
+
return report;
|
|
6074
|
+
}
|
|
6075
|
+
|
|
6076
|
+
function selectedPromotionEntry(promotion, branchName) {
|
|
6077
|
+
if (!promotion || promotion.success === false) return null;
|
|
6078
|
+
const entries = Array.isArray(promotion.branches) ? promotion.branches : [promotion];
|
|
6079
|
+
return entries.find((entry) => String(entry && entry.branch || '') === String(branchName)) || entries[0] || null;
|
|
6080
|
+
}
|
|
6081
|
+
|
|
6082
|
+
function syncDoctorStagedCount(status) {
|
|
6083
|
+
const laneSummary = status && status.laneSummary || {};
|
|
6084
|
+
const candidates = [laneSummary.stagedCount, laneSummary.count, laneSummary.total, status && status.stagedCount];
|
|
6085
|
+
for (const value of candidates) {
|
|
6086
|
+
const number = Number(value);
|
|
6087
|
+
if (Number.isFinite(number)) return number;
|
|
6088
|
+
}
|
|
6089
|
+
return Array.isArray(status && status.entries) ? status.entries.length : 0;
|
|
6090
|
+
}
|
|
6091
|
+
|
|
6092
|
+
function buildSyncDoctorReport(input) {
|
|
6093
|
+
const status = input.status || {};
|
|
6094
|
+
const promotion = input.promotion || null;
|
|
6095
|
+
const entry = selectedPromotionEntry(promotion, input.branchName);
|
|
6096
|
+
const platform = entry && entry.platform || {};
|
|
6097
|
+
const git = entry && entry.git || {};
|
|
6098
|
+
const branchContext = status.branchContext || {};
|
|
6099
|
+
const stagedCount = syncDoctorStagedCount(status);
|
|
6100
|
+
const report = {
|
|
6101
|
+
success: status.success !== false,
|
|
6102
|
+
accountId: input.accountId,
|
|
6103
|
+
branchName: input.branchName,
|
|
6104
|
+
workspace: input.workspace || null,
|
|
6105
|
+
dataMode: input.dataMode,
|
|
6106
|
+
host: input.baseUrl,
|
|
6107
|
+
local: input.local || {},
|
|
6108
|
+
world: status.variantWorld || null,
|
|
6109
|
+
branchContext,
|
|
6110
|
+
repositoryCheck: status.repositoryCheck || null,
|
|
6111
|
+
staging: {
|
|
6112
|
+
laneId: status.laneSummary && status.laneSummary.laneId || status.stagingLane || null,
|
|
6113
|
+
stagedCount,
|
|
6114
|
+
contentHash: status.laneSummary && status.laneSummary.contentHash || null,
|
|
6115
|
+
freshness: status.freshness || null
|
|
6116
|
+
},
|
|
6117
|
+
platform: {
|
|
6118
|
+
lastSyncedSha: branchContext.lastSyncedSha || null,
|
|
6119
|
+
syncRepository: branchContext.repository || null,
|
|
6120
|
+
mode: branchContextIsTrunk(branchContext) ? 'trunk' : 'variant'
|
|
6121
|
+
},
|
|
6122
|
+
promotion: entry ? {
|
|
6123
|
+
available: true,
|
|
6124
|
+
branch: entry.branch,
|
|
6125
|
+
phase: entry.phase || null,
|
|
6126
|
+
summary: entry.summary || null,
|
|
6127
|
+
remoteBranchHeadSha: git.branchHeadSha || null,
|
|
6128
|
+
remoteTrunkHeadSha: git.trunkHeadSha || null,
|
|
6129
|
+
overlaysComputedFrom: platform.syncedSha || null,
|
|
6130
|
+
overlayFreshness: platform.freshness || null,
|
|
6131
|
+
overridden: platform.overridden,
|
|
6132
|
+
branchOnly: platform.added,
|
|
6133
|
+
tombstoned: platform.removed,
|
|
6134
|
+
drifted: platform.drifted,
|
|
6135
|
+
blockers: entry.blockers || [],
|
|
6136
|
+
nextSteps: entry.nextSteps || []
|
|
6137
|
+
} : {
|
|
6138
|
+
available: false,
|
|
6139
|
+
message: promotion && promotion.message || 'promotion status unavailable'
|
|
6140
|
+
}
|
|
6141
|
+
};
|
|
6142
|
+
report.recommendations = syncDoctorRecommendations(report);
|
|
6143
|
+
return report;
|
|
6144
|
+
}
|
|
6145
|
+
|
|
6146
|
+
function syncDoctorRecommendations(report) {
|
|
6147
|
+
const recs = [];
|
|
6148
|
+
const repo = report.repositoryCheck;
|
|
6149
|
+
if (repo && repo.matches === false) {
|
|
6150
|
+
recs.push('Run sync from the checkout whose origin matches the platform repository: ' + repo.platformRepository + '.');
|
|
6151
|
+
}
|
|
6152
|
+
const freshness = report.staging && report.staging.freshness || {};
|
|
6153
|
+
if (freshness.landedSinceHead === true) {
|
|
6154
|
+
recs.push('Pull the platform-synced commit before trusting this lane: git fetch origin && git pull --ff-only, then re-stage.');
|
|
6155
|
+
}
|
|
6156
|
+
if (freshness.entriesBehindLastSync > 0) {
|
|
6157
|
+
recs.push('Re-stage from the current checkout with `remits-cli components stage --workset`; the lane shadows rows landed after it was staged.');
|
|
6158
|
+
}
|
|
6159
|
+
if ((report.staging && report.staging.stagedCount || 0) > 0) {
|
|
6160
|
+
recs.push('Committed-variant verification will be shadowed by this staging lane; clear it or use an unused --branch with --variant-branch before proving committed source.');
|
|
6161
|
+
}
|
|
6162
|
+
const promo = report.promotion || {};
|
|
6163
|
+
if (promo.available && Array.isArray(promo.blockers) && promo.blockers.length) {
|
|
6164
|
+
recs.push('Do not sync yet; `components promotion` reports blockers. Follow its next steps before mutating.');
|
|
6165
|
+
} else if (promo.available && promo.overlayFreshness && promo.overlayFreshness !== 'current') {
|
|
6166
|
+
recs.push('Stored overlays are stale relative to the branch/trunk pair. Re-read promotion, merge as instructed, then run one gated sync.');
|
|
6167
|
+
}
|
|
6168
|
+
if (report.platform && report.platform.mode === 'variant') {
|
|
6169
|
+
recs.push('Agent landing path: push the branch, run `remits-cli components sync --safe --yes` once, then `git pull --ff-only`.');
|
|
6170
|
+
} else {
|
|
6171
|
+
recs.push('Trunk sync has no dry-run plan. Use `remits-cli components sync --safe --yes` only when you intend the authoritative trunk reconcile.');
|
|
6172
|
+
}
|
|
6173
|
+
recs.push('If a sync times out client-side, treat the result as unknown: observe with `components sync doctor` or `components promotion`; do not put `components sync` in a polling loop.');
|
|
6174
|
+
return Array.from(new Set(recs));
|
|
6175
|
+
}
|
|
6176
|
+
|
|
6177
|
+
function printSyncDoctorReport(report) {
|
|
6178
|
+
console.log('Sync doctor');
|
|
6179
|
+
console.log('Account:', report.accountId);
|
|
6180
|
+
console.log('Data mode:', report.dataMode);
|
|
6181
|
+
console.log('Git branch:', report.branchName);
|
|
6182
|
+
console.log('Workspace:', report.workspace || 'shared default lane');
|
|
6183
|
+
console.log('Mode:', report.platform.mode);
|
|
6184
|
+
console.log('');
|
|
6185
|
+
console.log('Local git:');
|
|
6186
|
+
console.log(' HEAD: ' + short(report.local.head));
|
|
6187
|
+
console.log(' origin HEAD: ' + short(report.local.originHead));
|
|
6188
|
+
if (report.local.upstream) console.log(' upstream: ' + report.local.upstream);
|
|
6189
|
+
if (report.local.aheadBehind) console.log(' HEAD...origin/' + report.branchName + ': ' + report.local.aheadBehind.trim() + ' (left=local, right=remote)');
|
|
6190
|
+
console.log('');
|
|
6191
|
+
console.log('Platform sync:');
|
|
6192
|
+
console.log(' repository: ' + (report.platform.syncRepository || 'unknown'));
|
|
6193
|
+
console.log(' last synced SHA: ' + short(report.platform.lastSyncedSha));
|
|
6194
|
+
if (report.repositoryCheck && report.repositoryCheck.matches === false) {
|
|
6195
|
+
console.log(' REPOSITORY MISMATCH: checkout origin is ' + report.repositoryCheck.checkoutOrigin);
|
|
6196
|
+
}
|
|
6197
|
+
console.log('');
|
|
6198
|
+
console.log('Staging lane:');
|
|
6199
|
+
console.log(' staged entries: ' + report.staging.stagedCount);
|
|
6200
|
+
if (report.staging.contentHash) console.log(' content hash: ' + report.staging.contentHash);
|
|
6201
|
+
printStagingFreshness(report.staging.freshness);
|
|
6202
|
+
console.log('');
|
|
6203
|
+
console.log('Promotion / variant status:');
|
|
6204
|
+
if (report.promotion.available) {
|
|
6205
|
+
console.log(' phase: ' + (report.promotion.phase || 'unknown'));
|
|
6206
|
+
console.log(' remote branch HEAD: ' + short(report.promotion.remoteBranchHeadSha));
|
|
6207
|
+
console.log(' overlays computed from:' + ' ' + short(report.promotion.overlaysComputedFrom) +
|
|
6208
|
+
(report.promotion.overlayFreshness ? ' [' + report.promotion.overlayFreshness + ']' : ''));
|
|
6209
|
+
console.log(' overlays: overridden ' + (report.promotion.overridden ?? 'unknown') +
|
|
6210
|
+
', branch-only ' + (report.promotion.branchOnly ?? 'unknown') +
|
|
6211
|
+
', tombstoned ' + (report.promotion.tombstoned ?? 'unknown') +
|
|
6212
|
+
', drifted ' + (report.promotion.drifted ?? 'unknown'));
|
|
6213
|
+
if (report.promotion.blockers && report.promotion.blockers.length) {
|
|
6214
|
+
console.log(' blockers: ' + report.promotion.blockers.length);
|
|
6215
|
+
report.promotion.blockers.slice(0, 8).forEach((b) => console.log(' - ' + b.code + ': ' + b.message));
|
|
6216
|
+
}
|
|
6217
|
+
} else {
|
|
6218
|
+
console.log(' unavailable: ' + report.promotion.message);
|
|
6219
|
+
}
|
|
6220
|
+
console.log('');
|
|
6221
|
+
console.log('Recommended next action:');
|
|
6222
|
+
report.recommendations.forEach((line) => console.log(' - ' + line));
|
|
6223
|
+
}
|
|
6224
|
+
|
|
5997
6225
|
async function syncComponentsCommand(rawFlags) {
|
|
5998
6226
|
const cwd = process.cwd();
|
|
5999
6227
|
// `--safe` is a NAME for the gate combination that should be the default agent path, not a new gate.
|
|
@@ -11339,6 +11567,7 @@ function buildRepoSnapshot(entry) {
|
|
|
11339
11567
|
? path.join(localPaths.legacy.sessionsDir, legacySessionName + '.jsonl')
|
|
11340
11568
|
: null;
|
|
11341
11569
|
const repoFiles = [
|
|
11570
|
+
{ label: 'account-boot.json', path: path.join(directory, 'account-boot.json'), mode: 'json' },
|
|
11342
11571
|
{ label: 'account-info.json', path: entry.accountInfoPath || path.join(directory, 'account-info.json'), mode: 'json' },
|
|
11343
11572
|
{ label: 'account-hierarchy.json', path: path.join(directory, 'account-hierarchy.json'), mode: 'json' },
|
|
11344
11573
|
{ label: 'account-analytics.json', path: path.join(directory, 'account-analytics.json'), mode: 'json' },
|
|
@@ -16536,11 +16765,14 @@ function printComponentsHelp(subcommand) {
|
|
|
16536
16765
|
}
|
|
16537
16766
|
if (subcommand === 'sync') {
|
|
16538
16767
|
console.log('Usage: remits-cli components sync [--base-url URL] [--account-id ID] [--branch BRANCH] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--create-variant-branch] [--summary] [--json]');
|
|
16768
|
+
console.log(' remits-cli components sync doctor [--json]');
|
|
16539
16769
|
console.log('');
|
|
16540
16770
|
console.log('On trunk this reconciles the pushed repository into live component rows.');
|
|
16541
16771
|
console.log('On a variant branch this writes ComponentVariant overlays only.');
|
|
16542
16772
|
console.log('--dry-run is only supported on variant branches and writes nothing.');
|
|
16543
16773
|
console.log('--summary prints compact counts, removals/tombstones, errors, skipped items, and warnings.');
|
|
16774
|
+
console.log('`sync doctor` is read-only. It assembles local HEAD, origin HEAD, platform last sync,');
|
|
16775
|
+
console.log('staging shadow risk, promotion freshness, repository mismatch, and the next safe action.');
|
|
16544
16776
|
console.log('');
|
|
16545
16777
|
console.log('Agent safety gates (each exits non-zero instead of printing a wall of JSON):');
|
|
16546
16778
|
console.log(' --safe THE RECOMMENDED PATH on a variant branch. Expands to');
|
|
@@ -17083,6 +17315,11 @@ async function main() {
|
|
|
17083
17315
|
return;
|
|
17084
17316
|
}
|
|
17085
17317
|
|
|
17318
|
+
if (command === 'components' && subcommand === 'sync' && String(args._ && args._[2] || '').toLowerCase() === 'doctor') {
|
|
17319
|
+
await syncDoctorComponentsCommand(args);
|
|
17320
|
+
return;
|
|
17321
|
+
}
|
|
17322
|
+
|
|
17086
17323
|
if (command === 'components' && subcommand === 'sync') {
|
|
17087
17324
|
await syncComponentsCommand(args);
|
|
17088
17325
|
return;
|
package/package.json
CHANGED
|
@@ -92,6 +92,12 @@ reference named after it.
|
|
|
92
92
|
"branch" or "verified"; say what was actually proven: Test pass, browser journey, corpus measurement,
|
|
93
93
|
sync mutation, or ticket lifecycle state. (`component-resolution.md`, `branch-variants.md`,
|
|
94
94
|
`development-loop.md`, `support-tickets.md`)
|
|
95
|
+
- **Embeddable verification is browser verification.** For page, widget, form, upload, or other
|
|
96
|
+
browser-facing changes, mint a URL with `remits-cli token` and drive it with `playwright-cli`.
|
|
97
|
+
Prefer this over `curl`: `curl` can prove an HTTP response or inspect an action payload, but it does
|
|
98
|
+
not run JavaScript, Alpine, CSS/assets, redirects, cookies/session handling, uploads, iframes,
|
|
99
|
+
shadow-DOM placement, or websocket behavior. (`development-loop.md`,
|
|
100
|
+
`docs/front-stage/components/embeddable-components.md`, `docs/front-stage/features/web-browser-automation.md`)
|
|
95
101
|
- **Land only from trunk or a real variant branch.** A per-agent/feature branch (`components status` says
|
|
96
102
|
`FEATURE BRANCH … [subscription-fallback]`) is safe to stage and run from — it resolves the same world
|
|
97
103
|
as its target — but `components commit`/`sync` refuse it. Merge into the branch it resolves and land
|
|
@@ -107,6 +113,11 @@ reference named after it.
|
|
|
107
113
|
updating, renaming, and **hard-deleting** rows. Prefer the observable
|
|
108
114
|
`git commit → git push → components sync → git pull`. On trunk it refuses before any git write unless
|
|
109
115
|
you pass `--yes`. (`component-integrity.md`)
|
|
116
|
+
- **Do not hand-roll sync watchers.** A sync is a write; an observation loop must never start a fresh
|
|
117
|
+
`components sync`. Use `remits-cli components sync doctor` and `components promotion` to read sync /
|
|
118
|
+
overlay state. If a sync times out client-side, the result is unknown, not failed; observe before any
|
|
119
|
+
retry. Do not use `setsid`, `nohup`, `disown`, `tmux`, or shell-specific detach tricks to make sync
|
|
120
|
+
lifecycle work. (`development-loop.md`, `branch-variants.md`)
|
|
110
121
|
- **After anyone lands, ask whether your lane is stale: `remits-cli components status`.** A landing clears
|
|
111
122
|
only the lander's lane; yours keeps shadowing their new rows with content staged from the old base.
|
|
112
123
|
`LANDED SINCE YOUR BASE` / `STALE OVERLAY` mean pull, re-stage, then verify — a pass against a stale
|
|
@@ -140,6 +151,12 @@ reference named after it.
|
|
|
140
151
|
(`component-resolution.md`, `command-reference.md`)
|
|
141
152
|
- **Host and data mode are two independent decisions.** `--base-url` picks the Remits host,
|
|
142
153
|
`--data-mode` picks the data segment on it. Neither implies the other. (`command-reference.md`)
|
|
154
|
+
- **Localhost being down is not a verification blocker.** `remits-cli` can talk to any reachable Remits
|
|
155
|
+
host, including the deployed production host, by passing `--base-url`. If `http://localhost:8080`
|
|
156
|
+
refuses a connection, retry the same stage/test/tool/status command against the intended deployed host
|
|
157
|
+
with the same account, branch, workspace and data-mode facts; do not stop unless no reachable host or
|
|
158
|
+
valid session exists. A deployed host can still run test-lane verification: `--base-url` selects the
|
|
159
|
+
server, while `test run` still defaults to `--data-mode test`. (`command-reference.md`)
|
|
143
160
|
- **`test run` ignores the stored session data lane.** It defaults to `test` even when `whoami` shows
|
|
144
161
|
the session parked on prod; production Test runs require explicit prod provenance (`--data-mode prod`)
|
|
145
162
|
or Test source declaring `dataMode 'prod'` / `[dataMode:'prod']`. Check returned `dataModeSource`
|
|
@@ -163,6 +180,12 @@ reference named after it.
|
|
|
163
180
|
component (preferred, because it becomes regression protection) or a browser flow through
|
|
164
181
|
`remits-cli token`. "Just do it" and "that's fine, commit it" are not evidence. If you genuinely
|
|
165
182
|
cannot verify, say what you would need and ask. (`development-loop.md`)
|
|
183
|
+
- **Match the proof to the claim.** A mocked Test is a seam proof; a sync packet is durable source
|
|
184
|
+
movement; a token/browser run is journey proof; a corpus consistency report is repeatability proof. If
|
|
185
|
+
the request says "same file twice", "repeatability", "consistency", "same answer", or "model variance",
|
|
186
|
+
start with a corpus/evaluation or other repeated live measurement under an explicit AI budget; mocked
|
|
187
|
+
seam suites are guardrails, not acceptance. (`development-loop.md`, `component-resolution.md`,
|
|
188
|
+
`docs/front-stage/components/test-components.md`)
|
|
166
189
|
- **`remits-cli evidence` answers "what have I actually run, and in which world?"** Every stage, test,
|
|
167
190
|
token, tool and sync appends one world-stamped line automatically, per actor. Nothing to start,
|
|
168
191
|
nothing to satisfy. Read it before you re-run something, and quote it when you report what you
|
|
@@ -216,7 +239,8 @@ remits-cli components status # trunk or variant checkout, staging lane, wor
|
|
|
216
239
|
remits-cli tools # which tools this account actually has (tools are per-account)
|
|
217
240
|
```
|
|
218
241
|
|
|
219
|
-
plus the repo's `account-
|
|
242
|
+
plus the repo's `account-boot.json` → `resolution` block for the account's shape (`account-info.json`
|
|
243
|
+
only when you need full inventory detail).
|
|
220
244
|
For a workflow-shaped request, rely on the automatic `remits-cli evidence` trail unless someone else needs
|
|
221
245
|
a checkable verdict. Only then start `remits-cli verify start --summary "..."`, declare claims, and keep
|
|
222
246
|
that envelope active through stage/test/token/sync.
|
|
@@ -228,7 +252,8 @@ non-default host).
|
|
|
228
252
|
`~/.remits-cli/account-repos.json` (every local repo, plus the reserved `platform` entry for the core
|
|
229
253
|
platform clone), `~/.remits-cli/sessions.json` (auth state and lanes), `~/.remits-cli/agents.json`
|
|
230
254
|
(agents registered here), `./.remits-cli/actors/<local-agent>/tool-responses/<callId>.json` (the full
|
|
231
|
-
tool payload),
|
|
255
|
+
tool payload), the repo's `account-boot.json`, and `account-info.json` when compact context is not enough.
|
|
256
|
+
`cli-state.md` maps every remaining question to its
|
|
232
257
|
file, including legacy flat `.remits-cli/` fallbacks.
|
|
233
258
|
Repo-local session JSONL is intentionally a bounded audit log: request payloads and ordinary response
|
|
234
259
|
bodies are summarized with keys, sizes, hashes, and redaction markers. Open actor-scoped tool response
|
|
@@ -242,7 +267,7 @@ Keep support and development sessions lean:
|
|
|
242
267
|
`mcp_component_view` / `mcp_component_grep` are fallback surfaces for agents without that checkout,
|
|
243
268
|
or for confirming what the live DB has stored after you already understand the files. For a ticket
|
|
244
269
|
with `implementationAccountId`, resolve that account's indexed repo first, pull the appropriate
|
|
245
|
-
branch when the checkout is clean, and inspect `account-
|
|
270
|
+
branch when the checkout is clean, and inspect `account-boot.json` + relevant `components/` there.
|
|
246
271
|
- Do not read entire `.remits-cli/actors/<local-agent>/sessions/*.jsonl` (or legacy flat session logs) or
|
|
247
272
|
large tool response files unless you first narrow to the relevant request, endpoint, tool, or ticket.
|
|
248
273
|
- Prefer targeted Firestore queries: use `documentId`, tight `filters`, narrow `fields`, and low `limit`
|
|
@@ -23,13 +23,14 @@
|
|
|
23
23
|
against, and where a fix belongs are answered by the account's structure — never by its name.
|
|
24
24
|
|
|
25
25
|
The account model itself — types, component inheritance, primary vs membership edges, the three independent
|
|
26
|
-
edge properties, the user model — is in
|
|
26
|
+
edge properties, the user model — is summarized in `platform-core.md` and in depth in
|
|
27
27
|
`features/account-management.md` (`mcp_get_guide`). What follows is only what changes **what you type**.
|
|
28
28
|
|
|
29
29
|
### Read the shape first
|
|
30
30
|
|
|
31
|
-
`account-
|
|
32
|
-
place these facts appear. Field-by-field detail is
|
|
31
|
+
`account-boot.json` (in a repo), `account-info.json` (full local inventory), and `mcp_account_view`
|
|
32
|
+
(remotely) all carry a `resolution` block — the one place these facts appear. Field-by-field detail is
|
|
33
|
+
under **`mcp_account_view`** in `tool-reference.md`. The
|
|
33
34
|
four that decide a CLI action:
|
|
34
35
|
|
|
35
36
|
| Read | To decide |
|
|
@@ -57,7 +58,8 @@ Two more, easily confused: top-level **`componentBranches`** lists the variant b
|
|
|
57
58
|
current before reading source or editing. Run `git fetch origin`; when the tree is clean,
|
|
58
59
|
`git pull --ff-only origin <branch>`; then confirm `git log origin/<branch>..<branch>` and
|
|
59
60
|
`git log <branch>..origin/<branch>` are both empty. A worktree can have an isolated staging workspace
|
|
60
|
-
and still be based on a stale commit. Then read `account-
|
|
61
|
+
and still be based on a stale commit. Then read `account-boot.json` and inspect relevant `components/`
|
|
62
|
+
directly; use `account-info.json` only for full inventory detail.
|
|
61
63
|
- **Inside one repo but supporting a different account**: switch to that account's indexed repo if it
|
|
62
64
|
exists. For tickets, prefer `implementationAccountId` / `implementationAccountName` over the reporting
|
|
63
65
|
`accountId` when choosing that repo; a subscriber or client often reports the symptom while the
|
|
@@ -84,7 +86,7 @@ still go to the test lane. `Object.testMode` /
|
|
|
84
86
|
`Event.testMode` / `Alert.testMode` (and `testMode` inside test-lane Audit documents) identify lifecycle
|
|
85
87
|
rows in the test data lane. Agent-facing surfaces expose these fields:
|
|
86
88
|
|
|
87
|
-
- `account-info.json`, `account-hierarchy.json`, and `mcp_account_view`: `resolution.testAccount` for the
|
|
89
|
+
- `account-boot.json`, `account-info.json`, `account-hierarchy.json`, and `mcp_account_view`: `resolution.testAccount` for the
|
|
88
90
|
described account, and `testAccount` on returned hierarchy nodes.
|
|
89
91
|
- `mcp_account_user_admin`: `testAccount` on `hierarchy`, `account`, and `account_create` results;
|
|
90
92
|
`testUser` on `users` / `user` results.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
- [Which world does your working tree resolve? (read this before you run anything)](#which-world-does-your-working-tree-resolve-read-this-before-you-run-anything)
|
|
13
13
|
- [Two levers, two different questions](#two-levers-two-different-questions)
|
|
14
14
|
- [The SDLC is identical on a variant branch](#the-sdlc-is-identical-on-a-variant-branch)
|
|
15
|
+
- [Long-running variant sync](#long-running-variant-sync)
|
|
15
16
|
- [Where am I in the promotion loop?](#where-am-i-in-the-promotion-loop)
|
|
16
17
|
- [Subscribing, unsubscribing, retiring](#subscribing-unsubscribing-retiring)
|
|
17
18
|
- [Danger profile on a variant branch (different, not absent)](#danger-profile-on-a-variant-branch-different-not-absent)
|
|
@@ -237,7 +238,7 @@ remits-cli test run --test "Invoice Tests" # the feature_bran
|
|
|
237
238
|
remits-cli test run --test "Invoice Tests" --as-account 101 # ...as the real subscriber
|
|
238
239
|
git add -A && git commit -m "..." && git push origin feature_branch
|
|
239
240
|
remits-cli components sync --dry-run # inspect overrides/additions/tombstones without writes
|
|
240
|
-
remits-cli components sync
|
|
241
|
+
remits-cli components sync --safe --yes # agent/noninteractive: writes ComponentVariant overlays ONLY
|
|
241
242
|
```
|
|
242
243
|
|
|
243
244
|
`components stage` validates changed runtime-compiled source through the active branch/workspace lane,
|
|
@@ -252,6 +253,41 @@ for you, and merging a branch promotes its **deletions** as hard deletes. Do not
|
|
|
252
253
|
`remits-cli components sync --summary --timeout-ms 300000`; the platform may need longer than the default
|
|
253
254
|
60 seconds to create rows, push rename/meta commits, and regenerate account metadata.
|
|
254
255
|
|
|
256
|
+
### Long-running variant sync
|
|
257
|
+
|
|
258
|
+
A variant sync writes durable `ComponentVariant` overlays only. The proof that subscribers can resolve the
|
|
259
|
+
new committed branch source is the overlay set's computed SHA, not the fact that your local process once
|
|
260
|
+
started a sync.
|
|
261
|
+
|
|
262
|
+
Use this shape for agent landings:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
git push origin <branch>
|
|
266
|
+
remits-cli components sync --safe --yes
|
|
267
|
+
git pull --ff-only origin <branch>
|
|
268
|
+
remits-cli components sync doctor
|
|
269
|
+
remits-cli components promotion --branch <branch> --no-fail
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`--safe --yes` skips the interactive prompt after the safe dry-run gates pass; it does not skip the gates.
|
|
273
|
+
If the client times out, the result is **unknown**. Do not immediately re-run `components sync`, and never
|
|
274
|
+
write a polling loop that invokes it. Observe with `components sync doctor` and
|
|
275
|
+
`components promotion --branch <branch> --no-fail`; a read loop may inspect, but only one command should
|
|
276
|
+
start the write.
|
|
277
|
+
|
|
278
|
+
Read the promotion report precisely:
|
|
279
|
+
|
|
280
|
+
- `branch HEAD` in the git section says what the remote branch currently points at.
|
|
281
|
+
- `overlays computed from` in the platform section says what subscribers resolve right now.
|
|
282
|
+
- A cached status or a local process exit is not proof that overlays advanced.
|
|
283
|
+
- Immediately after a sync, metadata refresh and compile caches can lag by a moment; committed-variant
|
|
284
|
+
verification still has to clear or avoid staged overlays first.
|
|
285
|
+
|
|
286
|
+
Host and account provenance are part of this proof. A subscriber can be subscribed to a branch that
|
|
287
|
+
currently stores zero overlays, which means the selected branch resolves trunk behavior. Before comparing
|
|
288
|
+
uploads or browser runs, read the token/test/tool world: host, execution account, component branch,
|
|
289
|
+
`variantBranchSource`, data lane, and resolved database.
|
|
290
|
+
|
|
255
291
|
### Where am I in the promotion loop?
|
|
256
292
|
|
|
257
293
|
```bash
|
|
@@ -42,6 +42,10 @@ Treat host selection and data mode as two separate decisions:
|
|
|
42
42
|
|
|
43
43
|
- `--base-url` chooses the Remits host: localhost vs a deployed environment.
|
|
44
44
|
- `--data-mode` chooses the data segment on that host: `test` vs `prod`.
|
|
45
|
+
- A connection failure to `http://localhost:8080` only says the local back-stage app is not reachable.
|
|
46
|
+
It does **not** mean staging, testing, tokens, or investigation are blocked. If a deployed Remits host
|
|
47
|
+
is the right target, pass it explicitly with `--base-url` and keep the same account/branch/workspace
|
|
48
|
+
and `--data-mode` facts.
|
|
45
49
|
|
|
46
50
|
Examples:
|
|
47
51
|
|
|
@@ -49,11 +53,20 @@ Examples:
|
|
|
49
53
|
# Deployed prod host, but test data segment
|
|
50
54
|
remits-cli tools --base-url https://your-prod-host --data-mode test
|
|
51
55
|
|
|
56
|
+
# Deployed prod host, test data, staged component verification
|
|
57
|
+
remits-cli components stage --workset --base-url https://your-prod-host
|
|
58
|
+
remits-cli test run --test "Statement Reader Calculations" --base-url https://your-prod-host
|
|
59
|
+
|
|
52
60
|
# Localhost host, but prod data segment on that localhost instance
|
|
53
61
|
remits-cli tool --base-url http://localhost:8080 --name mcp_account_view --data-mode prod
|
|
54
62
|
```
|
|
55
63
|
|
|
56
|
-
Do not assume `--data-mode prod` implies the deployed prod host, or that `--data-mode test` implies
|
|
64
|
+
Do not assume `--data-mode prod` implies the deployed prod host, or that `--data-mode test` implies
|
|
65
|
+
localhost. Likewise, do not assume localhost is required because the current checkout is a back-stage
|
|
66
|
+
repo or because a previous command used localhost. If host matters, read `~/.remits-cli/sessions.json`,
|
|
67
|
+
`remits-cli whoami`, or the recent `remits-cli evidence` world blocks, then pass `--base-url` explicitly.
|
|
68
|
+
Only call verification blocked after trying the intended reachable host and finding that no authenticated
|
|
69
|
+
session or usable network path exists.
|
|
57
70
|
|
|
58
71
|
### Tool Execution Lifecycle
|
|
59
72
|
|
|
@@ -233,6 +246,7 @@ remits-cli components lanes [--json] # every indexed sta
|
|
|
233
246
|
remits-cli components entries --lane-id <id> [--json|--verbose] # authoritative staged files for one lane
|
|
234
247
|
remits-cli components clear [--branch <name>] [--component-type <type>] [--component-id <id>] [--all] [--json|--verbose] # id alone scopes to one component when unambiguous (ids are type-local; add --component-type if the same id is staged in multiple families); no filter clears the whole branch scope; --all forces the full wipe
|
|
235
248
|
remits-cli components sync [--safe [--yes]] [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--create-variant-branch] [--summary] [--changed-only [--changed-since <ref>]] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
|
|
249
|
+
remits-cli components sync doctor [--branch <name>] [--json] # read-only: local/remote/platform sync facts, staging shadow risk, promotion freshness, recommended next action
|
|
236
250
|
remits-cli components commit [--yes] [--safe] [--allow-shared-branch] [--create-variant-branch] [--message|-m "msg"] [--data-mode test|prod] [--force-tombstones] [--json [--summary]] # phase 1 merge-stages + compile-validates changed source (never reconciles the lane); on TRUNK refuses before any git write unless --yes; --safe gates variant sync writes
|
|
237
251
|
remits-cli components branches [--json] # branches carrying committed variants, with counts + drift
|
|
238
252
|
remits-cli components branch <name> [--json] # one branch: owner account, overridden / added / removed, drift flags, subscribers
|
|
@@ -566,6 +580,10 @@ For tests specifically:
|
|
|
566
580
|
- `--summary` on `components sync` prints compact counts plus named updated (with the fields that
|
|
567
581
|
changed), renamed, skipped, removal/tombstone, error, and gate details instead of the full payload. A
|
|
568
582
|
trunk sync reports an untouched component under `unchanged`, not `updated`.
|
|
583
|
+
- `components sync doctor` does not mutate. Use it when a sync timed out, status/promotion disagree, or
|
|
584
|
+
you need to know whether staged entries would shadow committed-variant verification. It prints local
|
|
585
|
+
`HEAD`, `origin/<branch>`, platform last-sync SHA, overlay freshness, repository mismatch, and a
|
|
586
|
+
recommended next action.
|
|
569
587
|
- `--json` on `components stage`, `components sync`, `components commit`, and `tool` prints one
|
|
570
588
|
parseable JSON document to stdout. Safety banners and prose go to stderr, and sync safety-gate failures
|
|
571
589
|
are reported inside `gateViolations` with a non-zero exit code instead of appending prose after the JSON.
|
|
@@ -90,6 +90,7 @@ every live component present at its real id, and nothing extra.
|
|
|
90
90
|
| `remits-cli components stage` (alias: deprecated `push`) | **Redis staging cache only.** Never mutates the DB or git. The safe iteration surface. A plain stage or `--workset` RECONCILES the lane (entries outside the manifest are dropped); `--changed-only` merges. | none for the DB; a lane you share with another agent is reconciled by the first two |
|
|
91
91
|
| `remits-cli components status` | Reads this lane's staging scope (account/user/branch/workspace) and branch resolution, and lists every other lane on the branch. | none |
|
|
92
92
|
| `remits-cli components clear` | Clears THIS lane's staging cache without changing DB or git. Never touches another workspace lane. | none |
|
|
93
|
+
| `remits-cli components sync doctor` | Reads local git, platform status, staging freshness, repository match, and promotion/overlay freshness. It is the safe diagnostic when sync state is confusing. | none |
|
|
93
94
|
| `remits-cli components sync` **on trunk** | **Server-side git→DB reconcile of the whole account** (create/update/**delete**/rename). Reads the pushed remote; ignores local files. | **high** |
|
|
94
95
|
| `remits-cli components sync` **on a variant branch** | Writes `ComponentVariant` overlays for that branch only. Never touches trunk rows or the account's trunk branch. When the checkout identifies a subscribing account, the branch-local `account-info.json` is refreshed for that subscriber; `--dry-run` reports the plan without writes. | medium (a missing file becomes a **tombstone** that hides the component from subscribers) |
|
|
95
96
|
| `remits-cli components commit` | **One shot:** changed-source compile validation (a `--changed-only` MERGE stage, so it never reconciles the lane) + `git add -A` + commit + `git push` + **`components sync`** + `git pull --ff-only`. Blindly stages the *entire* working tree (including any drift) and reconciles it into prod. Inherits the danger of whichever sync mode the branch selects. | **highest on trunk** |
|
|
@@ -64,6 +64,17 @@ source-layer facts the command observed. A staged test packet is proof of the st
|
|
|
64
64
|
is proof of a source transition; a token packet is proof of the browser token's resolution tuple. Those
|
|
65
65
|
are not interchangeable.
|
|
66
66
|
|
|
67
|
+
Use proof words narrowly:
|
|
68
|
+
|
|
69
|
+
| Evidence | What it proves | What it does NOT prove |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `components stage --workset` | The platform accepted the staged workset and compile-checked changed runtime source | Any committed component changed, or any user journey works |
|
|
72
|
+
| `test run` with staged entries | The selected Test passed against this staging lane/world | The committed variant/trunk source passes |
|
|
73
|
+
| `components sync` / sync packet | Durable source moved from the git remote into trunk rows or variant overlays | Browser/upload behavior, or repeated live AI consistency |
|
|
74
|
+
| `components promotion` / `sync doctor` | Which remote SHA and overlay SHA the platform reports now | That a workflow was exercised after the overlay advanced |
|
|
75
|
+
| `token` / browser flow | The browser entry point resolved a host/account/lane/source tuple and the journey worked there | Persisted document fields are stable or equal across repeated runs |
|
|
76
|
+
| `corpus consistency` / repeated live measurement | The same artifact's recorded metrics were stable or unstable across runs in that world | A mocked seam suite caught all customer-facing variance |
|
|
77
|
+
|
|
67
78
|
Use `remits-cli verify report` before summarizing the work. It will say when the evidence only covered
|
|
68
79
|
staged source, when committed variant/trunk proof is missing, when the manifest world does not match the
|
|
69
80
|
packet world, or when later packet facts made an earlier proof stale. Packets carry a lane content hash,
|
|
@@ -159,6 +159,11 @@ Two ways to prove it:
|
|
|
159
159
|
Use a Test when the behavior can be asserted programmatically, a browser when the change is visual.
|
|
160
160
|
Often both.
|
|
161
161
|
|
|
162
|
+
For Embeddables, prefer `playwright-cli` over `curl`. A `curl` request can confirm the server returned
|
|
163
|
+
something or expose a JSON/action payload, but it is not evidence that the user-facing page works:
|
|
164
|
+
JavaScript, Alpine initialization, assets, cookies/session state, redirects, file controls, iframe/embed
|
|
165
|
+
placement, and websocket updates all require a browser.
|
|
166
|
+
|
|
162
167
|
**Never skip verification.** "Just do it" and "that's fine, commit it" are not evidence. If you genuinely
|
|
163
168
|
cannot verify — no Test component, no relevant embeddable — say what you would need and ask how the user
|
|
164
169
|
wants to proceed rather than reporting the work as done.
|
|
@@ -172,7 +177,7 @@ wants to proceed rather than reporting the work as done.
|
|
|
172
177
|
This is how every development task should flow:
|
|
173
178
|
|
|
174
179
|
#### Step 1: Understand the Request
|
|
175
|
-
Read the user's request. If you may need a repo other than the current one, read `~/.remits-cli/account-repos.json` first. Then review `account-
|
|
180
|
+
Read the user's request. If you may need a repo other than the current one, read `~/.remits-cli/account-repos.json` first. Then review `account-boot.json` and `README.md` to understand the account shape and component routing inventory. Read `account-info.json` only when the compact file lacks detail you need. Read the source of any component you'll modify before changing it.
|
|
176
181
|
|
|
177
182
|
**Establish a steady git baseline before the first edit.** The platform syncs from the GitHub remote, not
|
|
178
183
|
from your local files, and a worktree can be stale even when its staging lane is isolated. In the checkout
|
|
@@ -191,14 +196,14 @@ that the branch is behind trunk or that overlays were computed from an old SHA,
|
|
|
191
196
|
code. A workspace prevents staged-cache collisions; it does not make a stale branch current.
|
|
192
197
|
|
|
193
198
|
**Establish the account's shape too, not just its components.** Read the `resolution` block in
|
|
194
|
-
`account-
|
|
199
|
+
`account-boot.json` (or `mcp_account_view`): the account `type` decides whether this repo is even the right
|
|
195
200
|
place to change code, `resolution.relationships` shows whether the account has more than one parent (and
|
|
196
201
|
which link carries a branch/namespace/host), and `resolvedDatabaseName` tells you where its data actually
|
|
197
202
|
lands. See `account-targeting.md` and `features/account-management.md` (`mcp_get_guide`).
|
|
198
203
|
|
|
199
204
|
**Also establish which world you are working in.** `remits-cli components status` reports whether the
|
|
200
205
|
working tree is a **trunk** checkout or a **variant branch** checkout — which decides both what your test
|
|
201
|
-
runs resolve and what a sync writes. If `account-
|
|
206
|
+
runs resolve and what a sync writes. If `account-boot.json` carries a `componentBranches` section, branch
|
|
202
207
|
variants of these components exist: editing an origin component will drift them, so check
|
|
203
208
|
`remits-cli components branches` before changing shared code. See `branch-variants.md`.
|
|
204
209
|
|
|
@@ -265,7 +270,7 @@ the file. Omit the key; the platform fills it in on sync:
|
|
|
265
270
|
```yaml
|
|
266
271
|
# components/embeddables/new_MerchantPortal.meta.yml — no `id:` yet
|
|
267
272
|
name: Merchant Portal
|
|
268
|
-
summary: One-line statement of what this component is for. This is the compact text account-
|
|
273
|
+
summary: One-line statement of what this component is for. This is the compact text account-boot.json uses first.
|
|
269
274
|
description: |
|
|
270
275
|
Longer technical description with line-number references to the key logic.
|
|
271
276
|
path: /page/merchant-portal # Readers and Embeddables only
|
|
@@ -515,6 +520,10 @@ playwright-cli fill "#amount" "500.00"
|
|
|
515
520
|
playwright-cli eval "() => document.querySelector('.total-amount').textContent"
|
|
516
521
|
```
|
|
517
522
|
|
|
523
|
+
Use this browser path for Embeddable acceptance. `curl` is acceptable for narrow diagnostics such as
|
|
524
|
+
checking an HTTP status or inspecting a server-rendered payload, but it does not prove the page initializes
|
|
525
|
+
or behaves correctly in a browser.
|
|
526
|
+
|
|
518
527
|
The `testMode` metadata confirms you're testing against staged changes, not production.
|
|
519
528
|
|
|
520
529
|
**Two different token keys come back, for two different jobs.** When `--path` resolves to an
|
|
@@ -568,7 +577,7 @@ If the work is tied to a support ticket:
|
|
|
568
577
|
|
|
569
578
|
Before committing, update metadata so the next session understands what changed:
|
|
570
579
|
|
|
571
|
-
1. **`.meta.yml` sidecars** — Update `summary`, `description`, and `mermaid` for each modified component. `summary` is what drives the compact component description in generated `account-
|
|
580
|
+
1. **`.meta.yml` sidecars** — Update `summary`, `description`, and `mermaid` for each modified component. `summary` is what drives the compact component description in generated `account-boot.json`; `description` is the fallback when no summary is set and is capped there. Preserve or explicitly revise dated decision notes; do not delete the evidence the next agent needs.
|
|
572
581
|
2. **`README.md`** — If the change affects account-level capabilities or workflows.
|
|
573
582
|
3. **New components** — Always fill in `.meta.yml` immediately.
|
|
574
583
|
|
|
@@ -630,12 +639,17 @@ IDs or when unexpected deletes/renumbers are present.
|
|
|
630
639
|
Only after those checks pass, and only when the user intends to promote the repo to the platform database:
|
|
631
640
|
|
|
632
641
|
```bash
|
|
633
|
-
# On a VARIANT branch
|
|
642
|
+
# On a VARIANT branch in an agent/noninteractive session — dry-runs first, refuses surprises,
|
|
643
|
+
# and skips only the confirmation prompt, not the gates.
|
|
644
|
+
remits-cli components sync --safe --yes
|
|
645
|
+
git pull --ff-only origin <branch>
|
|
646
|
+
|
|
647
|
+
# On a VARIANT branch in a human interactive shell — same gates, then asks before writing.
|
|
634
648
|
remits-cli components sync --safe
|
|
635
649
|
git pull --ff-only origin <branch>
|
|
636
650
|
|
|
637
651
|
# On TRUNK — there is no plan to gate, so --safe explains what a trunk reconcile does and needs --yes.
|
|
638
|
-
remits-cli components sync
|
|
652
|
+
remits-cli components sync --safe --yes
|
|
639
653
|
git pull --ff-only origin <branch>
|
|
640
654
|
```
|
|
641
655
|
|
|
@@ -655,14 +669,29 @@ remits-cli components sync --safe --expected-removed action:50
|
|
|
655
669
|
|
|
656
670
|
`--force-tombstones` stays explicit and human-owned. Never pass it to get past a refusal.
|
|
657
671
|
|
|
672
|
+
If sync state is confusing, use the read-only diagnostic instead of building shell loops:
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
remits-cli components sync doctor
|
|
676
|
+
remits-cli components promotion --branch <branch> --no-fail
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
`components sync doctor` assembles local `HEAD`, `origin/<branch>`, the platform's last synced SHA,
|
|
680
|
+
promotion freshness, staging shadow risk, repository mismatch, and a recommended next action. A client
|
|
681
|
+
timeout does **not** prove the sync failed; it means the result is unknown. Observe before retrying.
|
|
682
|
+
Never put `components sync` inside a polling loop, and do not use shell detach tricks (`setsid`, `nohup`,
|
|
683
|
+
`disown`, `tmux`, ...). A loop may read status/promotion/doctor; it must never start writes.
|
|
684
|
+
|
|
658
685
|
##### Verifying the COMMITTED variant, not your staging
|
|
659
686
|
|
|
660
687
|
After a sync, staged entries still win for CLI-scoped runs, so a test that passes may be testing your
|
|
661
|
-
staging rather than what you just committed. Clear the lane first
|
|
688
|
+
staging rather than what you just committed. Clear the lane first, then verify the subscriber/variant
|
|
689
|
+
world explicitly:
|
|
662
690
|
|
|
663
691
|
```bash
|
|
664
692
|
remits-cli components clear --all
|
|
665
693
|
remits-cli test run --test <id-or-name> --as-account <subscriber-id>
|
|
694
|
+
remits-cli components sync doctor
|
|
666
695
|
```
|
|
667
696
|
|
|
668
697
|
`remits-cli components sync` is the authoritative platform-sync step. It does not perform local git operations,
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
| Tool parameters rejected | Tool schemas may be cached. Run `remits-cli tools` to refresh `.remits-cli/shared/tools/tools.json` with latest schemas. |
|
|
29
29
|
| Tool response missing | Run `remits-cli doctor local-state`, then check `./.remits-cli/actors/<local-agent>/tool-responses/` and any legacy flat `./.remits-cli/tool-responses/` fallback it reports. |
|
|
30
30
|
| Long-running tool times out | For `mcp_run_action`/`mcp_run_agent`, use the tool's own `executionMode:"async"` and poll with a `controlAction:"status"` call (see `command-reference.md` → *Tool Execution Lifecycle*). For other long tools without their own async, use `remits-cli tool --async true` and poll `remits-cli tool status --call-id <callId>`. `--timeout-ms` only adjusts the per-request HTTP timeout; it is not a substitute for async. |
|
|
31
|
+
| `components sync` timed out, or you are unsure whether overlays advanced | Treat the result as **unknown**, not failed. Run `remits-cli components sync doctor` and `remits-cli components promotion --branch <branch> --no-fail`. Do not put `components sync` in a polling loop and do not use shell detach tricks; observation may poll, writes may not. |
|
|
31
32
|
| Need to continue tracking a long Action or Agent after terminal disconnect | Read `./.remits-cli/actors/<local-agent>/tool-responses/<callId>.json` for the returned `actionRunId`/`agentRunId`/`sessionId`/`threadGroupingId` (or the legacy flat fallback if `doctor local-state` reports it there). Re-poll the run with a `controlAction:"status"` call carrying that `actionRunId`/`agentRunId`, or inspect the agent session via `mcp_ai_session_search` with the `sessionId`. |
|
|
32
33
|
| Staged change has no effect in a live (non-CLI) run | Staged overrides resolve only under a CLI TestMode (`branchName`+`cliUserId`). Live webhooks and other non-CLI runtime paths still use the DB (trunk, or the account's subscribed variant). `commit` to make it durable. See `component-resolution.md`. |
|
|
33
34
|
| Need to know an account's shape (role, type, parents, namespace, branch, host/login routes) | Read `resolution` — from the repo's `account-info.json`, or `mcp_account_user_admin` `action:'account'` (cheap), or `mcp_account_view` (full inventory): `role`/`summary`, `type`, `resolvedDatabaseName`, `domainName`/`resolvedDomainName`, `authPath`/`targetPath`, `relationships`, `componentBranch`, plus top-level `componentBranches`. Never infer structure from the account's name. |
|