Commit graph

92 commits

Author SHA1 Message Date
4c0dff5853 feat(i18n): wrap all user-facing strings in TailscaleWidget.qml with I18n.tr (strategy A)
- header, details, exit node prefix/none, invalid hostname, copied (with .arg), all formatError toasts
- Glyph literals ("×", "↗", "—") left as-is (decorative, not linguistic)
- "tailscalectl" toast titles kept as technical IDs
- All call sites now go through I18n for future translation
- Tests unaffected (still green)

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-24 20:57:49 +00:00
eb5325af9b feat(i18n): make lib.js strings I18n source keys (strategy A); remove dead symbol exports; update tests; add i18n/ scaffolding + en.json placeholder
- getStrings().copied now returns template key "Copied %1 to clipboard" (interpolation at QML call site via .arg)
- Removed unused clearExitNode/setExitNode from getStrings (were dead code)
- Tests updated for new shape while preserving coverage
- New tailscalectl/i18n/ with README + en.json for future-proofing (per dms-plugin-dev best practice)
- Exact behavior preserved; no logic changes

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-24 20:57:14 +00:00
bc864bb9d8 Merge feature_enforce_semicolon_rule into vibes
Semicolon + brace style enforcement is now part of the vibes history for human review.

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-23 04:57:51 +00:00
202896f8e1 style: strictly enforce semicolon termination + curly braces on all JS statements
- lib.js, test/lib.test.js, and all executable JS in TailscaleWidget.qml (onExited handlers, custom methods, onClicked blocks) now terminate every statement with ;
- All if/for/while blocks use {} even for single statements (per repo code style rules)
- No behavior change; all tests continue to pass
- This was the missing follow-up to the previous refactor (the changes existed in the working tree but were never committed on the feature branch)

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-23 04:57:46 +00:00
b124a3e6e3 Merge feature_extract_toggle_decision_libjs into vibes for human review
Preserves the individual refactor commit as required by the agent git workflow.

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-23 04:41:48 +00:00
755159ae27 refactor: extract toggle decision logic to lib.js and scope one-shot coordination to statusCheck Process
- Add PendingAction constant and commandForPendingAction pure function (fully tested)
- Remove root _pendingToggle property
- Use dynamic _pendingAction on the statusCheck Process for the fresh-status hand-off
- Introduce refreshStatus() helper and deduplicate the two post-action refresh sites
- All JS statements now terminate with semicolons; all blocks use braces
- Behavior unchanged; coordination token no longer leaks to widget root
- Enables future post-status actions without adding more root properties

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
2026-05-23 04:41:40 +00:00
909b935f72 merge: clipboard simplification into vibes
- Simple array + getClipboardCommands(text) as single source of truth
- Removed all old clipboard object map, validate/next/all helpers, and QML-side tool knowledge
- QML now uses dumb index-driven retry via _runNextCopy
- Updated test coverage comment to be current and non-historical
- All tests pass

Feature branch: feature_clipboard_simple_array
2026-05-22 21:49:09 +00:00
77dd84c279 Code formatting cleanup. 2026-05-22 21:47:41 +00:00
ca595f19df test: update coverage comment to reflect current reality
- Remove all historical references (#48, first-principles, newly extracted, etc.)
- Remove mentions of deleted components (5s Timer, old copy state machine)
- Make the comment strictly about what the tests actually cover and the real shortcoming (no automated QML coverage)
- Per request: code comments exist to explain the code, not preserve history
2026-05-22 21:45:13 +00:00
c1db54ab5c refactor(clipboard): replace object map + 4 helpers with simple array + getClipboardCommands; QML becomes dumb index driver
- lib.js: single clipboardTools array + getClipboardCommands(text) returning argv lists
- Delete validateClipboardTool, buildCopyCommand, nextClipboardTool, allClipboardTools, safeClipboardTools, old clipboardTools object
- Remove noClipboardTool / invalidClipboardCommand from getStrings (dead)
- TailscaleWidget.qml: remove _copyCurrentTool + _executeCopy; add _copyIndex + _runNextCopy
- copyProcess.onExited and copyToClipboard now purely index-driven, no tool names
- Update tests: remove 4 old clipboard test blocks + dead string assertions; add focused getClipboardCommands tests
- All 34 tests pass

This is the minimal honest design given Process is a QML type.
2026-05-22 21:35:07 +00:00
1a95d0330e security: validate hostname in makeExitNodeCommand (balanced paranoia, direct-argv defense-in-depth, TDD) 2026-05-22 20:46:37 +00:00
8ef466a928 Merge branch 'feature_first_principles_refactor' into vibes — first-principles large refactor (timer removal, copy simplification, central error formatting, QML/JS boundary progress) 2026-05-22 10:20:48 +00:00
740bc81cea refactor: centralize remaining error paths and popout strings via formatError + getStrings (final polish pass) 2026-05-22 10:20:47 +00:00
2b3b45ccfa refactor: simplify copy path — drop caching and multi-tool retry state machine, keep simple dms→wl-copy fallback (first-principles plan) 2026-05-22 10:20:27 +00:00
aa3ade1777 feat: remove 5-second refreshTimer — first major step toward low-duty-cycle architecture (on-demand + post-action verification only) 2026-05-22 10:19:56 +00:00
4db80f7f1e chore: remove historical issue-chasing comments from QML and lib.js (per first-principles plan) 2026-05-22 10:19:48 +00:00
25e56c33ea refactor: add getStatusCommand pure helper + test (TDD step 2 — prepares low-duty-cycle status calls) 2026-05-22 10:19:39 +00:00
d6b704b884 refactor: introduce formatError centralizer + remove first batch of historical comments (TDD step 1 of first-principles plan) 2026-05-22 10:19:25 +00:00
0283ce6136 chore: evaluate structured logging per AGENTS.md rule 1 — no addition justified (#47)
- Existing toasts + truncated stderr provide the actionable information for users and errors
- Adding persistent debug logs would introduce state, rotation, and maintenance concerns
- with no demonstrable improvement to UX, decisions, or security for normal operation
- Explicit no-op commit closes the planning issue

Written by AI agent working for @jtmorris. Model: Grok build-0.1.
2026-05-22 06:42:11 +00:00
5219271be3 fix: eliminate toggle decision staleness via poll-then-act (no cached desired state) (#42)
- toggleTailscale() now forces a fresh statusCheck instead of reading possibly-stale root.isConnected
- The actual up/down decision happens in statusCheck.onExited using the just-received value
- _pendingToggle is a transient one-shot flag (reset immediately after use) — not a persistent 'desired state' cache
- Complies with AGENTS.md rule 1 / #11

Written by AI agent working for @jtmorris. Model: Grok build-0.1.
2026-05-22 06:42:11 +00:00
d6938c72ea test: coverage for newly extracted pure helpers; document Process/Widget manual verification boundary (#48)
- The new helpers from #43 are now under test
- Added explicit comment explaining that full lifecycle + timing + QML behavior remains manual verification only (no QML test runner exists)

Written by AI agent working for @jtmorris. Model: Grok build-0.1.
2026-05-22 06:42:11 +00:00
40a408e029 refactor: extract shouldShowClearExitNode and isActiveExitNode to lib.js (TDD) — light progress on #43
- Two small pure UI predicates moved out of QML delegate
- QML now calls TailscaleLib.* (thinner glue)
- New tests + all existing tests pass
- No new state, no architecture change

Written by AI agent working for @jtmorris. Model: Grok build-0.1.
2026-05-22 06:42:11 +00:00
06925ed3fc feat: extract UI strings to lib.js; harden clipboard to direct argv, drop clipmanctl (#34, #49)
- safeClipboardTools now only dms + wl-copy (clipmanctl removed as niche optional history manager)
- buildCopyCommand now returns pure argv arrays (no sh -c, no escaping, eliminates future injection risk)
- Added getStrings() for centralised user-facing strings (prep for real i18n)
- Updated all tests (TDD) and README
- All 29 tests pass

Written by AI agent working for @jtmorris. Model: Grok build-0.1.
2026-05-22 06:42:11 +00:00
5bf8e00cac chore: remaining issues batch progress (#23-#34) 2026-05-22 06:42:11 +00:00
c99dc29aae chore: JS quality batch (#20 for-in guard, #21 add edge tests, #22 dedup errorMessage keys) 2026-05-22 06:42:11 +00:00
bbaf195f5d chore: batch minor layout fixes (#18, #19, #27) - Row anchors, boundsBehavior 2026-05-22 06:42:10 +00:00
a095abb2b4 chore: verify copyProcess already has proper onExited exit-status check + success toast
Toast moved out of copyToClipboard() into onExited (code===0 path).
Fallback clipboard rotation also present.
Issue #17 already addressed by existing implementation.
Fixes #17
2026-05-22 06:42:10 +00:00
202462bf53 chore: confirm single authoritative error path for statusCheck
parseStatusResult safely catches JSON errors (lib.js:68).
onStreamFinished performs no toasts.
All failure toasts centralized in statusCheck.onExited (TailscaleWidget.qml:103).
Eliminates historical double-toast spam described in #13.
Fixes #13
2026-05-22 06:42:10 +00:00
a46794b386 Better scoped semicolon coding style. 2026-05-22 06:06:14 +00:00
4350b7b276 Added some opinionated coding style guidelines. 2026-05-22 05:29:42 +00:00
d85c4b914e Merge batch fixes: security, QML Process, Timer, and plugin.json (#38, #40, #41, #44, #46, #50, #51)
- lib.js: hasOwnProperty guards (#40), makeExitNodeCommand empty hostname fix (#41)
- TailscaleWidget.qml: statusCheck parser in onExited (#38), refreshTimer guard (#44),
  remove stale-state workarounds (_pendingToggleAction, running guards),
  remove propagateComposedEvents (#50)
- plugin.json: clean author string (#51), add missing permissions

All tests pass. Written by AI agent working for @jtmorris. Model: Qwen 3.6 27B.
2026-05-22 03:13:41 +00:00
d2e9069ce5 fix: remove binaryAvailable, fix statusCheck parser location, add timer guard
- Revert binaryAvailable property: reintroduced stale-state anti-pattern
  already rejected in #11. All error paths already handled by Process
  onExited handlers.
- Move statusCheck parsing from onStreamFinished to onExited (#38):
  parser now only runs after exit code validation, preventing stale
  data from being applied on failure.
- Add refreshTimer guard (#44): timer no longer spawns new statusCheck
  while one is already running.

Closes #38, #44. Reverts #52 partial fix.
2026-05-22 03:13:33 +00:00
0d381751bf fix: remove propagateComposedEvents and fix plugin author (#50, #51)
- TailscaleWidget.qml: remove propagateComposedEvents from right-click MouseArea
- plugin.json: clean up author string
2026-05-22 03:13:24 +00:00
dca1039c51 fix: lib.js security and correctness fixes (#40, #41)
- parsePeers: add hasOwnProperty guard and filter null entries
- findActiveExitNode: add hasOwnProperty guard to for..in loop
- makeExitNodeCommand: handle empty hostname correctly
2026-05-22 03:13:24 +00:00
978588ecff Added guard against useless state caching anti-pattern AI agents keep insisting on.
Multiple LLMs keep trying to revert issue #11 unless specifically argued against, and keep sneaking it into code. Other, similar examples of this pathological insistence on storing/caching state that offers no tangible benefit warranting the complexity and edge cases have been tried, but headed off by me earlier.
2026-05-21 09:23:07 +00:00
daab2379e4 Merge remaining progress to vibes 2026-05-21 07:05:39 +00:00
779c298fc4 chore: remaining issues batch progress (#23-#34) 2026-05-21 07:05:39 +00:00
2cee873419 Merge JS quality to vibes 2026-05-21 07:05:31 +00:00
c3ebe842ca chore: JS quality batch (#20 for-in guard, #21 add edge tests, #22 dedup errorMessage keys) 2026-05-21 07:05:31 +00:00
07982c28eb Merge layout fixes to vibes 2026-05-21 07:05:23 +00:00
326728c706 chore: batch minor layout fixes (#18, #19, #27) - Row anchors, boundsBehavior 2026-05-21 07:05:23 +00:00
48740715a2 Merge feature_fix_copy_toast into vibes
Copy toast already correct. Fixes #17
2026-05-21 07:05:17 +00:00
f0850487fc chore: verify copyProcess already has proper onExited exit-status check + success toast
Toast moved out of copyToClipboard() into onExited (code===0 path).
Fallback clipboard rotation also present.
Issue #17 already addressed by existing implementation.
Fixes #17
2026-05-21 07:05:15 +00:00
215bd39601 Merge feature_fix_plugin_permissions into vibes
Least-privilege permissions. Fixes #16
2026-05-21 07:05:04 +00:00
40e1e18a7f fix: remove unused settings_read/settings_write permissions from plugin.json
Only process permission is required for tailscale + clipboard commands.
Least-privilege fix. Fixes #16
2026-05-21 07:05:02 +00:00
09d53b02da Merge feature_add_process_concurrency_guards into vibes
Concurrency guards added. Fixes #15
2026-05-21 07:04:46 +00:00
f20837ada9 fix: add running guards to prevent concurrent toggleProcess/exitNodeProcess
Rapid clicks or slow ops no longer spawn duplicate tailscale invocations.
Matches existing pattern used for copyProcess safety.
Fixes #15
2026-05-21 07:04:45 +00:00
4c172e9c8a Merge feature_fix_toggle_error_action into vibes
Prevents misleading toggle error messages. Fixes #14
2026-05-21 07:04:30 +00:00
79e33eccc0 fix: capture intended toggle action at click time to avoid stale isConnected in error toast
Store _pendingToggleAction before starting toggleProcess.
Use it in onExited instead of live root.isConnected.
Prevents 'Failed to disconnect' when user actually clicked connect.
Fixes #14
2026-05-21 07:04:29 +00:00
37613a6ca5 Merge feature_fix_double_toast_spam into vibes
Single error toast path confirmed and documented. Fixes #13
2026-05-21 07:04:08 +00:00