Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ product overview.

## 0.5.1 — Unreleased

- Manage plugin packages through existing skill sources, review, templates and channel grants.
Compile native Claude hooks as an inline event map so SessionStart hooks execute correctly;
keep executable hooks restricted to authorized live admin turns.

- Fix repeated native file creation and inline editing exhausting Slack’s modal stack. Successful
forms return to the existing browser/preview; Cancel and validation retain their prior behavior.

Expand Down
1 change: 1 addition & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Git and folder skill sources recognize Claude/Codex plugin manifests and store a
as one revision. Existing Review, rollback, templates, organization/channel/personal grants, and
source sync govern the package. Catalog and assignment pickers show Plugin badges and safe
component summaries. Claude loads approved native skills/commands/agents and admin-gated hooks;
compiled inline hooks use Claude's event map so approved hooks execute instead of being ignored.
Codex receives approved skill catalogs. Both receive supported MCP transports through explicit
namespaced grants. Unsupported components/authentication produce actionable failures. Compiled
files stay inside the channel container's artifact mounts; updates rotate warm snapshots and
Expand Down
8 changes: 6 additions & 2 deletions TEST-PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ MCP tools. Verify personal artifact cleanup after the first author's run complet
**PLUG-03 — native components and compatibility (both engines, with different expectations).**
Import and approve `test/fixtures/plugins/native/`. Grant it only to disposable test conversations.
As an admin in a Full-access Claude conversation, start a fresh thread and ask “Use the native
plugin marker command and ask its plugin-inspector agent for its marker.” Require the command
plugin marker command.” In a separate fresh thread ask “Ask the plugin-inspector agent for its
own marker; do not invoke the marker command.” Separate threads keep command instructions from
contaminating the agent probe. Require the command
result `PLUGIN-COMMAND`, observed agent invocation/result `PLUGIN-AGENT`, and exactly one new
`PLUGIN-HOOK` line in that conversation's `plugin-hook-marker.txt` on session start. Repeat as a
`PLUGIN-HOOK` line in that conversation's `plugin-hook-marker.txt` per session start. The compiled
manifest's `hooks` property must contain the event map directly; a nested `hooks.hooks` object
is silently ignored by the CLI and is a failure even if manifest validation passes. Repeat as a
non-admin and as an unattended scheduled/background run: require a hook-policy error and no new
line. Pin Codex and repeat: require an explicit unsupported native component error before the
engine starts. Add an apps or LSP declaration to a disposable source revision and approve it:
Expand Down
2 changes: 1 addition & 1 deletion src/gateway/plugin-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function compilePluginPackage(pkg, { capabilities, allowBypass = false, w
merged[event] = [...(merged[event] || []), ...entries];
}
}
native.hooks = { hooks: merged };
native.hooks = merged;
}
const servers = [];
const seen = new Set();
Expand Down
2 changes: 1 addition & 1 deletion test/plugin-runtime.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ test("hooks require live admin bypass and are declared once without implicit hoo
const compiled = compile({}, files, { allowBypass: true });
assert.equal(compiled.files.some((f) => f.path === "hooks/hooks.json"), false);
const native = JSON.parse(compiled.files.find((f) => f.path === ".claude-plugin/plugin.json").content);
assert.deepEqual(native.hooks, hooks);
assert.deepEqual(native.hooks, hooks.hooks);
assert.throws(() => compile({ hooks: { Stop: "bad" } }, [], { allowBypass: true }), /invalid hook event/);
});

Expand Down
3 changes: 2 additions & 1 deletion test/skills-plugin-import.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ test("failed plugin sync preserves the last approved package", async () => {
assert.equal(failed.ok, false);
const after = getSkill("last-good-package");
assert.equal(after.deleted, false);
assert.equal(after.activeRevisionId, before.activeRevisionId);
assert.ok(before.currentRevisionId);
assert.equal(after.currentRevisionId, before.currentRevisionId);
});

test("manifest edits regenerate catalog metadata and cannot disguise a plugin as a plain skill", async () => {
Expand Down
Loading