overlord-cli 0.2605150751.0 → 0.2605151717.0
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 +7 -2
- package/bin/_cli/protocol.mjs +414 -0
- package/package.json +1 -1
- package/plugins/claude/skills/overlord-ticket/SKILL.md +11 -1
- package/plugins/cursor/skills/overlord-ticket/SKILL.md +11 -1
- package/plugins/overlord/scripts/overlord-mcp.mjs +1 -3
- package/plugins/overlord/skills/overlord-ticket/SKILL.md +11 -1
package/README.md
CHANGED
|
@@ -111,9 +111,10 @@ Agents can find docs here: https://www.ovld.ai/docs/for-agents
|
|
|
111
111
|
|
|
112
112
|
- `auth-status` - return machine-readable auth status for agent runtimes
|
|
113
113
|
- `discover-project` - resolve a project from the current (or given) working directory
|
|
114
|
-
- `attach` - start a ticket session and return full working context
|
|
114
|
+
- `attach` - start a ticket session, create a local git checkpoint per executing objective, and return full working context
|
|
115
115
|
- `connect` - start a lightweight session without full context
|
|
116
116
|
- `load-context` - read ticket context without creating a session
|
|
117
|
+
- `revert` - restore the local working tree to an objective checkpoint after fetching its checkpoint row
|
|
117
118
|
- `search-tickets` - find tickets by keyword, status, project, creator, or update date
|
|
118
119
|
- `create` - create a draft ticket without attaching (standalone or follow-up)
|
|
119
120
|
- `prompt` - create a ticket and attach to it immediately (`spawn` is a backward-compatible alias)
|
|
@@ -125,11 +126,15 @@ Agents can find docs here: https://www.ovld.ai/docs/for-agents
|
|
|
125
126
|
- `hook-event` - record lifecycle hook events such as `UserPromptSubmit` / Cursor `beforeSubmitPrompt` without a session key
|
|
126
127
|
- `read-context` - read shared persistent context for this ticket
|
|
127
128
|
- `write-context` - write shared persistent context for future sessions
|
|
128
|
-
- `deliver` -
|
|
129
|
+
- `deliver` - send artifacts/rationales and move the ticket to review
|
|
129
130
|
- `attachment-prepare-upload` - get a signed upload URL for an objective attachment
|
|
130
131
|
- `attachment-finalize-upload` - finalize an uploaded objective attachment row after storage upload
|
|
131
132
|
- `attachment-download-url` - get a signed download URL for an existing objective attachment
|
|
132
133
|
- `attachment-upload-file` - prepare, upload, and finalize a local objective attachment in one command
|
|
134
|
+
- `get-device` / `update-device` - register the caller machine (per organization + user + fingerprint) and rename its label
|
|
135
|
+
- `list-project-resources` / `add-project-resource` / `update-project-resource` - manage filesystem directories tied to a project device
|
|
136
|
+
|
|
137
|
+
Devices are keyed by **(organization, user, fingerprint)** so the same physical workstation can appear once per org session.
|
|
133
138
|
|
|
134
139
|
Use `create` for future work you want to track, `prompt` for work that should start immediately, and `record-work` for work that was already completed in chat and now needs a review ticket plus feed post.
|
|
135
140
|
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -548,6 +548,80 @@ function createLocalCheckpoint({ flags, kind = 'objective', objectiveId, snapsho
|
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
function snapshotLocalWorkingTree(repoRoot, parentSha, message) {
|
|
552
|
+
const tempIndex = path.join(repoRoot, '.git', `overlord-snap-index-${Date.now()}`);
|
|
553
|
+
const env = { ...process.env, NO_COLOR: '1', GIT_INDEX_FILE: tempIndex };
|
|
554
|
+
try {
|
|
555
|
+
execFileSync('git', ['-C', repoRoot, 'read-tree', 'HEAD'], { cwd: repoRoot, env });
|
|
556
|
+
execFileSync('git', ['-C', repoRoot, 'add', '-A'], { cwd: repoRoot, env });
|
|
557
|
+
const tree = execFileSync('git', ['-C', repoRoot, 'write-tree'], {
|
|
558
|
+
cwd: repoRoot,
|
|
559
|
+
env,
|
|
560
|
+
encoding: 'utf8'
|
|
561
|
+
}).trim();
|
|
562
|
+
if (!tree) throw new Error('git write-tree produced no output.');
|
|
563
|
+
return execFileSync(
|
|
564
|
+
'git',
|
|
565
|
+
['-C', repoRoot, 'commit-tree', tree, '-p', parentSha, '-m', message],
|
|
566
|
+
{
|
|
567
|
+
cwd: repoRoot,
|
|
568
|
+
env: { ...process.env, NO_COLOR: '1' },
|
|
569
|
+
encoding: 'utf8'
|
|
570
|
+
}
|
|
571
|
+
).trim();
|
|
572
|
+
} finally {
|
|
573
|
+
try {
|
|
574
|
+
fs.unlinkSync(tempIndex);
|
|
575
|
+
} catch {
|
|
576
|
+
/* ignore */
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function restoreLocalCheckpoint({ workspacePath, objectiveId, gitCommitId }) {
|
|
582
|
+
const repoRoot = resolveGitRepoRoot(workspacePath);
|
|
583
|
+
if (!repoRoot) throw new Error(`No git repository found at ${workspacePath}.`);
|
|
584
|
+
|
|
585
|
+
const ref = `refs/overlord/checkpoints/${objectiveId}`;
|
|
586
|
+
const target = gitCommitId
|
|
587
|
+
? runLocalCommand('git', ['-C', repoRoot, 'rev-parse', '--verify', `${gitCommitId}^{commit}`], {
|
|
588
|
+
cwd: repoRoot
|
|
589
|
+
}).trim()
|
|
590
|
+
: runLocalCommand('git', ['-C', repoRoot, 'rev-parse', '--verify', ref], {
|
|
591
|
+
cwd: repoRoot
|
|
592
|
+
}).trim();
|
|
593
|
+
if (!target) throw new Error(`No checkpoint exists for objective ${objectiveId}.`);
|
|
594
|
+
|
|
595
|
+
let safetyRef = null;
|
|
596
|
+
let safetySha = null;
|
|
597
|
+
try {
|
|
598
|
+
const headSha = runLocalCommand('git', ['-C', repoRoot, 'rev-parse', 'HEAD'], {
|
|
599
|
+
cwd: repoRoot
|
|
600
|
+
}).trim();
|
|
601
|
+
const stamp = new Date().toISOString().replace(/[^0-9A-Za-z]/g, '');
|
|
602
|
+
safetyRef = `refs/overlord/safety/${stamp}`;
|
|
603
|
+
safetySha = snapshotLocalWorkingTree(
|
|
604
|
+
repoRoot,
|
|
605
|
+
headSha,
|
|
606
|
+
`overlord pre-revert safety ${new Date().toISOString()}`
|
|
607
|
+
);
|
|
608
|
+
if (safetySha) {
|
|
609
|
+
runLocalCommand('git', ['-C', repoRoot, 'update-ref', safetyRef, safetySha], {
|
|
610
|
+
cwd: repoRoot
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
} catch {
|
|
614
|
+
safetyRef = null;
|
|
615
|
+
safetySha = null;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
runLocalCommand('git', ['-C', repoRoot, 'read-tree', '--reset', '-u', target], {
|
|
619
|
+
cwd: repoRoot
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
return { ref, gitCommitId: target, safetyRef, safetySha };
|
|
623
|
+
}
|
|
624
|
+
|
|
551
625
|
async function createAndRecordPendingCheckpoints({
|
|
552
626
|
attachData,
|
|
553
627
|
bearerToken,
|
|
@@ -1441,6 +1515,223 @@ async function protocolDiscoverProject(args) {
|
|
|
1441
1515
|
}
|
|
1442
1516
|
}
|
|
1443
1517
|
|
|
1518
|
+
// ---------------------------------------------------------------------------
|
|
1519
|
+
// get-device (identify / register the current device)
|
|
1520
|
+
// ---------------------------------------------------------------------------
|
|
1521
|
+
|
|
1522
|
+
async function protocolGetDevice(args) {
|
|
1523
|
+
const flags = parseFlags(args);
|
|
1524
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1525
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1526
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1527
|
+
|
|
1528
|
+
const deviceFingerprint = String(flags['device-fingerprint'] ?? process.env.OVERLORD_DEVICE_FINGERPRINT ?? '');
|
|
1529
|
+
if (!deviceFingerprint) {
|
|
1530
|
+
console.error('Error: --device-fingerprint is required (or set OVERLORD_DEVICE_FINGERPRINT)');
|
|
1531
|
+
process.exit(1);
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
const body = {
|
|
1535
|
+
deviceFingerprint,
|
|
1536
|
+
...(flags['device-hostname'] ? { deviceHostname: String(flags['device-hostname']) } : {}),
|
|
1537
|
+
...(flags['device-platform'] ? { devicePlatform: String(flags['device-platform']) } : {})
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
const data = await apiPost(
|
|
1541
|
+
platformUrl,
|
|
1542
|
+
bearerToken,
|
|
1543
|
+
localSecret,
|
|
1544
|
+
organizationId,
|
|
1545
|
+
'/api/protocol/get-device',
|
|
1546
|
+
body,
|
|
1547
|
+
timeoutMs
|
|
1548
|
+
);
|
|
1549
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1550
|
+
|
|
1551
|
+
if (data.device?.label) {
|
|
1552
|
+
process.stderr.write(`\nDEVICE_LABEL=${data.device.label}\n`);
|
|
1553
|
+
}
|
|
1554
|
+
if (data.device?.id) {
|
|
1555
|
+
process.stderr.write(`DEVICE_ID=${data.device.id}\n`);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
// ---------------------------------------------------------------------------
|
|
1560
|
+
// update-device (rename the device label)
|
|
1561
|
+
// ---------------------------------------------------------------------------
|
|
1562
|
+
|
|
1563
|
+
async function protocolUpdateDevice(args) {
|
|
1564
|
+
const flags = parseFlags(args);
|
|
1565
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1566
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1567
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1568
|
+
|
|
1569
|
+
const deviceFingerprint = String(flags['device-fingerprint'] ?? process.env.OVERLORD_DEVICE_FINGERPRINT ?? '');
|
|
1570
|
+
if (!deviceFingerprint) {
|
|
1571
|
+
console.error('Error: --device-fingerprint is required (or set OVERLORD_DEVICE_FINGERPRINT)');
|
|
1572
|
+
process.exit(1);
|
|
1573
|
+
}
|
|
1574
|
+
const label = typeof flags.label === 'string' ? flags.label.trim() : '';
|
|
1575
|
+
if (!label) {
|
|
1576
|
+
console.error('Error: --label is required');
|
|
1577
|
+
process.exit(1);
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const data = await apiPost(
|
|
1581
|
+
platformUrl,
|
|
1582
|
+
bearerToken,
|
|
1583
|
+
localSecret,
|
|
1584
|
+
organizationId,
|
|
1585
|
+
'/api/protocol/update-device',
|
|
1586
|
+
{ deviceFingerprint, label },
|
|
1587
|
+
timeoutMs
|
|
1588
|
+
);
|
|
1589
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
// ---------------------------------------------------------------------------
|
|
1593
|
+
// list-project-resources (list resource directories for a project)
|
|
1594
|
+
// ---------------------------------------------------------------------------
|
|
1595
|
+
|
|
1596
|
+
async function protocolListProjectResources(args) {
|
|
1597
|
+
const flags = parseFlags(args);
|
|
1598
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1599
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1600
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1601
|
+
|
|
1602
|
+
const projectId = typeof flags['project-id'] === 'string' ? flags['project-id'].trim() : '';
|
|
1603
|
+
if (!projectId) {
|
|
1604
|
+
console.error('Error: --project-id is required');
|
|
1605
|
+
process.exit(1);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
const deviceFingerprint = typeof flags['device-fingerprint'] === 'string'
|
|
1609
|
+
? flags['device-fingerprint'].trim()
|
|
1610
|
+
: (process.env.OVERLORD_DEVICE_FINGERPRINT?.trim() ?? '');
|
|
1611
|
+
|
|
1612
|
+
const body = {
|
|
1613
|
+
projectId,
|
|
1614
|
+
...(deviceFingerprint ? { deviceFingerprint } : {})
|
|
1615
|
+
};
|
|
1616
|
+
|
|
1617
|
+
const data = await apiPost(
|
|
1618
|
+
platformUrl,
|
|
1619
|
+
bearerToken,
|
|
1620
|
+
localSecret,
|
|
1621
|
+
organizationId,
|
|
1622
|
+
'/api/protocol/list-project-resources',
|
|
1623
|
+
body,
|
|
1624
|
+
timeoutMs
|
|
1625
|
+
);
|
|
1626
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
// ---------------------------------------------------------------------------
|
|
1630
|
+
// add-project-resource (register a directory for a project on this device)
|
|
1631
|
+
// ---------------------------------------------------------------------------
|
|
1632
|
+
|
|
1633
|
+
async function protocolAddProjectResource(args) {
|
|
1634
|
+
const flags = parseFlags(args);
|
|
1635
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1636
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1637
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1638
|
+
|
|
1639
|
+
const projectId = typeof flags['project-id'] === 'string' ? flags['project-id'].trim() : '';
|
|
1640
|
+
const directoryPath = typeof flags['directory'] === 'string'
|
|
1641
|
+
? flags['directory'].trim()
|
|
1642
|
+
: process.cwd();
|
|
1643
|
+
const deviceFingerprint = String(
|
|
1644
|
+
flags['device-fingerprint'] ?? process.env.OVERLORD_DEVICE_FINGERPRINT ?? ''
|
|
1645
|
+
);
|
|
1646
|
+
|
|
1647
|
+
if (!projectId) {
|
|
1648
|
+
console.error('Error: --project-id is required');
|
|
1649
|
+
process.exit(1);
|
|
1650
|
+
}
|
|
1651
|
+
if (!deviceFingerprint) {
|
|
1652
|
+
console.error('Error: --device-fingerprint is required (or set OVERLORD_DEVICE_FINGERPRINT)');
|
|
1653
|
+
process.exit(1);
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
// Verify directory exists on this device before sending to server
|
|
1657
|
+
const fs = await import('node:fs');
|
|
1658
|
+
if (!fs.existsSync(directoryPath)) {
|
|
1659
|
+
console.error(`Error: Directory does not exist: ${directoryPath}`);
|
|
1660
|
+
process.exit(1);
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
const body = {
|
|
1664
|
+
projectId,
|
|
1665
|
+
directoryPath,
|
|
1666
|
+
deviceFingerprint,
|
|
1667
|
+
...(typeof flags.label === 'string' ? { label: flags.label } : {}),
|
|
1668
|
+
...(flags['is-primary'] === true || flags['is-primary'] === 'true' ? { isPrimary: true } : {}),
|
|
1669
|
+
...(flags['device-hostname'] ? { deviceHostname: String(flags['device-hostname']) } : {}),
|
|
1670
|
+
...(flags['device-platform'] ? { devicePlatform: String(flags['device-platform']) } : {})
|
|
1671
|
+
};
|
|
1672
|
+
|
|
1673
|
+
const data = await apiPost(
|
|
1674
|
+
platformUrl,
|
|
1675
|
+
bearerToken,
|
|
1676
|
+
localSecret,
|
|
1677
|
+
organizationId,
|
|
1678
|
+
'/api/protocol/add-project-resource',
|
|
1679
|
+
body,
|
|
1680
|
+
timeoutMs
|
|
1681
|
+
);
|
|
1682
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1683
|
+
|
|
1684
|
+
if (data.resource?.id) {
|
|
1685
|
+
process.stderr.write(`\nRESOURCE_ID=${data.resource.id}\n`);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// ---------------------------------------------------------------------------
|
|
1690
|
+
// update-project-resource (update path, label, or primary status)
|
|
1691
|
+
// ---------------------------------------------------------------------------
|
|
1692
|
+
|
|
1693
|
+
async function protocolUpdateProjectResource(args) {
|
|
1694
|
+
const flags = parseFlags(args);
|
|
1695
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1696
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1697
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1698
|
+
|
|
1699
|
+
const resourceId = typeof flags['resource-id'] === 'string' ? flags['resource-id'].trim() : '';
|
|
1700
|
+
const deviceFingerprint = String(
|
|
1701
|
+
flags['device-fingerprint'] ?? process.env.OVERLORD_DEVICE_FINGERPRINT ?? ''
|
|
1702
|
+
);
|
|
1703
|
+
|
|
1704
|
+
if (!resourceId) {
|
|
1705
|
+
console.error('Error: --resource-id is required');
|
|
1706
|
+
process.exit(1);
|
|
1707
|
+
}
|
|
1708
|
+
if (!deviceFingerprint) {
|
|
1709
|
+
console.error('Error: --device-fingerprint is required (or set OVERLORD_DEVICE_FINGERPRINT)');
|
|
1710
|
+
process.exit(1);
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
const body = {
|
|
1714
|
+
resourceId,
|
|
1715
|
+
deviceFingerprint,
|
|
1716
|
+
...(typeof flags.directory === 'string' ? { directoryPath: flags.directory.trim() } : {}),
|
|
1717
|
+
...('label' in flags ? { label: flags.label === 'null' ? null : String(flags.label) } : {}),
|
|
1718
|
+
...(flags['is-primary'] !== undefined
|
|
1719
|
+
? { isPrimary: flags['is-primary'] === true || flags['is-primary'] === 'true' }
|
|
1720
|
+
: {})
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1723
|
+
const data = await apiPost(
|
|
1724
|
+
platformUrl,
|
|
1725
|
+
bearerToken,
|
|
1726
|
+
localSecret,
|
|
1727
|
+
organizationId,
|
|
1728
|
+
'/api/protocol/update-project-resource',
|
|
1729
|
+
body,
|
|
1730
|
+
timeoutMs
|
|
1731
|
+
);
|
|
1732
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1444
1735
|
// ---------------------------------------------------------------------------
|
|
1445
1736
|
// connect (lightweight session, no context returned)
|
|
1446
1737
|
// ---------------------------------------------------------------------------
|
|
@@ -1502,6 +1793,42 @@ async function protocolLoadContext(args) {
|
|
|
1502
1793
|
console.log(JSON.stringify(data, null, 2));
|
|
1503
1794
|
}
|
|
1504
1795
|
|
|
1796
|
+
// ---------------------------------------------------------------------------
|
|
1797
|
+
// revert (restore local working tree to an objective checkpoint)
|
|
1798
|
+
// ---------------------------------------------------------------------------
|
|
1799
|
+
|
|
1800
|
+
async function protocolRevert(args) {
|
|
1801
|
+
const flags = parseFlags(args);
|
|
1802
|
+
const objectiveId = requireFlag(flags, 'objective-id', 'OVERLORD_OBJECTIVE_ID');
|
|
1803
|
+
const workspacePath = path.resolve(
|
|
1804
|
+
String(flags['working-directory'] ?? process.env.OVERLORD_WORKSPACE_PATH ?? process.cwd())
|
|
1805
|
+
);
|
|
1806
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1807
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1808
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1809
|
+
|
|
1810
|
+
const data = await apiPost(
|
|
1811
|
+
platformUrl,
|
|
1812
|
+
bearerToken,
|
|
1813
|
+
localSecret,
|
|
1814
|
+
organizationId,
|
|
1815
|
+
'/api/protocol/revert',
|
|
1816
|
+
{ objectiveId },
|
|
1817
|
+
timeoutMs
|
|
1818
|
+
);
|
|
1819
|
+
const checkpoint = data?.checkpoint;
|
|
1820
|
+
if (!checkpoint?.git_commit_id) {
|
|
1821
|
+
throw new Error('API response did not include a checkpoint git_commit_id.');
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
const result = restoreLocalCheckpoint({
|
|
1825
|
+
workspacePath,
|
|
1826
|
+
objectiveId,
|
|
1827
|
+
gitCommitId: checkpoint.git_commit_id
|
|
1828
|
+
});
|
|
1829
|
+
console.log(JSON.stringify({ ok: true, checkpoint, restore: result }, null, 2));
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1505
1832
|
// ---------------------------------------------------------------------------
|
|
1506
1833
|
// prompt (create ticket + connect in one call)
|
|
1507
1834
|
// ---------------------------------------------------------------------------
|
|
@@ -1902,6 +2229,7 @@ Subcommands:
|
|
|
1902
2229
|
attach Start a ticket session and return full working context
|
|
1903
2230
|
connect Start a lightweight session without full context
|
|
1904
2231
|
load-context Read ticket context without creating a session
|
|
2232
|
+
revert Restore the local working tree to an objective checkpoint
|
|
1905
2233
|
search-tickets Find tickets by keyword, status, project, creator, or update date
|
|
1906
2234
|
discuss-objective Mark a draft objective as submitted (ready for review/execution)
|
|
1907
2235
|
create Create a draft ticket without attaching (follow-up or standalone)
|
|
@@ -1920,6 +2248,11 @@ Subcommands:
|
|
|
1920
2248
|
attachment-finalize-upload Finalize an uploaded attachment row after storage upload
|
|
1921
2249
|
attachment-download-url Get a signed download URL for an existing attachment
|
|
1922
2250
|
attachment-upload-file Prepare, upload, and finalize a local file in one command
|
|
2251
|
+
get-device Identify / register the current device and return its label
|
|
2252
|
+
update-device Rename this device's label (must be lowercase kebab-case)
|
|
2253
|
+
list-project-resources List resource directories registered for a project
|
|
2254
|
+
add-project-resource Register a local directory as a project resource on this device
|
|
2255
|
+
update-project-resource Update a resource directory's path, label, or primary status
|
|
1923
2256
|
|
|
1924
2257
|
Environment fallback:
|
|
1925
2258
|
--session-key <- SESSION_KEY
|
|
@@ -1993,6 +2326,16 @@ load-context:
|
|
|
1993
2326
|
Required:
|
|
1994
2327
|
--ticket-id <ticket_id>
|
|
1995
2328
|
|
|
2329
|
+
revert:
|
|
2330
|
+
Purpose:
|
|
2331
|
+
Fetch an objective checkpoint from Overlord and restore the local git working tree to it.
|
|
2332
|
+
Required:
|
|
2333
|
+
--objective-id <objective-uuid>
|
|
2334
|
+
Optional:
|
|
2335
|
+
--working-directory <path> Repository to restore (default: current working directory)
|
|
2336
|
+
Notes:
|
|
2337
|
+
A safety snapshot of the current working tree is saved under refs/overlord/safety/ first.
|
|
2338
|
+
|
|
1996
2339
|
search-tickets:
|
|
1997
2340
|
Purpose:
|
|
1998
2341
|
Find tickets in your organization by keyword, status, project, creator, or update window.
|
|
@@ -2272,6 +2615,44 @@ attachment-upload-file:
|
|
|
2272
2615
|
--content-type <mime> Defaults to application/octet-stream
|
|
2273
2616
|
--metadata-json <json>
|
|
2274
2617
|
|
|
2618
|
+
get-device:
|
|
2619
|
+
Required:
|
|
2620
|
+
--device-fingerprint <fp> (or OVERLORD_DEVICE_FINGERPRINT env var)
|
|
2621
|
+
Optional:
|
|
2622
|
+
--device-hostname <name>
|
|
2623
|
+
--device-platform <platform> (darwin|linux|windows)
|
|
2624
|
+
|
|
2625
|
+
update-device:
|
|
2626
|
+
Required:
|
|
2627
|
+
--device-fingerprint <fp> (or OVERLORD_DEVICE_FINGERPRINT env var)
|
|
2628
|
+
--label <label> Lowercase kebab-case, unique within org
|
|
2629
|
+
|
|
2630
|
+
list-project-resources:
|
|
2631
|
+
Required:
|
|
2632
|
+
--project-id <uuid>
|
|
2633
|
+
Optional:
|
|
2634
|
+
--device-fingerprint <fp> Filter to current device only
|
|
2635
|
+
|
|
2636
|
+
add-project-resource:
|
|
2637
|
+
Required:
|
|
2638
|
+
--project-id <uuid>
|
|
2639
|
+
--device-fingerprint <fp> (or OVERLORD_DEVICE_FINGERPRINT env var)
|
|
2640
|
+
Optional:
|
|
2641
|
+
--directory <path> Defaults to current working directory
|
|
2642
|
+
--label <text>
|
|
2643
|
+
--is-primary Mark as primary directory for this device+project
|
|
2644
|
+
--device-hostname <name>
|
|
2645
|
+
--device-platform <platform>
|
|
2646
|
+
|
|
2647
|
+
update-project-resource:
|
|
2648
|
+
Required:
|
|
2649
|
+
--resource-id <uuid> From list-project-resources output
|
|
2650
|
+
--device-fingerprint <fp> (or OVERLORD_DEVICE_FINGERPRINT env var)
|
|
2651
|
+
Optional:
|
|
2652
|
+
--directory <path> New absolute path
|
|
2653
|
+
--label <text> New label (pass 'null' to clear)
|
|
2654
|
+
--is-primary <true|false>
|
|
2655
|
+
|
|
2275
2656
|
Examples:
|
|
2276
2657
|
ovld protocol auth-status
|
|
2277
2658
|
ovld protocol discover-project
|
|
@@ -2281,6 +2662,7 @@ Examples:
|
|
|
2281
2662
|
ovld protocol attach --ticket-id 1:899 --external-session-id null
|
|
2282
2663
|
ovld protocol connect --ticket-id 1:899
|
|
2283
2664
|
ovld protocol load-context --ticket-id 1:899
|
|
2665
|
+
ovld protocol revert --objective-id <objective-uuid>
|
|
2284
2666
|
ovld protocol search-tickets --query "auth refactor" --status next-up,execute --limit 10
|
|
2285
2667
|
ovld protocol discuss-objective --ticket-id 1:899
|
|
2286
2668
|
ovld protocol discuss-objective --ticket-id 1:899 --objective-id <objective-uuid>
|
|
@@ -2309,6 +2691,14 @@ Examples:
|
|
|
2309
2691
|
ovld protocol record-work --payload-file - <<'EOF'
|
|
2310
2692
|
{"objective":"...","summary":"...","artifacts":[...],"changeRationales":[...]}
|
|
2311
2693
|
EOF
|
|
2694
|
+
ovld protocol get-device --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT
|
|
2695
|
+
ovld protocol update-device --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT --label work-macbook
|
|
2696
|
+
ovld protocol list-project-resources --project-id <project-uuid>
|
|
2697
|
+
ovld protocol list-project-resources --project-id <project-uuid> --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT
|
|
2698
|
+
ovld protocol add-project-resource --project-id <project-uuid> --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT
|
|
2699
|
+
ovld protocol add-project-resource --project-id <project-uuid> --directory /path/to/repo --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT --label "main checkout" --is-primary
|
|
2700
|
+
ovld protocol update-project-resource --resource-id <resource-uuid> --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT --label "docs branch"
|
|
2701
|
+
ovld protocol update-project-resource --resource-id <resource-uuid> --device-fingerprint $OVERLORD_DEVICE_FINGERPRINT --is-primary true
|
|
2312
2702
|
`);
|
|
2313
2703
|
return;
|
|
2314
2704
|
}
|
|
@@ -2333,6 +2723,10 @@ EOF
|
|
|
2333
2723
|
await protocolLoadContext(args);
|
|
2334
2724
|
return;
|
|
2335
2725
|
}
|
|
2726
|
+
if (subcommand === 'revert') {
|
|
2727
|
+
await protocolRevert(args);
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2336
2730
|
if (subcommand === 'search-tickets') {
|
|
2337
2731
|
await protocolSearchTickets(args);
|
|
2338
2732
|
return;
|
|
@@ -2405,6 +2799,26 @@ EOF
|
|
|
2405
2799
|
await protocolDeliver(args);
|
|
2406
2800
|
return;
|
|
2407
2801
|
}
|
|
2802
|
+
if (subcommand === 'get-device') {
|
|
2803
|
+
await protocolGetDevice(args);
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2806
|
+
if (subcommand === 'update-device') {
|
|
2807
|
+
await protocolUpdateDevice(args);
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
if (subcommand === 'list-project-resources') {
|
|
2811
|
+
await protocolListProjectResources(args);
|
|
2812
|
+
return;
|
|
2813
|
+
}
|
|
2814
|
+
if (subcommand === 'add-project-resource') {
|
|
2815
|
+
await protocolAddProjectResource(args);
|
|
2816
|
+
return;
|
|
2817
|
+
}
|
|
2818
|
+
if (subcommand === 'update-project-resource') {
|
|
2819
|
+
await protocolUpdateProjectResource(args);
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2408
2822
|
|
|
2409
2823
|
console.error(`Unknown protocol subcommand: ${subcommand}\n`);
|
|
2410
2824
|
console.log('Run: ovld protocol help');
|
package/package.json
CHANGED
|
@@ -27,6 +27,8 @@ Attach:
|
|
|
27
27
|
ovld protocol attach --ticket-id $TICKET_ID
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
In a git workspace, `attach` automatically creates a local git checkpoint for each executing objective before work begins, stored under `refs/overlord/checkpoints/<objectiveId>`. Pass `--skip-checkpoint` only when intentionally bypassing local provenance.
|
|
31
|
+
|
|
30
32
|
Update:
|
|
31
33
|
|
|
32
34
|
```bash
|
|
@@ -75,7 +77,15 @@ ovld protocol deliver --session-key <sessionKey> \
|
|
|
75
77
|
--change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
Use `--payload-json` when the full delivery object fits comfortably inline. For larger delivery payloads, prefer `--payload-file -` and stream the full JSON on stdin so no scratch file needs to be created or removed. If the summary contains special characters, use `--summary-file -` and pipe via a single-quoted heredoc (`<<'EOF'`) to prevent shell expansion. If you use `--payload-file`, `--artifacts-file`, or `--change-rationales-file` with a real path, treat that file as ephemeral scratch data outside the repository and remove it after delivery.
|
|
81
|
+
|
|
82
|
+
Revert an objective:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
ovld protocol revert --objective-id <objective-id>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`revert` restores the local working tree to the recorded objective checkpoint and saves a safety ref under `refs/overlord/safety/` first.
|
|
79
89
|
|
|
80
90
|
## Mode 2: Asked From Chat To Use Overlord
|
|
81
91
|
|
|
@@ -25,6 +25,8 @@ Attach:
|
|
|
25
25
|
ovld protocol attach --ticket-id $TICKET_ID
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
In a git workspace, `attach` automatically creates a local git checkpoint for each executing objective before work begins, stored under `refs/overlord/checkpoints/<objectiveId>`. Pass `--skip-checkpoint` only when intentionally bypassing local provenance.
|
|
29
|
+
|
|
28
30
|
Update:
|
|
29
31
|
|
|
30
32
|
```bash
|
|
@@ -61,7 +63,15 @@ ovld protocol deliver --session-key <sessionKey> \
|
|
|
61
63
|
--change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
62
64
|
```
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
Use `--payload-json` when the full delivery object fits comfortably inline. For larger delivery payloads, prefer `--payload-file -` and stream the full JSON on stdin so no scratch file needs to be created or removed.
|
|
67
|
+
|
|
68
|
+
Revert an objective:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ovld protocol revert --objective-id <objective-id>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`revert` restores the local working tree to the recorded objective checkpoint and saves a safety ref under `refs/overlord/safety/` first.
|
|
65
75
|
|
|
66
76
|
## Mode 2: Asked From Chat To Use Overlord
|
|
67
77
|
|
|
@@ -365,9 +365,8 @@ const tools = [
|
|
|
365
365
|
checkpoint: {
|
|
366
366
|
type: 'object',
|
|
367
367
|
description:
|
|
368
|
-
'Optional checkpoint metadata.
|
|
368
|
+
'Optional checkpoint metadata. Local git checkpoints are created on `attach`, not deliver; this field is only for callers forwarding pre-recorded checkpoint provenance.'
|
|
369
369
|
},
|
|
370
|
-
skip_checkpoint: { type: 'boolean' },
|
|
371
370
|
skip_file_change_check: { type: 'boolean' }
|
|
372
371
|
},
|
|
373
372
|
required: ['session_key', 'ticket_id', 'summary']
|
|
@@ -376,7 +375,6 @@ const tools = [
|
|
|
376
375
|
'session-key': args.session_key,
|
|
377
376
|
'ticket-id': args.ticket_id,
|
|
378
377
|
'payload-file': '-',
|
|
379
|
-
'skip-checkpoint': args.skip_checkpoint,
|
|
380
378
|
'skip-file-change-check': args.skip_file_change_check
|
|
381
379
|
}),
|
|
382
380
|
toCliStdin: args =>
|
|
@@ -25,6 +25,8 @@ Attach:
|
|
|
25
25
|
ovld protocol attach --ticket-id $TICKET_ID
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
In a git workspace, `attach` automatically creates a local git checkpoint for each executing objective before work begins, stored under `refs/overlord/checkpoints/<objectiveId>`. Pass `--skip-checkpoint` only when intentionally bypassing local provenance.
|
|
29
|
+
|
|
28
30
|
Update:
|
|
29
31
|
|
|
30
32
|
```bash
|
|
@@ -65,7 +67,15 @@ ovld protocol deliver --session-key <sessionKey> \
|
|
|
65
67
|
--change-rationales-json '[{"label":"Short reviewer title","file_path":"path/to/file.ts","summary":"What changed.","why":"Why it changed.","impact":"Behavioral impact.","hunks":[{"header":"@@ -10,6 +10,14 @@"}]}]'
|
|
66
68
|
```
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
Use `--payload-json` when the full delivery object fits comfortably inline. For larger delivery payloads, prefer `--payload-file -` and stream the full JSON on stdin so no scratch file needs to be created or removed. If you use `--payload-file`, `--artifacts-file`, or `--change-rationales-file` with a real path, treat that file as ephemeral scratch data outside the repository and remove it after delivery.
|
|
71
|
+
|
|
72
|
+
Revert an objective:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
ovld protocol revert --objective-id <objective-id>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`revert` restores the local working tree to the recorded objective checkpoint and saves a safety ref under `refs/overlord/safety/` first.
|
|
69
79
|
|
|
70
80
|
## Mode 2: Asked From Chat To Use Overlord
|
|
71
81
|
|