draftgo-cli 3.0.56 → 4.0.22

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.
Files changed (96) hide show
  1. package/README.md +169 -297
  2. package/package.json +12 -7
  3. package/resources/custom-service-sdk/ai.go +520 -0
  4. package/resources/custom-service-sdk/ai_test.go +156 -0
  5. package/resources/custom-service-sdk/billing.go +596 -0
  6. package/resources/custom-service-sdk/billing_test.go +150 -0
  7. package/resources/custom-service-sdk/go.mod +3 -0
  8. package/resources/custom-service-sdk/manifest.json +72 -0
  9. package/resources/custom-service-sdk/platform.go +360 -0
  10. package/resources/custom-service-sdk/platform_logger_test.go +24 -0
  11. package/resources/custom-service-sdk/registration_test.go +39 -0
  12. package/resources/custom-service-sdk/resources.go +246 -0
  13. package/resources/custom-service-sdk/resources_billing_test.go +115 -0
  14. package/resources/custom-service-sdk/resources_files_test.go +57 -0
  15. package/resources/custom-service-sdk/resources_scope_test.go +87 -0
  16. package/resources/custom-service-sdk/sdk.go +208 -0
  17. package/resources/skill/SKILL.md +36 -87
  18. package/resources/skill/init/SKILL.md +9 -14
  19. package/resources/skill/manifest.json +6 -2
  20. package/resources/skill/references/aihub.md +28 -5
  21. package/resources/skill/references/app-api.md +56 -6
  22. package/resources/skill/references/architecture.md +2 -2
  23. package/resources/skill/references/chat-sdk.md +4 -2
  24. package/resources/skill/references/checkout.md +21 -7
  25. package/resources/skill/references/custom-services.md +124 -222
  26. package/resources/skill/references/data.md +22 -6
  27. package/resources/skill/references/delivery.md +33 -0
  28. package/resources/skill/references/diagnostics.md +51 -0
  29. package/resources/skill/references/frontend.md +93 -499
  30. package/resources/skill/references/mcp.md +65 -101
  31. package/resources/skill/references/methods.md +189 -0
  32. package/resources/skill/references/modules.md +36 -8
  33. package/resources/skill/references/runtime.md +26 -3
  34. package/resources/skill/story/SKILL.md +1 -2
  35. package/src/apiContractCache.js +112 -0
  36. package/src/cli.js +24 -20
  37. package/src/commandRegistry.js +15 -12
  38. package/src/commands/api.js +41 -10
  39. package/src/commands/apiKey.js +34 -0
  40. package/src/commands/capabilities.js +93 -0
  41. package/src/commands/check.js +1 -10
  42. package/src/commands/checkout.js +1 -1
  43. package/src/commands/commit.js +1 -1
  44. package/src/commands/components.js +550 -0
  45. package/src/commands/conflict.js +1 -1
  46. package/src/commands/connect.js +18 -8
  47. package/src/commands/customService.js +22 -8
  48. package/src/commands/dataRange.js +33 -0
  49. package/src/commands/delete.js +34 -46
  50. package/src/commands/deploy.js +1 -1
  51. package/src/commands/diff.js +18 -2
  52. package/src/commands/grant.js +29 -0
  53. package/src/commands/group.js +38 -0
  54. package/src/commands/help.js +80 -51
  55. package/src/commands/init.js +6 -12
  56. package/src/commands/listTargets.js +1 -1
  57. package/src/commands/local.js +2 -6
  58. package/src/commands/map.js +145 -28
  59. package/src/commands/mcp.js +2 -2
  60. package/src/commands/reconcile.js +1 -1
  61. package/src/commands/role.js +32 -0
  62. package/src/commands/space.js +41 -0
  63. package/src/commands/status.js +111 -8
  64. package/src/commands/uninstall.js +3 -3
  65. package/src/commands/update.js +24 -12
  66. package/src/commands/verify.js +118 -21
  67. package/src/commands/{verifyUi.js → visualVerify.js} +28 -116
  68. package/src/commands/worklog.js +90 -0
  69. package/src/consoleEncoding.js +34 -0
  70. package/src/contractCompatibility.js +57 -0
  71. package/src/customServices.js +278 -41
  72. package/src/diffReport.js +106 -0
  73. package/src/index.js +2 -0
  74. package/src/{localdev → localRuntime}/compose.js +14 -17
  75. package/src/{localdev → localRuntime}/detect.js +1 -1
  76. package/src/{localdev → localRuntime}/index.js +22 -23
  77. package/src/{localdev → localRuntime}/mysqlClient.js +1 -1
  78. package/src/{localdev → localRuntime}/services.js +28 -37
  79. package/src/mcp/client.js +11 -2
  80. package/src/mcp/protocol.js +2 -2
  81. package/src/mcp/tools.js +14 -1
  82. package/src/platforms.js +9 -0
  83. package/src/projectConfig.js +8 -4
  84. package/src/releaseInstall.js +105 -0
  85. package/src/{installers/index.js → targets.js} +3 -5
  86. package/src/updateCheck.js +48 -28
  87. package/src/worklog.js +275 -0
  88. package/src/workspaceHealth.js +1 -1
  89. package/src/worktree/backend.js +1 -1
  90. package/src/worktree/index.js +86 -51
  91. package/src/changelog.js +0 -276
  92. package/src/commands/changelog.js +0 -24
  93. package/src/commands/localDev.js +0 -9
  94. package/src/commands/sync.js +0 -46
  95. package/src/commands/task.js +0 -408
  96. package/src/commands/verifyUiCompat.js +0 -16
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs');
4
+ const path = require('path');
4
5
  const log = require('../logger');
5
6
  const services = require('../customServices');
7
+ const { report, formatSummary, formatStat } = require('../diffReport');
6
8
 
7
9
  function ids(positional) { return positional.map(String).filter(Boolean); }
8
- const TYPE_ALIASES = new Set(['custom-services', 'custom-service', 'custom_services', 'custom_service', 'services', 'scripts', 'custom_scripts']);
9
10
  function isServiceType(value) {
10
- return TYPE_ALIASES.has(String(value || '').toLowerCase());
11
+ return String(value || '').toLowerCase() === 'custom-services';
11
12
  }
12
13
  function serviceIds(positional) {
13
14
  const values = ids(positional);
14
- if (isServiceType(values[0])) values.shift();
15
- return values;
15
+ return isServiceType(values[0]) ? values.slice(1) : [];
16
16
  }
17
17
  function output(flags, value) {
18
18
  if (flags.output === 'json') console.log(JSON.stringify(value, null, 2));
@@ -30,9 +30,10 @@ async function checkout(projectDir, positional, flags = {}) {
30
30
  async function commit(projectDir, positional, flags = {}) {
31
31
  const values = ids(positional);
32
32
  if (!values.length) { log.err('Usage: draftgo commit custom-services <id...>'); return 1; }
33
- const result = await services.commit(projectDir, values);
33
+ // The user-facing custom-service commit is a complete delivery operation.
34
+ const result = await services.publish(projectDir, values);
34
35
  if (flags.output === 'json') output(flags, result);
35
- else result.forEach((item) => log.ok(`custom service ${item.resource_id}: ${item.status}`));
36
+ else result.forEach((item) => log.ok(`custom service ${item.id || item.resource_id}: published (commit + validate + publish)`));
36
37
  return 0;
37
38
  }
38
39
 
@@ -40,7 +41,18 @@ async function diff(projectDir, positional, flags = {}) {
40
41
  const id = positional[0];
41
42
  if (!id) { log.err('Usage: draftgo diff custom-services <id>'); return 1; }
42
43
  const result = services.diff(projectDir, id);
43
- if (flags.output === 'json') output(flags, result);
44
+ const concise = Boolean(flags.stat || flags.summary);
45
+ const value = concise ? report(result.entry, result.file_outputs.map((file) => ({
46
+ path: file.filename,
47
+ changed: file.changed,
48
+ output: file.output,
49
+ base_path: path.join(result.entry.base_dir, file.filename),
50
+ local_path: path.join(result.entry.local_dir, file.filename),
51
+ }))) : null;
52
+ if (flags.output === 'json' && concise) output(flags, value);
53
+ else if (flags.output === 'json') output(flags, result);
54
+ else if (flags.stat) process.stdout.write(formatStat(value));
55
+ else if (flags.summary) process.stdout.write(formatSummary(value));
44
56
  else if (result.changed) process.stdout.write(result.output);
45
57
  else log.dim(`custom service ${id}: no local changes`);
46
58
  return 0;
@@ -62,8 +74,10 @@ async function test(projectDir, positional, flags = {}) {
62
74
  const readJSON = (value) => value ? JSON.parse(fs.readFileSync(String(value), 'utf8')) : undefined;
63
75
  const policy = String(flags['side-effect-policy'] || 'deny').toLowerCase();
64
76
  if (!['deny', 'mock', 'live'].includes(policy)) throw new Error('--side-effect-policy must be deny, mock, or live.');
77
+ const source = String(flags.source || 'draft').toLowerCase();
78
+ if (!['auto', 'draft', 'published'].includes(source)) throw new Error('--source must be auto, draft, or published.');
65
79
  const result = await services.test(projectDir, id, input, { handler: flags.handler, headers: readJSON(flags.headers), user: readJSON(flags.user),
66
- testWrite: Boolean(flags['test-write']), sideEffectPolicy: policy });
80
+ testWrite: Boolean(flags['test-write']), sideEffectPolicy: policy, source });
67
81
  if (flags.output === 'json') output(flags, result);
68
82
  else log[result.status === 'success' ? 'ok' : 'err'](`custom service ${id}: ${result.status}`);
69
83
  return result.status === 'success' ? 0 : 1;
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const log = require('../logger');
4
+ const { callOperation } = require('./api');
5
+
6
+ // DataRange is represented by db_meta record policies; it is not a second
7
+ // authorization scope or a free-form client-side filter.
8
+ const OPERATIONS = Object.freeze({
9
+ list: 'list_meta_api_db_meta_get',
10
+ create: 'create_meta_api_db_meta_post',
11
+ get: 'get_meta_api_db_meta__type__get',
12
+ update: 'update_meta_api_db_meta__id__put',
13
+ batch: 'update_meta_batch_api_db_meta_batch_patch',
14
+ delete: 'delete_meta_api_db_meta__id__delete',
15
+ });
16
+
17
+ function operationKey(value) {
18
+ const action = String(value || 'list').trim().toLowerCase();
19
+ return OPERATIONS[action] ? action : '';
20
+ }
21
+
22
+ async function dataRangeCommand(projectDir, positional, flags = {}) {
23
+ const action = operationKey(positional[0]);
24
+ if (!action) {
25
+ log.err('Usage: draftgo data-range list|create|get|update|batch|delete --input <json-file>');
26
+ return 1;
27
+ }
28
+ return callOperation(projectDir, OPERATIONS[action], flags);
29
+ }
30
+
31
+ module.exports = dataRangeCommand;
32
+ module.exports.OPERATIONS = OPERATIONS;
33
+ module.exports.operationKey = operationKey;
@@ -6,23 +6,13 @@ const log = require('../logger');
6
6
  const { confirm } = require('../prompt');
7
7
  const { loadProjectConfig } = require('../projectConfig');
8
8
  const { TOOL_NAMES, openToolSession, callStructured } = require('../mcp/tools');
9
-
10
- const LEGACY_TYPES = new Set([
11
- 'page', 'pages', 'nav', 'navigation', 'navigations', 'doc', 'docs', 'article',
12
- 'db_meta', 'custom_scripts', 'doc_categories', 'aihub', 'roles', 'users', 'system_config',
13
- ]);
14
-
15
- function resultItems(value) {
16
- if (Array.isArray(value)) return value;
17
- if (!value || typeof value !== 'object') return [];
18
- if (Array.isArray(value.items)) return value.items;
19
- if (Array.isArray(value.operations)) return value.operations;
20
- return value.data ? resultItems(value.data) : [];
21
- }
22
-
23
- function operationId(value) {
24
- return value && (value.operation_id || value.operationId || value.id);
25
- }
9
+ const { cachedDescription, normalizeDescription, storeDescription } = require('../apiContractCache');
10
+ const {
11
+ isContractCompatibilityError,
12
+ isHardContractIncompatibility,
13
+ sameOperationContract,
14
+ incompatibleOperationError,
15
+ } = require('../contractCompatibility');
26
16
 
27
17
  function readParams(projectDir, flags) {
28
18
  const raw = flags.params ? String(flags.params)
@@ -45,40 +35,25 @@ function pathParameterName(description) {
45
35
  async function deleteResource(projectDir, positional, flags = {}) {
46
36
  if (!positional.length && !flags['operation-id']) {
47
37
  log.err('Usage: draftgo delete <operation_id> [id] [--params JSON]');
48
- log.dim(' Legacy form is supported when discovery is unambiguous: draftgo delete <type> <id>.');
49
38
  return 1;
50
39
  }
51
40
  const config = loadProjectConfig(projectDir);
52
41
  const session = await openToolSession(config, [
53
- TOOL_NAMES.apiSearch, TOOL_NAMES.apiDescribe, TOOL_NAMES.apiCall,
42
+ TOOL_NAMES.apiDescribe, TOOL_NAMES.apiCall,
54
43
  ]);
55
44
 
56
- const first = String(positional[0] || '');
57
- const legacy = LEGACY_TYPES.has(first.toLowerCase()) && !flags['operation-id'];
58
- let selectedOperation = flags['operation-id'] ? String(flags['operation-id']) : (legacy ? null : first);
59
- const resourceId = legacy ? positional[1] : positional[1];
60
- if (legacy) {
61
- if (!resourceId) {
62
- log.err('Legacy delete form requires a resource id.');
63
- return 1;
64
- }
65
- const search = await callStructured(session, TOOL_NAMES.apiSearch, { query: `delete ${first}` });
66
- const candidates = resultItems(search).filter((item) => operationId(item)
67
- && (!item.method || String(item.method).toUpperCase() === 'DELETE'));
68
- if (candidates.length !== 1) {
69
- log.err(`Delete operation discovery was ambiguous (${candidates.length} matches).`);
70
- log.dim(` Run \`draftgo api delete ${first}\`, then pass --operation-id explicitly.`);
71
- return 1;
72
- }
73
- selectedOperation = operationId(candidates[0]);
74
- }
45
+ const selectedOperation = flags['operation-id'] ? String(flags['operation-id']) : String(positional[0]);
46
+ const resourceId = positional[1];
75
47
 
76
- const description = await callStructured(session, TOOL_NAMES.apiDescribe, {
77
- operation_id: selectedOperation,
78
- });
48
+ let contract = cachedDescription(projectDir, config.server, selectedOperation);
49
+ if (!contract) {
50
+ const described = await callStructured(session, TOOL_NAMES.apiDescribe, { operation_id: selectedOperation });
51
+ contract = storeDescription(projectDir, config.server, described) || normalizeDescription(described);
52
+ }
53
+ if (!contract) throw new Error('DraftGo API description is missing contract revision metadata.');
79
54
  const params = readParams(projectDir, flags);
80
55
  if (resourceId && Object.keys(params).length === 0) {
81
- const parameterName = pathParameterName(description);
56
+ const parameterName = pathParameterName(contract.operation);
82
57
  if (!parameterName) {
83
58
  log.err('The operation does not expose exactly one path parameter; provide --params JSON explicitly.');
84
59
  return 1;
@@ -89,11 +64,24 @@ async function deleteResource(projectDir, positional, flags = {}) {
89
64
  const approved = await confirm(`Call destructive DraftGo operation ${selectedOperation}?`, { default: false });
90
65
  if (!approved) return 0;
91
66
  }
92
- const result = await callStructured(session, TOOL_NAMES.apiCall, {
93
- ...params,
94
- operation_id: selectedOperation,
95
- confirm: true,
67
+ const invoke = () => callStructured(session, TOOL_NAMES.apiCall, {
68
+ ...params, operation_id: selectedOperation, registry_revision: contract.registry_revision, confirm: true,
96
69
  });
70
+ let result;
71
+ try {
72
+ result = await invoke();
73
+ } catch (error) {
74
+ if (!isContractCompatibilityError(error)) throw error;
75
+ if (isHardContractIncompatibility(error)) throw incompatibleOperationError(selectedOperation, error);
76
+ const previousContract = contract;
77
+ const described = await callStructured(session, TOOL_NAMES.apiDescribe, { operation_id: selectedOperation });
78
+ contract = storeDescription(projectDir, config.server, described) || normalizeDescription(described);
79
+ if (!contract) throw new Error('DraftGo API description is missing contract revision metadata.');
80
+ if (!sameOperationContract(previousContract, contract)) {
81
+ throw incompatibleOperationError(selectedOperation, error);
82
+ }
83
+ result = await invoke();
84
+ }
97
85
  if (flags.output === 'json') console.log(JSON.stringify(result, null, 2));
98
86
  else log.ok(`DraftGo operation completed: ${selectedOperation}`);
99
87
  return 0;
@@ -23,7 +23,7 @@ async function deploy(projectDir, positional, flags = {}) {
23
23
 
24
24
  const [resourceType, ...ids] = positional;
25
25
  if (!resourceType || !ids.length) {
26
- log.err('Deploy no longer commits every legacy index. Specify <pages|nav|docs> <id...>.');
26
+ log.err('Usage: draftgo deploy <pages|nav|docs> <id...> --delivery preview|deploy');
27
27
  return 1;
28
28
  }
29
29
  if (delivery === 'preview') {
@@ -2,19 +2,35 @@
2
2
 
3
3
  const log = require('../logger');
4
4
  const { diffResource } = require('../worktree');
5
+ const { report, formatSummary, formatStat } = require('../diffReport');
6
+ const { absolutePath } = require('../worktree/manifest');
5
7
 
6
8
  function diff(projectDir, positional, flags = {}) {
7
9
  const [resourceType, resourceId] = positional;
8
10
  if (!resourceType || !resourceId) {
9
- log.err('Usage: draftgo diff <pages|nav|docs> <id>');
11
+ log.err('Usage: draftgo diff <pages|nav|docs|custom-services> <id>');
10
12
  return 1;
11
13
  }
12
14
  if (require('./customService').isServiceType(resourceType)) {
13
15
  return require('./customService').diff(projectDir, [resourceId], flags);
14
16
  }
15
17
  const result = diffResource(projectDir, resourceType, resourceId);
16
- if (flags.output === 'json') {
18
+ const concise = Boolean(flags.stat || flags.summary);
19
+ const value = concise ? report(result.entry, [{
20
+ path: result.entry.local_path,
21
+ changed: result.changed,
22
+ output: result.output,
23
+ base_path: absolutePath(projectDir, result.entry.base_path),
24
+ local_path: absolutePath(projectDir, result.entry.local_path),
25
+ }]) : null;
26
+ if (flags.output === 'json' && concise) {
27
+ console.log(JSON.stringify(value, null, 2));
28
+ } else if (flags.output === 'json') {
17
29
  console.log(JSON.stringify({ changed: result.changed, entry: result.entry, diff: result.output }, null, 2));
30
+ } else if (flags.stat) {
31
+ process.stdout.write(formatStat(value));
32
+ } else if (flags.summary) {
33
+ process.stdout.write(formatSummary(value));
18
34
  } else if (result.changed) {
19
35
  process.stdout.write(result.output);
20
36
  } else {
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const log = require('../logger');
4
+ const { callOperation } = require('./api');
5
+
6
+ const OPERATIONS = Object.freeze({
7
+ list: 'listAccessGrants',
8
+ create: 'createAccessGrant',
9
+ get: 'getAccessGrant',
10
+ revoke: 'revokeAccessGrant',
11
+ });
12
+
13
+ function operationKey(value) {
14
+ const action = String(value || 'list').trim().toLowerCase();
15
+ return OPERATIONS[action] ? action : '';
16
+ }
17
+
18
+ async function grantCommand(projectDir, positional, flags = {}) {
19
+ const action = operationKey(positional[0]);
20
+ if (!action) {
21
+ log.err('Usage: draftgo grant list|create|get|revoke [--input <json-file>]');
22
+ return 1;
23
+ }
24
+ return callOperation(projectDir, OPERATIONS[action], flags);
25
+ }
26
+
27
+ module.exports = grantCommand;
28
+ module.exports.OPERATIONS = OPERATIONS;
29
+ module.exports.operationKey = operationKey;
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const log = require('../logger');
4
+ const { callOperation } = require('./api');
5
+
6
+ const OPERATIONS = Object.freeze({
7
+ list: 'listUserGroups',
8
+ create: 'createUserGroup',
9
+ get: 'getUserGroup',
10
+ update: 'updateUserGroup',
11
+ replace: 'replaceUserGroup',
12
+ remove: 'removeUserGroup',
13
+ 'members.list': 'listUserGroupMembers',
14
+ 'members.add': 'addUserGroupMember',
15
+ 'members.remove': 'removeUserGroupMember',
16
+ });
17
+
18
+ function operationKey(parts) {
19
+ const values = parts.map((part) => String(part || '').trim().toLowerCase()).filter(Boolean);
20
+ if (values.length === 1) return values[0] === 'delete' ? 'remove' : values[0];
21
+ if (values.length === 2 && ['member', 'members'].includes(values[0])) {
22
+ return `members.${values[1] === 'delete' ? 'remove' : values[1]}`;
23
+ }
24
+ return '';
25
+ }
26
+
27
+ async function groupCommand(projectDir, positional, flags = {}) {
28
+ const key = operationKey(positional);
29
+ if (!OPERATIONS[key]) {
30
+ log.err('Usage: draftgo group list|create|get|update|replace|remove | members list|add|remove [--input <json-file>]');
31
+ return 1;
32
+ }
33
+ return callOperation(projectDir, OPERATIONS[key], flags);
34
+ }
35
+
36
+ module.exports = groupCommand;
37
+ module.exports.OPERATIONS = OPERATIONS;
38
+ module.exports.operationKey = operationKey;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { all } = require('../installers');
3
+ const { all } = require('../targets');
4
4
  const { HOSTS } = require('../mcp/hosts');
5
5
  const { getPackageVersion } = require('../skill');
6
6
 
@@ -13,8 +13,8 @@ function help() {
13
13
 
14
14
  console.log(`draftgo v${getPackageVersion()} - DraftGo workbench CLI for AI coding agents
15
15
 
16
- DraftGo Next frontend baseline: React + Vite.
17
- Database pages may use native web technologies or bundled component libraries.
16
+ DraftGo shell baseline: React + Vite. Database Pages default to native HTML,
17
+ Tailwind CSS 4, and Basecoat UI; Oat UI remains an optional Web Components layer.
18
18
  MCP handles live discovery and structured resources; complete page, navigation,
19
19
  document, and custom-service bodies use checkout/commit outside MCP context.
20
20
  The installed Skill routes agents to task-specific References and MCP tools.
@@ -26,9 +26,9 @@ Usage:
26
26
  refresh installed or detected Skills.
27
27
  draftgo uninstall <target|all> Remove Skill files. --purge also removes
28
28
  the entire .draftgo/ runtime directory.
29
- draftgo status Show installed targets and Skill version.
29
+ draftgo status Show connection health, current scope, targets, and Skill version.
30
30
 
31
- draftgo connect [<target>...] Verify and save server/SAT, then configure
31
+ draftgo connect [<target>...] Verify and save server/API Key, then configure
32
32
  a detected or explicit MCP host. This never
33
33
  downloads DraftGo business resources.
34
34
  draftgo mcp setup [<target>...] Merge project-level stdio MCP configuration.
@@ -36,24 +36,42 @@ Usage:
36
36
  draftgo mcp test Test project, resource, and API MCP calls.
37
37
  draftgo mcp serve Bridge local stdio to the remote /mcp endpoint.
38
38
 
39
- draftgo map Read remote overview/resources through MCP and
40
- overlay local checkout state.
41
- draftgo checkout <type> <id...> Download pages/nav/docs body + verified base.
39
+ draftgo map [--type <type>] Locate bounded remote resource metadata and
40
+ overlay matching local checkout state.
41
+ Use --route/--title for exact selection.
42
+ draftgo checkout <type> <id...> Download a long-form body + verified base,
43
+ including custom-service worktrees.
42
44
  --force explicitly replaces local changes.
43
45
  draftgo check [custom-services <id...>]
44
46
  Validate all checkouts or selected custom services.
45
47
  --remote also compares remote hash/version.
46
- draftgo verify [<type> <id...>] Run unified static verification; --remote adds
47
- remote comparison and --url enables UI checks.
48
- draftgo diff <type> <id> Show checkout base versus local body.
49
- draftgo commit <type> <id...> Validate and upload complete checked-out bodies.
48
+ draftgo verify [<type> <id...>] Run the default delivery verification.
49
+ Browser options are explicit and optional.
50
+ draftgo diff <type> <id> Show checkout base versus local body/files.
51
+ --stat/--summary omit the full patch.
52
+ draftgo commit <type> <id...> Validate and upload complete checked-out bodies/files.
53
+ draftgo components search <query> Search the live component catalog.
54
+ draftgo components show <library/component>
55
+ Show HTML, props, slots, CSS variables and revision.
56
+ draftgo components expand --page <id> --instance <data-dg-instance>
57
+ Expand one component in a checked-out Page worktree.
58
+ draftgo components libraries list|show|create|update|delete
59
+ Manage component libraries.
60
+ draftgo components list|create|copy|delete
61
+ Manage component catalog entries.
62
+ draftgo components checkout|diff|verify|commit|publish <library/component>
63
+ Develop a component draft locally, then publish explicitly.
64
+ draftgo components import <zip> [--dry-run]
65
+ draftgo components export <library> [--file <zip>]
66
+ Transfer standard DraftGo component archives.
50
67
  draftgo refresh <type> <id...> Safely refresh a clean checkout from the cloud.
51
68
  draftgo validate custom-services <id>
52
69
  Build and inspect the current cloud draft.
53
- draftgo test custom-services <id> [--handler <selector>]
70
+ draftgo test custom-services <id> [--source <source>] [--input <file>] [--handler <selector>]
54
71
  Run the cloud draft in the DraftGo Runner.
55
72
  draftgo publish custom-services <id...>
56
- Publish validated drafts atomically.
73
+ Publish current validated drafts; batch errors
74
+ report services already completed.
57
75
  draftgo reconcile <type> <id...> Repair stale metadata only when local equals remote.
58
76
  draftgo conflicts List unresolved conflicts; --all includes resolved.
59
77
  draftgo conflict show <type> <id>
@@ -61,37 +79,40 @@ Usage:
61
79
  draftgo conflict resolve <type> <id>
62
80
  Mark a merged worktree file ready against the
63
81
  preserved remote base; then check/diff/commit.
64
- draftgo verify-ui <url> Deprecated alias for verify --url <url> --ui always.
65
82
  draftgo clean [--dry-run|--yes] Plan or remove all tmp and registered artifacts.
66
- draftgo task <operation> [...] Track sustained work in one authoritative Task.md.
67
- Operations: create, list, show, add, claim,
68
- start, complete, block, reopen, accept, finish,
69
- and explicit legacy migrate.
83
+ draftgo work start <item> Add an active item to .draftgo/worklog.md.
84
+ draftgo work add <item> Add a pending item.
85
+ draftgo work start-item <ref> Mark an item active; ref is number or date#number.
86
+ draftgo work complete <ref> Mark an item complete; --note appends evidence.
87
+ draftgo work show|list Show the worklog or its structured item list.
70
88
 
71
89
  draftgo api <query> Search the live API contract through MCP.
72
90
  draftgo api describe <operation_id>
73
91
  Describe one live API operation through MCP.
74
92
  draftgo api call <operation_id> --input <json-file>
75
93
  Call one described operation with UTF-8 JSON.
94
+ draftgo capabilities list|search|show|audit
95
+ Discover and audit the current server's live operation catalog.
96
+ draftgo space <action> Manage spaces and workspace members.
97
+ draftgo group <action> Manage workspace groups and group members.
98
+ draftgo grant list|create|get|revoke
99
+ Manage platform/space AccessGrants.
100
+ draftgo api-key status|create|update|delete|rotate|reset|enable|disable
101
+ Manage the current user's API key through MCP.
102
+ draftgo role permissions|list|create|get|update|delete
103
+ Manage structured permission templates.
104
+ draftgo data-range list|create|get|update|batch|delete
105
+ Manage db_meta record policies (none|owner|all).
76
106
  draftgo delete <operation_id> [id]
77
107
  Confirm and call a live delete operation.
78
- Legacy <type> <id> works only when unambiguous.
79
108
  draftgo deploy [<type> <id...>] Check, then diff or commit checked-out content.
80
109
  --delivery local needs no IDs; preview/deploy
81
110
  require an explicit type and IDs.
82
111
  draftgo auto-push [<type> <id...>]
83
112
  With config.auto_push=true, check and commit
84
113
  changed checkouts. Any conflict stops the run.
85
- draftgo changelog add <result> Append one completed result after the task has
86
- passed unified verification and delivery.
87
- draftgo pull Migration notice only; always downloads nothing.
88
- draftgo push <type> <id...> Deprecated alias to commit for pages/nav/docs.
89
- Push-all and structured-resource push are removed.
90
-
91
114
  draftgo local setup|start|stop|logs|status
92
- Manage the existing local Docker stack. up/down
93
- remain aliases for start/stop; status also has ps.
94
- draftgo local-dev Compatibility alias for \`draftgo local setup\`.
115
+ Manage the project-local Docker stack.
95
116
  draftgo list-targets List Skill installation targets.
96
117
  draftgo -v | --version Print CLI version.
97
118
  draftgo -h | --help Show this help.
@@ -105,7 +126,9 @@ Important flags:
105
126
  --server <url> (connect) DraftGo base URL.
106
127
  --mcp-url <url> (connect) Explicit endpoint; standard /mcp derives the
107
128
  base URL; custom paths also need --server.
108
- --token <sat> (connect) SAT for non-interactive use.
129
+ --api-key <key> (connect) DraftGo user API Key for non-interactive use.
130
+ --scope-type space --space-id <id>
131
+ (connect) Save a target space for workspace resources.
109
132
  --timeout <ms> (connect/mcp test) Network timeout.
110
133
  --allow-offline (connect) Save only after explicitly accepting a
111
134
  failed MCP validation.
@@ -114,42 +137,49 @@ Important flags:
114
137
  --purge (uninstall) Also remove the .draftgo/ directory.
115
138
  --skip-update-check (update) Refresh Skills without contacting npm.
116
139
  --connect (init) Continue into DraftGo server connection.
117
- --local-dev (init) Continue into local Docker setup.
118
140
  --no-setup (init) Install the Skill without either setup flow.
119
141
  --output json Print machine-readable output where supported.
120
- --type <type> (map) pages | nav/navigations | docs/articles.
142
+ --type <type> (map) pages | nav/navigations | docs/articles |
143
+ custom-services.
144
+ --route <path> (map) Select resources with this exact route.
145
+ --title <title> (map) Select resources with this exact title.
146
+ --limit <1-100> (map) Maximum resources returned per type/page;
147
+ defaults to 20.
148
+ --cursor <cursor> (map) Continue one typed map result page.
149
+ --summary (map/diff) Print bounded resource or change summary.
150
+ --stat (diff) Print per-file and total change statistics.
121
151
  --strict Treat check warnings as failures.
122
152
  --remote (check) Compare checkout hashes/versions with remote.
123
153
  --yes Skip supported confirmation prompts.
124
154
  --operation-id <id> (delete) Select an operation explicitly.
125
155
  --params <json> (api call/delete) Pass an API parameter object.
126
- --input <file> (api call/delete) Read a UTF-8 JSON parameter object.
156
+ --input <file> (api call/delete/custom-service test) Read a UTF-8
157
+ JSON object.
127
158
  --handler <selector> (custom-service test) route:METHOD:/path, event:name,
128
159
  scheduled:name, or a handler name.
160
+ --source <source> (custom-service test) draft (default), auto, or published.
129
161
  --headers/--user <file> (custom-service test) Read JSON test identity data.
130
162
  --test-write (custom-service test) Permit declared write testing.
131
163
  --side-effect-policy <mode>
132
164
  (custom-service test) deny | mock | live; default deny.
133
165
  --delivery <mode> (deploy) local | preview | deploy.
134
- --dry-run (push) Show diffs without committing.
135
- --ui <mode> (verify) auto | always | never; auto runs with --url.
166
+ --dry-run Preview supported cleanup or delivery operations.
167
+ --ui <mode> (verify) always | never; default never.
136
168
  --remote (check/verify) Compare checkout hashes with remote.
137
169
  --viewport <mode> (verify) mobile | desktop | both.
138
170
  --frame <mode> (verify) auto | top | all | <iframe-selector>.
139
- --mobile-check <mode> (verify-ui compatibility) auto | always | never.
140
171
  --token <mode> (verify) auto | never; auto appends the configured
141
- SAT to same-origin URLs as the token query parameter.
142
- --screenshot <mode> (verify) on-failure | always | never; default never.
172
+ API Key to same-origin URLs as the token query parameter.
173
+ --screenshot <mode> (verify) always | never; always alone captures a screenshot.
143
174
  --browser <name> (verify) chromium | chrome | msedge.
144
175
  --browser-path <file> (verify) Explicit browser executable; environment
145
176
  fallback: DRAFTGO_BROWSER_PATH.
146
- --resource <type:id> (verify compatibility) Assert one remote UI resource.
147
177
  --selector <css> (verify) Require a visible element in top or iframe DOM.
148
- --width/--height <px> (verify) Override the default 390x844 viewport.
178
+ --width/--height <px> (verify) Override the default 1440x900 desktop viewport.
149
179
 
150
180
  Security:
151
- .draftgo/config.json stores the server and SAT and is gitignored. Host MCP
152
- files contain only "draftgo mcp serve"; they never contain the SAT.
181
+ .draftgo/config.json stores the server and API Key and is gitignored. Host MCP
182
+ files contain only "draftgo mcp serve"; they never contain the API Key.
153
183
 
154
184
  MCP targets (project config or status):
155
185
  ${mcpTargets}
@@ -159,18 +189,17 @@ ${targets}
159
189
 
160
190
  Examples:
161
191
  draftgo init codex
162
- draftgo connect codex --server https://draftgo.example --token <sat>
192
+ draftgo connect codex --server https://draftgo.example --api-key <key>
163
193
  draftgo mcp test
164
- draftgo map --output json
194
+ draftgo map --type pages --route /admin/channel-ops --summary --output json
165
195
  draftgo checkout pages 42
166
- draftgo check --strict
167
- draftgo verify pages 42 --remote --url http://localhost:5173/example
168
- draftgo diff pages 42
196
+ draftgo verify pages 42
197
+ draftgo diff pages 42 --stat
169
198
  draftgo commit pages 42
170
- draftgo changelog add "Complete document management and role permissions"
171
- draftgo task create "Personal growth" --original "Build a Notion-like system" \
172
- --clarified "Build goals, habits, notes, and reviews" \
173
- --expected-effect "Users manage personal growth in one workspace"
199
+ draftgo checkout custom-services 12
200
+ draftgo test custom-services 12 --handler route:POST:/health --input request.json
201
+ draftgo work start "Build document management and role permissions"
202
+ draftgo work complete 1 --note "Verification and delivery passed"
174
203
  draftgo deploy docs 7 --delivery preview
175
204
  `);
176
205
  }
@@ -3,7 +3,7 @@
3
3
  const path = require('path');
4
4
  const log = require('../logger');
5
5
  const { detectTargets } = require('../detect');
6
- const { resolveTargets, all } = require('../installers');
6
+ const { resolveTargets, all } = require('../targets');
7
7
  const { ensureRuntime, getPackageVersion } = require('../skill');
8
8
  const { exists } = require('../fsx');
9
9
  const { ask } = require('../prompt');
@@ -76,29 +76,23 @@ async function init(projectDir, positional, flags) {
76
76
  const cfgPath = path.join(projectDir, '.draftgo', 'config.json');
77
77
  const hasConfig = exists(cfgPath);
78
78
  const flagConnect = flags.connect === true;
79
- const flagLocalDev = flags['local-dev'] === true;
80
- const flagSkip = flags['no-local-dev'] === true
81
- || flags['skip-local-dev'] === true
82
- || flags['no-setup'] === true;
79
+ const flagSkip = flags['no-setup'] === true;
83
80
  const interactive = process.stdin.isTTY && process.stdout.isTTY;
84
81
 
85
82
  if (!hasConfig && !flagSkip) {
86
- // 非交互场景下,如果同时给了 --server --token,直接走 connect,不再阻塞在 TTY 提示上。
87
- if (flags.server && flags.token && !flagConnect && !flagLocalDev) {
83
+ // Non-interactive setup can connect immediately with a server and API Key.
84
+ if (flags.server && (flags['api-key'] || flags.token) && !flagConnect) {
88
85
  return await require('./connect')(projectDir, [], flags);
89
86
  }
90
87
  if (flagConnect) {
91
88
  return await require('./connect')(projectDir, [], flags);
92
89
  }
93
- if (flagLocalDev) {
94
- return await require('./localDev')(projectDir, [], flags);
95
- }
96
90
  if (interactive) {
97
91
  log.title('选择 DraftGo 基座处理方式');
98
92
  log.plain(` ${log.c.cyan('[A]')} 连接基座服务`);
99
93
  log.dim(' 使用已有 DraftGo 服务,接下来输入 BaseURL 和系统访问令牌。');
100
94
  log.plain(` ${log.c.cyan('[B]')} 本地启动基座`);
101
- log.dim(' 使用 Docker 启动 DraftGo;按需准备共享的 MySQL、Redis 和 Milvus。');
95
+ log.dim(' 使用 Docker 启动 DraftGo;按需准备共享的 MySQL、Redis 和 Qdrant。');
102
96
  log.plain(` ${log.c.cyan('[C]')} 稍后自行处理`);
103
97
  log.dim(' 仅安装 Skill,不写入服务配置,也不创建容器。');
104
98
  const choice = (await ask('请选择 [A/B/C]', { default: 'C' })).trim().toUpperCase();
@@ -106,7 +100,7 @@ async function init(projectDir, positional, flags) {
106
100
  return await require('./connect')(projectDir, [], flags);
107
101
  }
108
102
  if (choice === 'B') {
109
- return await require('./localDev')(projectDir, [], { ...flags, yes: true });
103
+ return await require('../localRuntime').runWizard(projectDir, { yes: true });
110
104
  }
111
105
  if (choice !== 'C') {
112
106
  log.warn('无效选择,已跳过基座处理。');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { all } = require('../installers');
3
+ const { all } = require('../targets');
4
4
 
5
5
  function listTargets() {
6
6
  console.log('draftgo 支持的 AI 工具(target):');