@elalfner/relevo 0.0.0-stage → 0.3.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 (139) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +51 -0
  4. package/README.es.md +90 -0
  5. package/README.md +89 -2
  6. package/agents/dev.md +101 -0
  7. package/agents/qa.md +112 -0
  8. package/package.json +42 -4
  9. package/scripts/add-corrections.mjs +21 -0
  10. package/scripts/app-id.mjs +19 -0
  11. package/scripts/archive-state.mjs +31 -0
  12. package/scripts/branch-state.mjs +31 -0
  13. package/scripts/branch-work.mjs +25 -0
  14. package/scripts/can-edit-issue.mjs +45 -0
  15. package/scripts/capture.mjs +22 -0
  16. package/scripts/check-archive.mjs +19 -0
  17. package/scripts/check-issue.mjs +41 -0
  18. package/scripts/checklist.mjs +29 -0
  19. package/scripts/cli.mjs +28 -0
  20. package/scripts/commit-change.mjs +50 -0
  21. package/scripts/conflict-scope.mjs +19 -0
  22. package/scripts/design-fetch.mjs +103 -0
  23. package/scripts/device.mjs +12 -0
  24. package/scripts/digest.mjs +50 -0
  25. package/scripts/doctor.mjs +47 -0
  26. package/scripts/fix-guard.mjs +38 -0
  27. package/scripts/fix-stash.mjs +57 -0
  28. package/scripts/fix-state.mjs +28 -0
  29. package/scripts/fix-tasks.mjs +22 -0
  30. package/scripts/go-local.mjs +49 -0
  31. package/scripts/go-plan.mjs +82 -0
  32. package/scripts/init.mjs +109 -0
  33. package/scripts/intent-to-add.mjs +20 -0
  34. package/scripts/issue-coverage.mjs +30 -0
  35. package/scripts/issue-hash.mjs +44 -0
  36. package/scripts/issue-sections.mjs +42 -0
  37. package/scripts/label-change.mjs +35 -0
  38. package/scripts/lib/appid.mjs +12 -0
  39. package/scripts/lib/archive-check.mjs +29 -0
  40. package/scripts/lib/archive-state.mjs +15 -0
  41. package/scripts/lib/branch-work.mjs +13 -0
  42. package/scripts/lib/branch.mjs +43 -0
  43. package/scripts/lib/can-edit-issue.mjs +34 -0
  44. package/scripts/lib/checklist.mjs +68 -0
  45. package/scripts/lib/cli.mjs +82 -0
  46. package/scripts/lib/commit-change.mjs +57 -0
  47. package/scripts/lib/config.mjs +296 -0
  48. package/scripts/lib/design-fetch.mjs +156 -0
  49. package/scripts/lib/device.mjs +67 -0
  50. package/scripts/lib/doctor.mjs +614 -0
  51. package/scripts/lib/execution-mode.mjs +24 -0
  52. package/scripts/lib/fix-guard.mjs +23 -0
  53. package/scripts/lib/fix-stash.mjs +17 -0
  54. package/scripts/lib/fix.mjs +31 -0
  55. package/scripts/lib/github.mjs +161 -0
  56. package/scripts/lib/go-local.mjs +102 -0
  57. package/scripts/lib/init.mjs +324 -0
  58. package/scripts/lib/intent-to-add.mjs +32 -0
  59. package/scripts/lib/issue-check.mjs +63 -0
  60. package/scripts/lib/issue-coverage.mjs +47 -0
  61. package/scripts/lib/issue-hash.mjs +25 -0
  62. package/scripts/lib/issue-parse.mjs +194 -0
  63. package/scripts/lib/issue-sections.mjs +43 -0
  64. package/scripts/lib/labels.mjs +65 -0
  65. package/scripts/lib/language.mjs +9 -0
  66. package/scripts/lib/logaudit.mjs +123 -0
  67. package/scripts/lib/messages.mjs +328 -0
  68. package/scripts/lib/next-step.mjs +144 -0
  69. package/scripts/lib/openspec-commands.mjs +44 -0
  70. package/scripts/lib/openspec-status.mjs +16 -0
  71. package/scripts/lib/plan.mjs +256 -0
  72. package/scripts/lib/platform-of.mjs +32 -0
  73. package/scripts/lib/platform-scope.mjs +32 -0
  74. package/scripts/lib/platforms.mjs +90 -0
  75. package/scripts/lib/preflight.mjs +71 -0
  76. package/scripts/lib/protected-paths.mjs +102 -0
  77. package/scripts/lib/requeue.mjs +23 -0
  78. package/scripts/lib/review-adapters.mjs +37 -0
  79. package/scripts/lib/review-brief.mjs +43 -0
  80. package/scripts/lib/review-events.mjs +56 -0
  81. package/scripts/lib/review-state.mjs +157 -0
  82. package/scripts/lib/reviewers.mjs +39 -0
  83. package/scripts/lib/role-skills.mjs +112 -0
  84. package/scripts/lib/run-flags.mjs +16 -0
  85. package/scripts/lib/run-usage.mjs +65 -0
  86. package/scripts/lib/scan.mjs +73 -0
  87. package/scripts/lib/ship.mjs +161 -0
  88. package/scripts/lib/sla.mjs +90 -0
  89. package/scripts/lib/stack-profile.mjs +169 -0
  90. package/scripts/lib/staging.mjs +21 -0
  91. package/scripts/lib/status-data.mjs +109 -0
  92. package/scripts/lib/status.mjs +199 -0
  93. package/scripts/lib/tasks-file.mjs +81 -0
  94. package/scripts/lib/web-review.mjs +98 -0
  95. package/scripts/lib/yaml-lite.mjs +157 -0
  96. package/scripts/needs-reviewer.mjs +41 -0
  97. package/scripts/next-step.mjs +39 -0
  98. package/scripts/pick-reviewer.mjs +42 -0
  99. package/scripts/platform-of.mjs +49 -0
  100. package/scripts/preflight.mjs +32 -0
  101. package/scripts/render-message.mjs +35 -0
  102. package/scripts/requeue.mjs +53 -0
  103. package/scripts/review-adapter.mjs +32 -0
  104. package/scripts/review-brief.mjs +29 -0
  105. package/scripts/review-event.mjs +70 -0
  106. package/scripts/review-sla.mjs +41 -0
  107. package/scripts/review-state.mjs +171 -0
  108. package/scripts/review-who.mjs +21 -0
  109. package/scripts/role-skills.mjs +53 -0
  110. package/scripts/run-usage.mjs +22 -0
  111. package/scripts/scan-diff.mjs +16 -0
  112. package/scripts/ship-check.mjs +54 -0
  113. package/scripts/spec-ready.mjs +40 -0
  114. package/scripts/stack-profile.mjs +67 -0
  115. package/scripts/stage.mjs +14 -0
  116. package/scripts/status.mjs +47 -0
  117. package/scripts/usage-limit.mjs +17 -0
  118. package/scripts/validate-config.mjs +44 -0
  119. package/scripts/web-review.mjs +134 -0
  120. package/skills/doctor/SKILL.md +28 -0
  121. package/skills/fix/SKILL.md +128 -0
  122. package/skills/go/SKILL.md +242 -0
  123. package/skills/init/SKILL.md +72 -0
  124. package/skills/issue/SKILL.md +128 -0
  125. package/skills/issue/references/update.md +15 -0
  126. package/skills/review/SKILL.md +157 -0
  127. package/skills/ship/SKILL.md +128 -0
  128. package/skills/status/SKILL.md +27 -0
  129. package/skills/think/SKILL.md +76 -0
  130. package/stacks/flutter.md +63 -0
  131. package/stacks/laravel.md +65 -0
  132. package/stacks/vue.md +70 -0
  133. package/templates/issue.md +99 -0
  134. package/templates/relevo.yml +59 -0
  135. package/templates/workflows/relevo-digest.yml +54 -0
  136. package/templates/workflows/relevo-go.yml +263 -0
  137. package/templates/workflows/relevo-queue.yml +72 -0
  138. package/templates/workflows/relevo-review.yml +60 -0
  139. package/templates/workflows/relevo-sla.yml +53 -0
@@ -0,0 +1,67 @@
1
+ // Android device detection and screenshot capture. The adb client is injected so this can be tested
2
+ // without a device. Screenshots are only written to disk, never opened or sent anywhere.
3
+
4
+ import { mkdirSync, writeFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { execFileSync } from 'node:child_process';
7
+
8
+ /** Parse the output of `adb devices` into [{ serial, state }]. */
9
+ export function parseDevices(output) {
10
+ return String(output)
11
+ .split('\n')
12
+ .slice(1)
13
+ .map((l) => l.trim())
14
+ .filter((l) => l && !l.startsWith('*'))
15
+ .map((l) => {
16
+ const [serial, state] = l.split(/\s+/);
17
+ return { serial, state };
18
+ });
19
+ }
20
+
21
+ /** Pick the device to use: the only ready one, or the one named in `preferred`. Throws a message a person can act on. */
22
+ export function pickDevice(devices, preferred = null) {
23
+ const ready = devices.filter((d) => d.state === 'device');
24
+ if (preferred) {
25
+ if (ready.some((d) => d.serial === preferred)) return preferred;
26
+ throw new Error(`device ${preferred} is not connected and ready`);
27
+ }
28
+ if (ready.length === 1) return ready[0].serial;
29
+ if (ready.length === 0) {
30
+ const stuck = devices.find((d) => d.state === 'unauthorized');
31
+ throw new Error(
32
+ stuck
33
+ ? 'the device is connected but unauthorised: unlock it and accept the USB debugging prompt'
34
+ : 'no device is connected: connect an Android device with USB debugging enabled (run `adb devices` to check)',
35
+ );
36
+ }
37
+ throw new Error(`several devices are connected (${ready.map((d) => d.serial).join(', ')}): set ANDROID_SERIAL to the one to use`);
38
+ }
39
+
40
+ const NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,60}$/;
41
+
42
+ /** Capture names come from a person: only plain file names are accepted, never paths. */
43
+ export function safeCaptureName(name) {
44
+ const n = String(name ?? '').replace(/\.png$/i, '');
45
+ if (!NAME_RE.test(n) || n.includes('..')) {
46
+ throw new Error('capture names may use letters, digits, "_", "-" and "." only (for example 02_after_tap)');
47
+ }
48
+ return n;
49
+ }
50
+
51
+ export const realAdb = (args, options = {}) => execFileSync('adb', args, { maxBuffer: 64 * 1024 * 1024, ...options });
52
+
53
+ /** List devices through the injected client. */
54
+ export function listDevices(adb = realAdb) {
55
+ return parseDevices(adb(['devices'], { encoding: 'utf8' }));
56
+ }
57
+
58
+ /** Take a screenshot and save it as <dir>/<name>.png. Returns the path. */
59
+ export function capture({ adb = realAdb, name, dir = 'evidence', serial, write = writeFileSync, mkdir = mkdirSync }) {
60
+ const safe = safeCaptureName(name);
61
+ const png = adb(['-s', serial, 'exec-out', 'screencap', '-p']);
62
+ if (!png || png.length < 8) throw new Error('the device returned no image; is the screen on and the device unlocked?');
63
+ mkdir(dir, { recursive: true });
64
+ const path = join(dir, `${safe}.png`);
65
+ write(path, png);
66
+ return path;
67
+ }