linmux 0.1.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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/bin/run.js +4 -0
  4. package/dist/commands/comment/create.js +94 -0
  5. package/dist/commands/comment/delete.js +74 -0
  6. package/dist/commands/comment/list.js +84 -0
  7. package/dist/commands/comment/update.js +80 -0
  8. package/dist/commands/cycle/current.js +78 -0
  9. package/dist/commands/cycle/list.js +84 -0
  10. package/dist/commands/cycle/move.js +91 -0
  11. package/dist/commands/describe.js +65 -0
  12. package/dist/commands/graphql/index.js +92 -0
  13. package/dist/commands/install-skill.js +54 -0
  14. package/dist/commands/issue/archive.js +75 -0
  15. package/dist/commands/issue/create.js +115 -0
  16. package/dist/commands/issue/get.js +84 -0
  17. package/dist/commands/issue/list.js +93 -0
  18. package/dist/commands/issue/purge.js +81 -0
  19. package/dist/commands/issue/search.js +109 -0
  20. package/dist/commands/issue/transition.js +91 -0
  21. package/dist/commands/issue/trash.js +75 -0
  22. package/dist/commands/issue/update.js +126 -0
  23. package/dist/commands/label/create.js +91 -0
  24. package/dist/commands/label/list.js +76 -0
  25. package/dist/commands/list-tools.js +47 -0
  26. package/dist/commands/me.js +71 -0
  27. package/dist/commands/project/create.js +101 -0
  28. package/dist/commands/project/get.js +83 -0
  29. package/dist/commands/project/list.js +75 -0
  30. package/dist/commands/project/update-status.js +99 -0
  31. package/dist/commands/project/update.js +99 -0
  32. package/dist/commands/raw/batch.js +85 -0
  33. package/dist/commands/raw/index.js +72 -0
  34. package/dist/commands/schema.js +69 -0
  35. package/dist/commands/state/list.js +77 -0
  36. package/dist/commands/team/get.js +73 -0
  37. package/dist/commands/team/list.js +73 -0
  38. package/dist/commands/whoami.js +71 -0
  39. package/dist/commands/workspace/add.js +97 -0
  40. package/dist/commands/workspace/list.js +47 -0
  41. package/dist/commands/workspace/remove.js +63 -0
  42. package/dist/commands/workspace/replace-token.js +89 -0
  43. package/dist/commands/workspace/use.js +54 -0
  44. package/dist/core/client/factory.js +28 -0
  45. package/dist/core/client/index.js +2 -0
  46. package/dist/core/config/index.js +4 -0
  47. package/dist/core/config/paths.js +30 -0
  48. package/dist/core/config/schema.js +36 -0
  49. package/dist/core/config/store.js +149 -0
  50. package/dist/core/errors/error.js +142 -0
  51. package/dist/core/errors/exit-codes.js +70 -0
  52. package/dist/core/output/envelope.js +53 -0
  53. package/dist/core/output/format.js +42 -0
  54. package/dist/core/output/index.js +3 -0
  55. package/dist/core/pagination/flags.js +29 -0
  56. package/dist/core/pagination/index.js +2 -0
  57. package/dist/core/projection/presets.js +116 -0
  58. package/dist/core/projection/project.js +282 -0
  59. package/dist/core/redact/redact.js +45 -0
  60. package/dist/core/resolvers/cycle.js +60 -0
  61. package/dist/core/resolvers/index.js +7 -0
  62. package/dist/core/resolvers/label.js +54 -0
  63. package/dist/core/resolvers/project-status.js +42 -0
  64. package/dist/core/resolvers/project.js +43 -0
  65. package/dist/core/resolvers/state.js +46 -0
  66. package/dist/core/resolvers/team.js +50 -0
  67. package/dist/core/transport/fetch-interceptor.js +109 -0
  68. package/dist/core/transport/index.js +3 -0
  69. package/dist/core/transport/rate-limit.js +167 -0
  70. package/dist/core/workspace/resolver.js +70 -0
  71. package/dist/core/workspace/write-guard.js +43 -0
  72. package/dist/generated/graphql.js +89428 -0
  73. package/dist/generated/operations.js +3013 -0
  74. package/dist/lib/comment-create-runtime.js +96 -0
  75. package/dist/lib/comment-delete-runtime.js +46 -0
  76. package/dist/lib/comment-list-runtime.js +182 -0
  77. package/dist/lib/comment-update-runtime.js +93 -0
  78. package/dist/lib/cycle-current-runtime.js +90 -0
  79. package/dist/lib/cycle-list-runtime.js +151 -0
  80. package/dist/lib/cycle-move-runtime.js +142 -0
  81. package/dist/lib/describe-runtime.js +180 -0
  82. package/dist/lib/filter-heuristics.js +59 -0
  83. package/dist/lib/graphql-runtime.js +202 -0
  84. package/dist/lib/include-fragments.js +73 -0
  85. package/dist/lib/install-skill-runtime.js +228 -0
  86. package/dist/lib/introspection-registry.js +488 -0
  87. package/dist/lib/issue-archive-runtime.js +89 -0
  88. package/dist/lib/issue-create-runtime.js +175 -0
  89. package/dist/lib/issue-get-runtime.js +153 -0
  90. package/dist/lib/issue-list-runtime.js +164 -0
  91. package/dist/lib/issue-purge-runtime.js +89 -0
  92. package/dist/lib/issue-search-runtime.js +114 -0
  93. package/dist/lib/issue-transition-runtime.js +131 -0
  94. package/dist/lib/issue-trash-runtime.js +84 -0
  95. package/dist/lib/issue-update-runtime.js +164 -0
  96. package/dist/lib/label-create-runtime.js +113 -0
  97. package/dist/lib/label-list-runtime.js +97 -0
  98. package/dist/lib/levenshtein.js +42 -0
  99. package/dist/lib/list-tools-runtime.js +38 -0
  100. package/dist/lib/me-runtime.js +55 -0
  101. package/dist/lib/project-create-runtime.js +103 -0
  102. package/dist/lib/project-get-runtime.js +134 -0
  103. package/dist/lib/project-list-runtime.js +84 -0
  104. package/dist/lib/project-update-runtime.js +110 -0
  105. package/dist/lib/project-update-status-runtime.js +91 -0
  106. package/dist/lib/raw-batch-runtime.js +229 -0
  107. package/dist/lib/raw-runtime.js +171 -0
  108. package/dist/lib/schema-loader.js +41 -0
  109. package/dist/lib/schema-runtime.js +65 -0
  110. package/dist/lib/state-list-runtime.js +93 -0
  111. package/dist/lib/team-get-runtime.js +55 -0
  112. package/dist/lib/team-list-runtime.js +52 -0
  113. package/dist/lib/workspace-runtime.js +112 -0
  114. package/dist/operations/_registry.zod.js +5337 -0
  115. package/oclif.manifest.json +3631 -0
  116. package/package.json +99 -0
  117. package/schema.graphql +30772 -0
  118. package/skills/linmux/SKILL.md +186 -0
