@@ -2514,8 +2581,6 @@ export function SkillDetailPage({
versions,
versionsLoading,
attachAgents,
- attachPopoverOpen,
- setAttachPopoverOpen,
onSubmitAttach,
attachPending,
expandedDirs,
@@ -2553,8 +2618,6 @@ export function SkillDetailPage({
versions: CompanySkillVersion[];
versionsLoading: boolean;
attachAgents: AttachAgentOption[];
- attachPopoverOpen: boolean;
- setAttachPopoverOpen: (open: boolean) => void;
onSubmitAttach: (ids: string[], versionId: string | null) => void;
attachPending: boolean;
expandedDirs: Set;
@@ -2575,10 +2638,25 @@ export function SkillDetailPage({
deletePending: boolean;
}) {
const [diffOpen, setDiffOpen] = useState(false);
+ const [settingsOpen, setSettingsOpen] = useState(false);
const sortedVersions = [...versions].sort((a, b) => b.revisionNumber - a.revisionNumber);
const [leftVersionId, setLeftVersionId] = useState(null);
const [rightVersionId, setRightVersionId] = useState(null);
+ // Track unsaved edits so we can float a save bar and warn before the page is
+ // unloaded with a dirty draft (PAP-10907 J).
+ const savedFileContent = file?.content ?? "";
+ const isDirty = editMode && Boolean(file?.editable) && draft !== savedFileContent;
+ useEffect(() => {
+ if (!isDirty) return;
+ const handler = (event: BeforeUnloadEvent) => {
+ event.preventDefault();
+ event.returnValue = "";
+ };
+ window.addEventListener("beforeunload", handler);
+ return () => window.removeEventListener("beforeunload", handler);
+ }, [isDirty]);
+
if (!detail) {
return loading ? : ;
}
@@ -2598,7 +2676,7 @@ export function SkillDetailPage({
function renderFilesBody() {
return (
-
+
{/* GitHub-style social proof, top-right: installs · stars · fork.
- Installs is a read-only stat; stars and fork are interactive. */}
+ "Installs" counts agents that currently have this skill attached
+ (PAP-10907); stars and fork are interactive. */}
- {detail.installCount}
- {detail.installCount === 1 ? "install" : "installs"}
+ {detail.attachedAgentCount}
+ {detail.attachedAgentCount === 1 ? "install" : "installs"}
- Times this skill has been installed or forked.
+ Agents in this company that currently have this skill installed.{detail.forkCount}
@@ -2987,8 +3050,6 @@ export function SkillDetailPage({
{/* Big primary action opens the agent multi-selector (PAP-10907). */}
agent.id)}
versions={versions}
@@ -3028,59 +3089,112 @@ export function SkillDetailPage({
- {/* Sharing scope only surfaces when the viewer can edit it (round 2 #3). */}
+ {/* Revision / update controls sit under Agents, above the config gear
+ (PAP-10907 F). Only GitHub-sourced skills can pull updates. */}
+ {detail.sourceType === "github" ? (
+
+