@brainervirus/workit-core 0.6.0 → 0.7.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 (95) hide show
  1. package/package.json +10 -14
  2. package/scripts/doctor-check.ts +20 -0
  3. package/scripts/install-cursor-plugin.sh +51 -28
  4. package/scripts/install-opencode-plugin.sh +25 -22
  5. package/scripts/rewrite-workspace-deps.ts +15 -9
  6. package/scripts/sync-runtime.sh +71 -19
  7. package/scripts/vendor-assets.ts +37 -0
  8. package/skills/wk-implement/SKILL.md +2 -2
  9. package/skills/wk-pr/SKILL.md +1 -1
  10. package/src/core/boundary.ts +27 -0
  11. package/src/core/branch-policy.ts +63 -0
  12. package/src/core/branch.ts +166 -57
  13. package/src/core/changelog.ts +17 -14
  14. package/src/core/config-guard.ts +9 -2
  15. package/src/core/config.ts +227 -32
  16. package/src/core/detector.ts +22 -11
  17. package/src/core/docs-layout.ts +251 -0
  18. package/src/core/docs-migration.ts +639 -0
  19. package/src/core/docs-repo.ts +58 -21
  20. package/src/core/docs-validate.ts +181 -43
  21. package/src/core/doctor.ts +801 -0
  22. package/src/core/flow-state.ts +1579 -137
  23. package/src/core/git.ts +22 -5
  24. package/src/core/gitignore.ts +11 -2
  25. package/src/core/handoff-context.ts +18 -5
  26. package/src/{tools/handoff.ts → core/handoff-tools.ts} +16 -63
  27. package/src/core/hygiene.ts +53 -17
  28. package/src/core/init.ts +128 -31
  29. package/src/core/logger.ts +321 -0
  30. package/src/core/package-root.ts +28 -0
  31. package/src/core/parse-sections.ts +2 -2
  32. package/src/core/plan-tasks.ts +13 -3
  33. package/src/core/ports/init-toolkit-status.ts +1 -1
  34. package/src/core/ports/vcs-verify-token.ts +1 -1
  35. package/src/core/ports/youtrack-api.ts +4 -2
  36. package/src/core/ports/youtrack-config.ts +1 -3
  37. package/src/core/ports/youtrack-verify-token.ts +1 -1
  38. package/src/core/pr-create.ts +156 -29
  39. package/src/core/present.ts +11 -2
  40. package/src/core/registration.ts +215 -0
  41. package/src/core/reminder.ts +1 -2
  42. package/src/core/repo-context.ts +447 -0
  43. package/src/core/repo-tool.ts +4 -1
  44. package/src/core/repo-tools.ts +23 -0
  45. package/src/core/rules.ts +10 -7
  46. package/src/core/safe-write.ts +22 -0
  47. package/src/core/scripts.ts +3 -39
  48. package/src/core/sdd.ts +56 -31
  49. package/src/core/setup-state.ts +54 -0
  50. package/src/core/setup.ts +1216 -0
  51. package/src/core/skill-manifests.ts +95 -0
  52. package/src/core/support-matrix.ts +12 -0
  53. package/src/core/sync-runtime.ts +348 -0
  54. package/src/core/templates.ts +16 -6
  55. package/src/core/vcs-config.ts +191 -62
  56. package/src/core/verify-parse.ts +4 -2
  57. package/src/core/verify-project.ts +181 -0
  58. package/src/core/workspaces.ts +136 -17
  59. package/src/core/youtrack-tools.ts +228 -0
  60. package/src/core/youtrack.ts +320 -87
  61. package/src/core.ts +18 -3
  62. package/templates/execution-contract.md +9 -7
  63. package/templates/superpowers-doc-contract.md +5 -4
  64. package/scripts/_shared/common.sh +0 -158
  65. package/scripts/changelog-context.sh +0 -42
  66. package/scripts/docs-refresh-context.sh +0 -40
  67. package/scripts/init/apply.sh +0 -5
  68. package/scripts/init/status.sh +0 -5
  69. package/scripts/init/toolkit-status.sh +0 -5
  70. package/scripts/pr-create.sh +0 -5
  71. package/scripts/pr-ready-context.sh +0 -88
  72. package/scripts/present/ascii-wireframe.sh +0 -5
  73. package/scripts/present/flow-diagram.sh +0 -5
  74. package/scripts/release-notes-context.sh +0 -40
  75. package/scripts/vcs/config.sh +0 -5
  76. package/scripts/vcs/merged-style.sh +0 -5
  77. package/scripts/vcs/token-create-urls.sh +0 -5
  78. package/scripts/vcs/verify-token.sh +0 -5
  79. package/scripts/verify-project.sh +0 -140
  80. package/scripts/youtrack/api.sh +0 -5
  81. package/scripts/youtrack/config.sh +0 -5
  82. package/scripts/youtrack/greeting.sh +0 -5
  83. package/scripts/youtrack/parse-duration.sh +0 -5
  84. package/scripts/youtrack/token-create-url.sh +0 -5
  85. package/scripts/youtrack/verify-token.sh +0 -5
  86. package/scripts/youtrack/work-date-ms.sh +0 -5
  87. package/src/tools/docs-repo.ts +0 -42
  88. package/src/tools/flow.ts +0 -88
  89. package/src/tools/index.ts +0 -22
  90. package/src/tools/present.ts +0 -45
  91. package/src/tools/repo.ts +0 -357
  92. package/src/tools/rules.ts +0 -30
  93. package/src/tools/sdd.ts +0 -189
  94. package/src/tools/templates.ts +0 -27
  95. package/src/tools/youtrack.ts +0 -360
@@ -1,140 +0,0 @@
1
- #!/bin/sh
2
-
3
- set -u
4
-
5
- root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
6
- cd "$root" || exit 1
7
-
8
- dry_run=false
9
- case " ${*:-} " in
10
- *" --dry-run "*) dry_run=true ;;
11
- *" dry-run "*) dry_run=true ;;
12
- esac
13
-
14
- passed=0
15
- failed=0
16
- skipped=0
17
-
18
- run_check() {
19
- label=$1
20
- shift
21
- printf '\n## %s\n\n' "$label"
22
- printf 'command: %s\n\n' "$*"
23
- if [ "$dry_run" = true ]; then
24
- printf 'status: skipped (dry run)\n'
25
- skipped=$((skipped + 1))
26
- return 0
27
- fi
28
- "$@"
29
- code=$?
30
- if [ "$code" -eq 0 ]; then
31
- printf '\nstatus: pass\n'
32
- passed=$((passed + 1))
33
- else
34
- printf '\nstatus: fail (exit %s)\n' "$code"
35
- failed=$((failed + 1))
36
- fi
37
- return 0
38
- }
39
-
40
- skip_check() {
41
- label=$1
42
- reason=$2
43
- printf '\n## %s\n\nstatus: skipped (%s)\n' "$label" "$reason"
44
- skipped=$((skipped + 1))
45
- }
46
-
47
- has_script() {
48
- name=$1
49
- [ -f package.json ] || return 1
50
- node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts['$name'] ? 0 : 1)" >/dev/null 2>&1
51
- }
52
-
53
- package_runner() {
54
- if [ -f pnpm-lock.yaml ] || grep -q '"packageManager"[[:space:]]*:[[:space:]]*"pnpm' package.json 2>/dev/null; then
55
- printf 'pnpm'
56
- elif [ -f yarn.lock ]; then
57
- printf 'yarn'
58
- elif [ -f package-lock.json ]; then
59
- printf 'npm'
60
- else
61
- printf 'npm'
62
- fi
63
- }
64
-
65
- printf '# Verification Context\n'
66
- printf '\nroot: %s\n' "$root"
67
- printf 'dry_run: %s\n' "$dry_run"
68
-
69
- if [ -f package.json ]; then
70
- runner=$(package_runner)
71
- for script in lint format:check test build; do
72
- if has_script "$script"; then
73
- if [ "$runner" = "npm" ]; then
74
- run_check "$script" npm run "$script"
75
- else
76
- run_check "$script" "$runner" "$script"
77
- fi
78
- else
79
- skip_check "$script" "package.json has no $script script"
80
- fi
81
- done
82
- else
83
- skip_check "javascript" "package.json not found"
84
- fi
85
-
86
- cargo_manifest=""
87
- if [ -f Cargo.toml ]; then
88
- cargo_manifest="Cargo.toml"
89
- elif [ -f src-tauri/Cargo.toml ]; then
90
- cargo_manifest="src-tauri/Cargo.toml"
91
- fi
92
-
93
- if [ "$cargo_manifest" != "" ]; then
94
- run_check "cargo fmt" cargo fmt --manifest-path "$cargo_manifest" -- --check
95
- run_check "cargo clippy" cargo clippy --manifest-path "$cargo_manifest" --all-targets -- -D warnings
96
- run_check "cargo test" cargo test --manifest-path "$cargo_manifest" --all-targets
97
- else
98
- skip_check "rust" "Cargo.toml not found"
99
- fi
100
-
101
- if [ -f pyproject.toml ] || [ -f pytest.ini ] || [ -d tests ]; then
102
- if command -v pytest >/dev/null 2>&1; then
103
- run_check "pytest" pytest
104
- else
105
- skip_check "pytest" "pytest not available"
106
- fi
107
- if command -v ruff >/dev/null 2>&1; then
108
- run_check "ruff check" ruff check .
109
- else
110
- skip_check "ruff check" "ruff not available"
111
- fi
112
- fi
113
-
114
- printf '\n## CHANGELOG.md format\n\n'
115
- printf 'command: grep -qi "## [Unreleased]" CHANGELOG.md\n\n'
116
-
117
- if [ "$dry_run" = true ]; then
118
- printf 'status: skipped (dry run)\n'
119
- skipped=$((skipped + 1))
120
- elif [ -f CHANGELOG.md ]; then
121
- if grep -qi '## \[Unreleased\]' CHANGELOG.md; then
122
- printf 'status: pass\n'
123
- passed=$((passed + 1))
124
- else
125
- printf 'status: fail (missing ## [Unreleased])\n'
126
- failed=$((failed + 1))
127
- fi
128
- else
129
- printf 'status: fail (missing CHANGELOG.md)\n'
130
- failed=$((failed + 1))
131
- fi
132
-
133
- printf '\n# Summary\n\n'
134
- printf 'passed: %s\n' "$passed"
135
- printf 'failed: %s\n' "$failed"
136
- printf 'skipped: %s\n' "$skipped"
137
-
138
- if [ "$failed" -gt 0 ]; then
139
- exit 1
140
- fi
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-api.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-api.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-config.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-config.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-greeting.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-greeting.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-parse-duration.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-parse-duration.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-token-create-url.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-token-create-url.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-verify-token.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-verify-token.ts" "$@"
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Ported to TS — CLI contract kept: execs bun <core>/ports/youtrack-work-date-ms.ts
3
- set -euo pipefail
4
- SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
- exec bun "$SCRIPT_DIR/../../src/core/ports/youtrack-work-date-ms.ts" "$@"
@@ -1,42 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
- import { fail, ok } from "../core";
3
- import { linkDocsRepo, listSpecs, promoteSpec } from "../core/docs-repo";
4
-
5
- const output = (value: unknown) => JSON.stringify(value, null, 2);
6
-
7
- export function createDocsRepoTools() {
8
- return {
9
- workflow_docs_repo_link: tool({
10
- description: "Link the component docs repo in the toolkit config (validates git repo + features/)",
11
- args: {
12
- path: tool.schema.string(),
13
- confirmed: tool.schema.boolean(),
14
- },
15
- execute: async ({ path: docsPath, confirmed }, _context) => {
16
- const result = linkDocsRepo(docsPath, confirmed);
17
- return output(result.ok ? ok({ path: result.path }) : fail(result.error));
18
- },
19
- }),
20
- workflow_docs_list: tool({
21
- description: "List local specs (docs/<slug>/spec.md) with docs-repo promotion status",
22
- args: {},
23
- execute: async (_input, context) => {
24
- const result = listSpecs(context.directory);
25
- return output(ok(result));
26
- },
27
- }),
28
- workflow_docs_promote: tool({
29
- description: "Promote a spec (+plan) to the linked docs repo features/YYYY-MM-<slug>/ with quality gate",
30
- args: {
31
- slug: tool.schema.string(),
32
- confirmed: tool.schema.boolean(),
33
- force: tool.schema.boolean().optional(),
34
- },
35
- execute: async ({ slug, confirmed, force }, context) => {
36
- const result = promoteSpec(context.directory, slug, { confirmed, force });
37
- if (result.ok) return output(ok({ target_dir: result.target_dir, files: result.files, index_updated: result.index_updated }));
38
- return output(fail(result.error, { findings: result.findings ?? [] } as never));
39
- },
40
- }),
41
- };
42
- }
package/src/tools/flow.ts DELETED
@@ -1,88 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
- import { fail, ok } from "../core";
3
- import {
4
- readFlowState,
5
- transitionSpec,
6
- transitionPlan,
7
- recordMenuChoice,
8
- slugFromPath,
9
- } from "../core/flow-state";
10
- import path from "node:path";
11
-
12
- const output = (value: unknown) => JSON.stringify(value, null, 2);
13
-
14
- const flowPathFor = (slug: string) =>
15
- path.posix.join("docs", slug, "sdd", "flow.json");
16
-
17
- export function createFlowTools() {
18
- return {
19
- workflow_flow_status: tool({
20
- description: "Read the spec/plan approval flow state for a workflow",
21
- args: {
22
- plan_path: tool.schema.string().optional(),
23
- spec_path: tool.schema.string().optional(),
24
- },
25
- execute: async ({ plan_path, spec_path }, context) => {
26
- try {
27
- const slug = slugFromPath(plan_path ?? spec_path ?? "");
28
- if (!slug) return output(fail("plan_path or spec_path required"));
29
- const state = readFlowState(context.directory, slug);
30
- return output(ok({
31
- slug,
32
- spec: state.spec,
33
- plan: state.plan,
34
- menu: state.menu,
35
- flow_path: flowPathFor(slug),
36
- }));
37
- } catch (error) {
38
- return output(fail(error instanceof Error ? error.message : "flow status failed"));
39
- }
40
- },
41
- }),
42
- workflow_spec_approve: tool({
43
- description: "Advance spec status: first call self_reviewed, second call approved (after user approval)",
44
- args: {
45
- confirmed: tool.schema.boolean(),
46
- spec_path: tool.schema.string(),
47
- },
48
- execute: async ({ confirmed, spec_path }, context) => {
49
- const slug = slugFromPath(spec_path);
50
- const result = transitionSpec(context.directory, slug, spec_path, confirmed);
51
- return output(
52
- result.ok
53
- ? ok({ spec: spec_path, status: readFlowState(context.directory, slug).spec.status })
54
- : fail(result.error),
55
- );
56
- },
57
- }),
58
- workflow_plan_approve: tool({
59
- description: "Advance plan status: first call self_reviewed, second call approved. Requires approved spec.",
60
- args: {
61
- confirmed: tool.schema.boolean(),
62
- plan_path: tool.schema.string(),
63
- },
64
- execute: async ({ confirmed, plan_path }, context) => {
65
- const slug = slugFromPath(plan_path);
66
- const result = transitionPlan(context.directory, slug, plan_path, confirmed);
67
- return output(
68
- result.ok
69
- ? ok({ plan: plan_path, status: readFlowState(context.directory, slug).plan.status })
70
- : fail(result.error),
71
- );
72
- },
73
- }),
74
- workflow_plan_menu: tool({
75
- description: "Record the answered post-plan choice menu (called after native question)",
76
- args: {
77
- confirmed: tool.schema.boolean(),
78
- plan_path: tool.schema.string(),
79
- choice: tool.schema.enum(["subagent-driven", "inline", "handoff", "review-spec", "review-plan"]),
80
- },
81
- execute: async ({ confirmed, plan_path, choice }, context) => {
82
- const slug = slugFromPath(plan_path);
83
- const result = recordMenuChoice(context.directory, slug, plan_path, choice, confirmed);
84
- return output(result.ok ? ok({ menu: { presented: true, chosen: choice } }) : fail(result.error));
85
- },
86
- }),
87
- };
88
- }
@@ -1,22 +0,0 @@
1
- import { createRepoTools } from "./repo";
2
- import { WorkflowStateStore } from "../state";
3
- import { createSddTools } from "./sdd";
4
- import { createHandoffTools, type HandoffClient } from "./handoff";
5
- import { createYouTrackTools } from "./youtrack";
6
- import { createPresentTools } from "./present";
7
- import { createFlowTools } from "./flow";
8
- import { createDocsRepoTools } from "./docs-repo";
9
- import { createTemplateTools } from "./templates";
10
- import { createRuleTools } from "./rules";
11
-
12
- export const createTools = (client: HandoffClient, state: WorkflowStateStore) => ({
13
- ...createRepoTools(),
14
- ...createSddTools(state),
15
- ...createHandoffTools(client, state),
16
- ...createYouTrackTools(),
17
- ...createPresentTools(),
18
- ...createFlowTools(),
19
- ...createDocsRepoTools(),
20
- ...createTemplateTools(),
21
- ...createRuleTools(),
22
- });
@@ -1,45 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
- import { fail, ok } from "../core";
3
- import { asciiWireframe, flowDiagram } from "../core/present";
4
-
5
- const output = (value: unknown) => JSON.stringify(value, null, 2);
6
-
7
- export function createPresentTools() {
8
- return {
9
- workflow_present_ascii: tool({
10
- description: "Render deterministic ASCII UI wireframe from JSON spec",
11
- args: {
12
- title: tool.schema.string().optional(),
13
- width: tool.schema.number().optional(),
14
- rows: tool.schema.array(tool.schema.record(tool.schema.string(), tool.schema.any())),
15
- },
16
- execute: async (spec) => {
17
- const result = asciiWireframe(spec);
18
- if ("error" in result) return output(fail(result.error));
19
- return output(ok(result.data));
20
- },
21
- }),
22
- workflow_present_flow: tool({
23
- description: "Render mermaid flowchart from JSON nodes/edges",
24
- args: {
25
- title: tool.schema.string().optional(),
26
- direction: tool.schema.enum(["TD", "LR", "BT", "RL"]).optional(),
27
- nodes: tool.schema.array(tool.schema.object({
28
- id: tool.schema.string(),
29
- label: tool.schema.string(),
30
- shape: tool.schema.string().optional(),
31
- })),
32
- edges: tool.schema.array(tool.schema.object({
33
- from: tool.schema.string(),
34
- to: tool.schema.string(),
35
- label: tool.schema.string().optional(),
36
- })),
37
- },
38
- execute: async (spec) => {
39
- const result = flowDiagram(spec);
40
- if ("error" in result) return output(fail(result.error));
41
- return output(ok(result.data));
42
- },
43
- }),
44
- };
45
- }