Skip to content

feat(plugins): "Local folder" badge, content fingerprint and folder info card (A2-3, after A2-2) - #538

Closed
nt-nerdtechnic wants to merge 8 commits into
mainfrom
feat/a2-3-local-folder-card
Closed

nt-nerdtechnic wants to merge 8 commits into
mainfrom
feat/a2-3-local-folder-card

Conversation

@nt-nerdtechnic

Copy link
Copy Markdown
Collaborator

⚠️ Merge order: after A2-2

This branch contains A2-2's commit 4c8d7a23d (folder record by 實作-A2a, not yet its own PR when this was pushed). Merge this PR only after the A2-2 PR lands; then this branch merges origin/main normally and its diff shrinks to the A2-3 commit 039e5ba02. Review only 039e5ba02 (+ the merge with main).

Summary

DESIGN-A2 slice A2-3 (gap G2): 「本機資料夾」 wording, content fingerprint and the folder info card.

  • pluginDisclosure.source.developer-unpacked → "Local folder" / 「本機資料夾」 / 「ローカルフォルダー」 (glossary-safe). The same wording in the native backend consent line and the agent approval note (pluginLocalInstall.ts). "Its contents can change at any time" moves to a second line of the disclosure row (.nv-source-folder-note) and to the info card — nothing removed. The six other sources keep their words (snapshot diff touches only developer-unpacked).
  • New pluginFolderFingerprint.ts: SHA-256 over sorted relpath\0size\0sha256(content)\n, .git/ skipped, symlinks recorded by target and not followed, streamed. Taken after each load in activateDeveloperFolder, added to A2-2's lastLoad (with fileCount) only while it is still the last load. Disclosed only: never compared, never blocks, no count/size bound.
  • New DeveloperFolderInfoCard.vue (Host chrome): path + Reveal in folder, last load time + trigger, fingerprint (12 chars + copy in full) + file count, who loaded it (same wording as A2-2), and the two fixed lines (not reviewed/signed/scanned; may change, fingerprint only records). Opened from the badge in the Navide plugin list (ExtensionsPane, refreshes state on open) and in a view's title strip (PluginRegionHost, reads plugins:developerMode on open, card sits in the flow above the guest, never inside it).

Why

Approved DESIGN-A2 §2.2 (R3/R4), Approval (c): no colour distinction.

Test plan (red → green)

New / changed tests: pluginFolderFingerprint.test.ts (3), DeveloperFolderInfoCard.test.ts (3), PluginSourceBadge.test.ts (+1, snapshot updated by hand for developer-unpacked only), PluginRegionHost.test.ts (+1, existing label assertion → "Local folder"), ExtensionsPane.test.ts (+1), pluginIpc.developerMode.test.ts (+2 fingerprint after load / not taken while off), pluginLocalInstall.entryPoints.test.ts (wording).
Not run locally yet: 5-min load 72–87 > 60, handed to CI (coordinator instruction). Red proof and targeted runs + typecheck will follow once load < 60; any difference from CI will be reported.

Regression: existing plugins

Pending local run; CI runs the full suites. With Developer Mode off nothing new runs (no fingerprint, no meta file — test "is not taken while Developer Mode is off").