@@ -0,0 +1,55 @@
1
+ import { LinearAgentError } from "../core/errors/error.js";
2
+ import { getLastComplexity, withFetchInterception } from "../core/transport/fetch-interceptor.js";
3
+ import { withRateLimitRetry } from "../core/transport/rate-limit.js";
4
+ import "../core/transport/index.js";
5
+ import { createLinearClient } from "../core/client/factory.js";
6
+ import "../core/client/index.js";
7
+ import { loadConfig } from "../core/config/store.js";
8
+ import "../core/config/index.js";
9
+ import { parseFields, project } from "../core/projection/project.js";
10
+ import { resolveWorkspace } from "../core/workspace/resolver.js";
11
+ import { TEAM_KEY_RE, UUID_RE } from "./filter-heuristics.js";
12
+ //#region src/lib/team-get-runtime.ts
13
+ async function teamGetRuntime(input) {
14
+ const config = (input.loadConfigOverride ?? loadConfig)();
15
+ const envForResolver = {};
16
+ if (input.env.LINEAR_WORKSPACE !== void 0) envForResolver.LINEAR_WORKSPACE = input.env.LINEAR_WORKSPACE;
17
+ if (input.env.LINEAR_API_KEY !== void 0) envForResolver.LINEAR_API_KEY = input.env.LINEAR_API_KEY;
18
+ const resolved = resolveWorkspace({
19
+ flags: input.flags.workspace ? { workspace: input.flags.workspace } : {},
20
+ env: envForResolver,
21
+ config
22
+ });
23
+ const fields = parseFields(input.flags.fields ?? "defaults", "team");
24
+ const client = (input.clientFactoryOverride ?? createLinearClient)(resolved);
25
+ return withFetchInterception(async () => {
26
+ const ref = input.args.ref;
27
+ let team;
28
+ if (UUID_RE.test(ref)) team = await withRateLimitRetry(() => client.team(ref), input.retryOptsOverride);
29
+ else if (TEAM_KEY_RE.test(ref)) team = (await withRateLimitRetry(() => client.teams({
30
+ filter: { key: { eq: ref.toUpperCase() } },
31
+ first: 1
32
+ }), input.retryOptsOverride)).nodes[0];
33
+ else team = (await withRateLimitRetry(() => client.teams({
34
+ filter: { name: { eq: ref } },
35
+ first: 1
36
+ }), input.retryOptsOverride)).nodes[0];
37
+ if (!team) throw new LinearAgentError({
38
+ code: "TEAM_NOT_FOUND",
39
+ message: `team not found: ${ref}`,
40
+ details: { ref }
41
+ });
42
+ const data = project(team, fields);
43
+ const complexity = getLastComplexity();
44
+ return {
45
+ data,
46
+ meta: {
47
+ workspace: resolved.name,
48
+ workspaceSource: resolved.source,
49
+ ...complexity !== void 0 ? { complexity } : {}
50
+ }
51
+ };
52
+ });
53
+ }
54
+ //#endregion
55
+ export { teamGetRuntime };
@@ -0,0 +1,52 @@
1
+ import { getLastComplexity, withFetchInterception } from "../core/transport/fetch-interceptor.js";
2
+ import { withRateLimitRetry } from "../core/transport/rate-limit.js";
3
+ import "../core/transport/index.js";
4
+ import { createLinearClient } from "../core/client/factory.js";
5
+ import "../core/client/index.js";
6
+ import { loadConfig } from "../core/config/store.js";
7
+ import "../core/config/index.js";
8
+ import { parseFields, project } from "../core/projection/project.js";
9
+ import { resolveWorkspace } from "../core/workspace/resolver.js";
10
+ import { parsePagination } from "../core/pagination/flags.js";
11
+ import "../core/pagination/index.js";
12
+ //#region src/lib/team-list-runtime.ts
13
+ async function teamListRuntime(input) {
14
+ const config = (input.loadConfigOverride ?? loadConfig)();
15
+ const envForResolver = {};
16
+ if (input.env.LINEAR_WORKSPACE !== void 0) envForResolver.LINEAR_WORKSPACE = input.env.LINEAR_WORKSPACE;
17
+ if (input.env.LINEAR_API_KEY !== void 0) envForResolver.LINEAR_API_KEY = input.env.LINEAR_API_KEY;
18
+ const resolved = resolveWorkspace({
19
+ flags: input.flags.workspace ? { workspace: input.flags.workspace } : {},
20
+ env: envForResolver,
21
+ config
22
+ });
23
+ const fields = parseFields(input.flags.fields ?? "defaults", "team");
24
+ const { first, after } = parsePagination({
25
+ ...input.flags.limit !== void 0 ? { limit: input.flags.limit } : {},
26
+ ...input.flags.cursor !== void 0 ? { cursor: input.flags.cursor } : {}
27
+ });
28
+ const client = (input.clientFactoryOverride ?? createLinearClient)(resolved);
29
+ return withFetchInterception(async () => {
30
+ const teamsArgs = { first };
31
+ if (after !== void 0) teamsArgs.after = after;
32
+ const connection = await withRateLimitRetry(() => client.teams(teamsArgs), input.retryOptsOverride);
33
+ const projected = connection.nodes.map((node) => project(node, fields));
34
+ const complexity = getLastComplexity();
35
+ return {
36
+ data: projected,
37
+ meta: {
38
+ workspace: resolved.name,
39
+ workspaceSource: resolved.source,
40
+ pageInfo: {
41
+ hasNextPage: Boolean(connection.pageInfo?.hasNextPage),
42
+ endCursor: connection.pageInfo?.endCursor ?? null,
43
+ hasPreviousPage: Boolean(connection.pageInfo?.hasPreviousPage),
44
+ startCursor: connection.pageInfo?.startCursor ?? null
45
+ },
46
+ ...complexity !== void 0 ? { complexity } : {}
47
+ }
48
+ };
49
+ });
50
+ }
51
+ //#endregion
52
+ export { teamListRuntime };
@@ -0,0 +1,112 @@
1
+ import { LinearAgentError } from "../core/errors/error.js";
2
+ import { exitCodeFor } from "../core/errors/exit-codes.js";
3
+ import { failure, success } from "../core/output/envelope.js";
4
+ import { format } from "../core/output/format.js";
5
+ import "../core/output/index.js";
6
+ import { classifySdkError } from "../core/transport/rate-limit.js";
7
+ import "../core/transport/index.js";
8
+ import { Flags } from "@oclif/core";
9
+ //#region src/lib/workspace-runtime.ts
10
+ /**
11
+ * Shared runtime for workspace commands.
12
+ *
13
+ * Lives in `src/lib/` (not `src/commands/workspace/`) because oclif's manifest
14
+ * generator scans every file under `src/commands/` as a command — a helper
15
+ * file there would surface as `linmux workspace _shared`. The lib path
16
+ * also matches `tsdown.config.ts`'s entry globs (commands + lib double-star
17
+ * patterns) so the bundle layout stays predictable.
18
+ *
19
+ * Each oclif command file under `src/commands/workspace/` stays under ~50 LOC
20
+ * by delegating envelope formatting, error wrapping, exit-code mapping, and
21
+ * stdout/stderr writing to `runCommand` here. Tests call this helper (and the
22
+ * per-command `run<Cmd>` wrappers in each file) directly without spawning a
23
+ * subprocess.
24
+ *
25
+ * Flow:
26
+ * 1. Caller invokes `runCommand({ commandPath, pretty, handler })`.
27
+ * 2. Handler returns `{ data, meta }` for the success envelope.
28
+ * 3. We wrap the result in the locked Phase 1 envelope (PLAN-01) via
29
+ * `success(data, { ...meta, command: commandPath })` and return
30
+ * `{ stdout, stderr?, exitCode: 0 }`.
31
+ * 4. If the handler throws:
32
+ * - `LinearAgentError` → wrap as `failure(err, { command })`,
33
+ * exit code via `exitCodeFor(err.code)`.
34
+ * - Anything else → wrap as `LinearAgentError({ code: 'GENERIC_ERROR',
35
+ * message: 'Internal error', details: { cause: err.message } })`,
36
+ * exit code 1. The kernel-wide redactor in `format()` (PLAN-01) is
37
+ * the safety net that scrubs token-shaped substrings before stdout.
38
+ *
39
+ * This module imports from `@/core/output` and `@/core/errors` only — no
40
+ * filesystem, no SDK, no oclif. The oclif `Command.run()` shim is the
41
+ * thinnest possible glue (`process.stdout.write(out.stdout); process.exit(out.exitCode)`).
42
+ */
43
+ const BASE_FLAGS = {
44
+ pretty: Flags.boolean({ description: "Human-readable output (default is JSON)" }),
45
+ quiet: Flags.boolean({ description: "Suppress meta block from success envelopes and pretty-mode banners (implies --no-meta)." }),
46
+ noMeta: Flags.boolean({
47
+ name: "no-meta",
48
+ aliases: ["no-meta"],
49
+ description: "Omit the meta block from success envelopes (smaller token footprint; failure envelopes unchanged)."
50
+ }),
51
+ retry: Flags.integer({
52
+ description: "Extra retries on transient errors (added on top of defaults). Min 0.",
53
+ min: 0,
54
+ default: 0
55
+ })
56
+ };
57
+ async function runCommand(args) {
58
+ const dropMeta = args.quiet === true || args.noMeta === true;
59
+ const effectivePretty = args.pretty && !dropMeta;
60
+ const extraAttempts = args.retry ?? 0;
61
+ const retryOptsOverride = extraAttempts > 0 && args.quiet !== true ? {
62
+ extraAttempts,
63
+ onRetry: (info) => {
64
+ process.stderr.write(`[retry ${info.attempt}/${info.total}] ${info.code}: backing off ${info.backoffMs}ms\n`);
65
+ }
66
+ } : { extraAttempts };
67
+ try {
68
+ const { data, meta } = await args.handler(retryOptsOverride);
69
+ const out = format(dropMeta ? {
70
+ $apiVersion: "1",
71
+ ok: true,
72
+ data
73
+ } : success(data, {
74
+ ...meta,
75
+ command: args.commandPath
76
+ }), { pretty: effectivePretty });
77
+ return {
78
+ stdout: out.stdout,
79
+ stderr: out.stderr,
80
+ exitCode: 0
81
+ };
82
+ } catch (raw) {
83
+ const err = wrapAsLinearAgentError(raw);
84
+ const out = format(failure(err, { command: args.commandPath }), { pretty: effectivePretty });
85
+ return {
86
+ stdout: out.stdout,
87
+ stderr: out.stderr,
88
+ exitCode: exitCodeFor(err.code)
89
+ };
90
+ }
91
+ }
92
+ function wrapAsLinearAgentError(raw) {
93
+ if (raw instanceof LinearAgentError) return raw;
94
+ return new LinearAgentError({
95
+ code: "GENERIC_ERROR",
96
+ message: "Internal error",
97
+ details: { cause: raw instanceof Error ? raw.message : String(raw) }
98
+ });
99
+ }
100
+ /**
101
+ * Read the env vars our commands consult. Pure for testability — callers
102
+ * inject `process.env` so tests can pass a synthetic env without touching
103
+ * the real one.
104
+ */
105
+ function readEnv(env = process.env) {
106
+ const out = {};
107
+ if (env.LINEAR_WORKSPACE !== void 0) out.LINEAR_WORKSPACE = env.LINEAR_WORKSPACE;
108
+ if (env.LINEAR_API_KEY !== void 0) out.LINEAR_API_KEY = env.LINEAR_API_KEY;
109
+ return out;
110
+ }
111
+ //#endregion
112
+ export { BASE_FLAGS, classifySdkError, readEnv, runCommand };