Protection check

  • git diff $(git merge-base HEAD origin/main) HEAD -- backend/agent_team_backend/credential_*.py quota_*.py usage_*.py → empty; no account switching code touched.
  • No function deleted in A2-3. (The prepareAgentFileInstall handler / loadDeveloperFolders / prepareAgentFile signature changes in the diff are A2-2's, optional parameters.) New files only add.
  • No new limits. gitleaks origin/main..HEAD → no leaks.

🤖 Generated with Claude Code

nt-nerdtechnic and others added 7 commits October 21, 2026 01:32
DESIGN-A2 slice A2-2 (gap G3 and the sidecar record of §2.0). A developer
folder an agent asked for named its caller only in the consent dialog; once
loaded, nothing said whether the user or an agent had it loaded.

- New PluginDeveloperFolderMetaStore keeps, per folder, who had it loaded
  (the user, an agent request the user approved in the main window, or
  unknown for folders consented to before this record), the auto-reload
  choice (on by default, used by A2-4) and the last load (time and trigger).
  It lives in its own file beside the Developer Mode store, whose
  four-field format stays as on main, so older releases read the store as
  before. Disclosure only: a missing or damaged record never blocks a load.
- The main window passes the approval card's caller with
  prepareAgentFileInstall; commitFolderLoad records it.
- plugins:developerMode returns loadedBy, autoReload and lastLoad for each
  folder; the Extensions card shows who loaded a developer folder in the
  wording of agent request cards (en-US, zh-TW, ja-JP).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nt and info card

DESIGN-A2 slice A2-3, in progress.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…older info card

DESIGN-A2 slice A2-3 (gap G2), on top of A2-2's folder record.

- The developer-unpacked source reads "Local folder" (本機資料夾,
  ローカルフォルダー) in the badge, the native backend consent line and the
  agent approval note; "its contents can change at any time" moves to the
  disclosure row's second line and the info card, so no information is lost.
  The six other sources keep their wording.
- After each load the main process takes the folder's content fingerprint
  (SHA-256 over relative path, size and SHA-256 of each file, .git/ left out,
  symbolic links recorded by target and never followed), streamed off the
  load path, and adds it with the file count to the folder's last load while
  it is still the last load. Disclosed only: never compared, never blocks a
  load, no file count or size bound.
- The badge in the Navide plugin list and in a view's title strip opens the
  "Local folder" info card (Host chrome, in the flow above the guest): path
  with Reveal in folder, last load time and trigger, fingerprint (first 12,
  copy in full) and file count, who loaded it, and the two fixed disclosure
  lines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the Extensions card

plugin-agent.caller.pane takes {pane}; a pane without a name reads pane-unknown.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A2-2 (4c8d7a2) passes the requester identity to
prepareAgentFileInstall so a developer folder keeps who loaded it; the
W1 dialog test still asserted the single-argument call and failed on
every platform. Assert both arguments.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nt-nerdtechnic added a commit that referenced this pull request Oct 20, 2026
…ord for word

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nt-nerdtechnic
nt-nerdtechnic marked this pull request as ready for review October 21, 2026 02:53
…r-card

Brings in A2-2 as merged (#536) and A2-5 (#537). Conflicts were resolved
against a base of the earlier A2-2 commit this branch carried (4c8d7a2)
merged with 8f51ac0, so only A2-3's own changes are laid over main:

- pluginDeveloperFolderMeta.ts and its test (add/add): main's version;
  A2-3 never changed them.
- pluginIpc.ts imports: main's import of DeveloperModeIntegrity plus
  A2-3's folderFingerprint import.
- PluginRegionHost.vue: A2-3's Local folder toggle around the badge, with
  main's new local-install prop on both badges.
- plugin-development-v2.md, Local testing row: main's sentence on who
  loaded a folder, then A2-3's sentences on the badge, info card and
  fingerprint.
- pluginIpc.developerMode.test.ts and ExtensionsPane.test.ts: main's
  file with A2-3's own describe block appended unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nt-nerdtechnic added a commit that referenced this pull request Oct 21, 2026
…nfo card (A2-3, after A2-2) (#538)

Squash-merged from origin/pr-538.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nt-nerdtechnic

Copy link
Copy Markdown
Collaborator Author

Squash-merged into main as 93a6b30.

nt-nerdtechnic added a commit that referenced this pull request Oct 21, 2026
…eload

With #538 (A2-3). Hand-resolved, keeping both sides:
- activateDeveloperFolder records the load, starts the folder watch, then
  takes A2-3's fingerprint off the load path (void + catch, disclosure
  only), so an automatic reload's load is fingerprinted like any other.
- ExtensionsPane: the automatic reload row and A2-3's "Local folder" info
  card both stay on a loaded developer folder.
- plugin-development-v2.md local testing row: the automatic reload text
  and A2-3's badge / info card / fingerprint text.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nt-nerdtechnic added a commit that referenced this pull request Oct 21, 2026
…igned

With #543 (A2-4) and #538 (A2-3). Hand-resolved, keeping both sides:
- pluginIpc.developerMode.test.ts: this branch's signed-record tests and
  A2-3's fingerprint tests are both kept.
- plugin-development-v2.md local testing row: main's row (automatic
  reload, A2-3 badge / info card / fingerprint) with its "record is not
  signed" sentence replaced by this branch's signing behaviour.
- A2-3's info card names who loaded a folder through
  developerFolderLoadedByText, which now also takes the record's check, so
  the card says a record may have been changed, the key was replaced, or
  it is not signed, as the plugin list does (test added).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant