From 86c3eea255bc5ec6078e58c7a155f63196216e8d Mon Sep 17 00:00:00 2001 From: chumanic Date: Thu, 12 Nov 2026 16:02:15 +0800 Subject: [PATCH] Guide document checks and local verification workflows --- README.md | 3 +++ browser/index.html | 3 ++- browser/main.ts | 3 +++ browser/style.css | 2 ++ src/workbench/page.ts | 7 +++++-- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2c8e418..2efd782 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ [在线检查 SKILL.md](https://chumaniac.github.io/skillsync/) · [English / CLI reference](README.en.md) · [桌面下载](https://github.com/Chumaniac/skillsync/releases/tag/user-2026.11.11-zh) + +在线页的“第一次检查”从示例文档走到解析结果。本机工作台的页内引导分别定位单份核验、批量计划与历史记录;切换入口不会自动运行检查或批准修复。 + ## 快速开始 CLI 支持 Node.js 20 及以上版本。下面使用 Node.js 24 和 npm,在示例目录做一次只读检查。桌面打包所需的运行时见[构建说明](docs/build.md)。 diff --git a/browser/index.html b/browser/index.html index 796348a..55c1466 100644 --- a/browser/index.html +++ b/browser/index.html @@ -4,7 +4,8 @@ Skill 文档检查 · SkillSync
SkillSync本机目录核验 ↗
-

DOCUMENT INSPECTOR

检查 Skill 文档

粘贴 SKILL.md,读取 YAML 文档头和正文。内容只在当前标签页处理。

本机处理 · 无网络请求
+

DOCUMENT INSPECTOR

检查 Skill 文档

SkillSync 帮助维护者在运行或交付前核对技能包与材料声明。这里先检查一份 SKILL.md 的文档格式,找到缺失字段或出错位置。

本机处理 · 无网络请求
+
第一次检查:从一份文档开始

适合分享 Skill 前、收到技能包后或修改文档时自查。准备文件全文;无需账号或 API Key。

  1. 放入一份文档

    把 SKILL.md 全文粘贴到左侧,保留开头两条 --- 之间的字段。也可先使用内置示例。

  2. 运行格式检查

    点击“检查文档”或按 Ctrl / ⌘ + Enter,查看文档头字段和正文长度。

  3. 按结果继续

    出错时用“定位错误”返回原文。能解析只说明格式可读;目录、权限和交付物请在本机继续核验。

    阅读当前解析结果
最多 24 KiB。网页检查文档格式,本机 CLI 可继续检查来源、权限和交付物。

解析结果

等待检查

运行检查后,这里会列出文档头字段和正文长度。

检查范围

读取 YAML 文档头与正文。来源身份、执行行为及目录权限,请使用本机核验台检查。

diff --git a/browser/main.ts b/browser/main.ts index 4f58160..0c5c283 100644 --- a/browser/main.ts +++ b/browser/main.ts @@ -102,3 +102,6 @@ document.querySelector("#example")!.addEventListener("click", () => { clear(); input.focus(); }); + +document.querySelector('#guide-example')!.addEventListener('click', () => document.querySelector('#example')!.click()); +document.querySelector('#guide-check')!.addEventListener('click', inspect); diff --git a/browser/style.css b/browser/style.css index cc9475e..a08991f 100644 --- a/browser/style.css +++ b/browser/style.css @@ -1,3 +1,5 @@ :root{color-scheme:light;font:14px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",sans-serif;color:#223344;background:#f5f7f9;--line:#dce3e9;--accent:#294e70;--muted:#5b6c7a}*{box-sizing:border-box}body{margin:0}header,main{max-width:1280px;padding:20px clamp(20px,4vw,48px);margin:auto}header{display:flex;gap:12px;align-items:center;min-height:76px;border-bottom:1px solid var(--line)}header strong{font-size:16px;letter-spacing:-.03em}header a{margin-left:auto;color:var(--muted);font-size:12px;text-underline-offset:4px}.workspace-heading{display:flex;justify-content:space-between;align-items:center;gap:24px;margin:28px 0 30px}.eyebrow{font-size:10px;letter-spacing:.15em;color:var(--muted);margin:0 0 12px}h1{font-size:32px;line-height:1.25;letter-spacing:-.04em;font-weight:600;margin:0}.workspace-heading p:not(.eyebrow){color:var(--muted);margin:12px 0 0}.privacy-label{font-size:11px;color:#446659;white-space:nowrap;border:1px solid #cfded5;padding:7px 12px;border-radius:6px;background:#f1f7f3}.columns{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:24px;align-items:start}section{min-width:0;border:1px solid var(--line);background:#fff;border-radius:10px;box-shadow:0 2px 5px #243d5304;overflow:hidden}.panel-heading{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:18px 24px;border-bottom:1px solid var(--line);background:#fcfdfe}.panel-heading label,.panel-heading h2{font-size:14px;font-weight:600;margin:0}#document-meta{font:11px ui-monospace,monospace;color:var(--muted)}textarea{display:block;width:100%;height:380px;min-height:200px;max-height:70vh;padding:24px;resize:vertical;border:0;border-bottom:1px solid var(--line);border-radius:0;background:#fcfdfe;color:#243c52;font:14px/1.8 ui-monospace,SFMono-Regular,monospace;tab-size:2}small{display:block;margin:14px 24px;color:var(--muted);font-size:12px}.actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:0 24px 24px}.actions::after{content:'⌘ / Ctrl + Enter';margin-left:auto;color:var(--muted);font-size:11px}button{font:inherit;min-height:42px;padding:9px 16px;border:1px solid var(--accent);border-radius:6px;background:var(--accent);color:#fff;cursor:pointer;touch-action:manipulation}button.secondary{color:var(--accent);background:#fff;border-color:#b6c4d0}button:hover{background:#203d57;color:#fff}.result-panel{position:sticky;top:24px}.result-panel>strong{display:block;font-size:21px;letter-spacing:-.02em;margin:24px 24px 10px;font-weight:550}.result-panel>p{margin:0 24px 20px;color:var(--muted);overflow-wrap:anywhere}.result-panel>#locate{margin:0 24px 20px}.result-indicator{width:7px;height:7px;border-radius:50%;background:#a3afb8}.result-panel[data-state=error] .result-indicator{background:#a44a35}.result-panel[data-state=error]>strong{color:#92412f}.result-panel[data-state=valid] .result-indicator{background:#507b60}dl{margin:0 24px 24px}dt{color:var(--muted);font:12px ui-monospace,monospace;border-top:1px solid var(--line);padding-top:12px}dd{margin:4px 0 14px;overflow-wrap:anywhere}.scope-note{padding:18px 24px;background:#f7f9fb;border-top:1px solid var(--line);font-size:12px;color:var(--muted)}.scope-note strong{font-weight:550;color:#344c60}.scope-note p{margin:5px 0 0}:focus-visible{outline:2px solid #517b9d;outline-offset:3px}.skip-link{position:fixed;top:8px;left:8px;z-index:10;transform:translateY(-200%);padding:10px;background:var(--accent);color:#fff}.skip-link:focus{transform:none}[hidden]{display:none!important}textarea.diagnostic-measure{position:fixed;inset-inline-start:-9999px;visibility:hidden;min-height:0;height:1px;border:0;overflow:hidden;resize:none} @media(max-width:760px){.workspace-heading{display:block;margin-top:20px}.privacy-label{display:inline-block;margin-top:12px}h1{font-size:27px}.columns{grid-template-columns:1fr;gap:16px}.result-panel{position:static}textarea{font-size:16px;height:300px}.panel-heading{padding:16px 20px}.actions{padding:0 20px 20px}.actions::after{display:none}.result-panel>strong{margin:20px 20px 10px}.result-panel>p{margin-inline:20px}.result-panel>#locate{margin-left:20px}small{margin:14px 20px}button{min-height:44px}header a{font-size:11px}} + +.first-use{border:1px solid var(--line);border-radius:8px;padding:0 20px;margin:0 0 24px;background:#fff}.first-use>summary{padding:14px 0;font-size:13px;font-weight:550;color:#294e70;cursor:pointer}.first-use ol{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px;padding:0 0 0 20px;margin:14px 0 22px}.first-use li{font-size:12px;padding-left:3px;min-width:0}.first-use p{font-size:12px;color:var(--muted);line-height:1.8;margin:7px 0 10px}.first-use .guide-preparation{font-size:12px;margin-top:0}.first-use button{font-size:12px;min-height:38px;padding:7px 10px}.first-use a{display:inline-flex;align-items:center;min-height:38px;color:#294e70;text-underline-offset:3px}@media(max-width:760px){.first-use{padding:0 18px}.first-use ol{grid-template-columns:1fr;gap:14px}.first-use>summary{font-size:12px}.first-use button,.first-use a{min-height:44px}} diff --git a/src/workbench/page.ts b/src/workbench/page.ts index 0e11672..7d70177 100644 --- a/src/workbench/page.ts +++ b/src/workbench/page.ts @@ -1,6 +1,6 @@ /** Static local UI. All evidence is inserted as text or in a scriptless report frame. */ export function workbenchPage(nonce: string): string { - return `SkillSync 核验台
核验台本机工作区

本机核验台

打开 Skill 目录或交付包,查看核验结果、历史记录与修复计划。

+ return `SkillSync 核验台
核验台本机工作区

本机核验台

给使用或维护 Skill 的人:在运行、更新或接收交付文件前,核对材料结构、声明与差异,并留下一份可复查的报告。这里不执行 Skill,也不认证作者。

先查什么?选择一条使用路径
  1. 第一次核对技能包

    准备包含 SKILL.md 的目录。进入单目录核验,可先填入内置示例,点“核验目录”后读清阻断、警告与尚未确认项。

  2. 接收多份交付

    准备交付目录与验收清单。先预检计划,再按声明逐批核验;得到复核包,不会替你提交或修改交付文件。

  3. 回看并处理结果

    历史是只读依据。若要修正 Skill,先生成计划、审阅并明确确认;应用后重新核验,不沿用旧的通过结论。

核验一个目录

只读检查
  1. 01选择范围
  2. 02查看结论
  3. 03保存证据
选择要完成的任务

@@ -41,6 +41,8 @@ main{max-width:1240px}.page-heading{padding-bottom:22px;margin-bottom:24px}.work @media(max-width:720px){.app-sidebar{position:sticky;top:0;z-index:10;padding:12px 18px}.app-brand{padding-bottom:10px}.task-nav{margin-top:0}.sidebar-label{display:none}.task-nav button{font-size:12px}#result-title,#selection,#fix-title{scroll-margin-top:150px}} :root{--muted:#526576} +.workbench-guide{margin-top:18px;padding:0 16px;border:1px solid var(--line);border-radius:7px;background:#fff}.workbench-guide>summary{cursor:pointer;font-size:13px;font-weight:550;padding:12px 0;color:#29445d}.workbench-guide ol{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px;padding:0 0 0 20px;margin:12px 0 18px}.workbench-guide li{min-width:0;font-size:12px}.workbench-guide li p{font-size:12px;line-height:1.8}.workbench-guide button{font-size:12px;margin-top:10px}@media(max-width:900px){.workbench-guide ol{grid-template-columns:1fr;gap:16px}.workbench-guide button{min-height:44px}} + `; export const workbenchScript = `"use strict"; @@ -89,7 +91,7 @@ function mountReport(){ function showReport(html){reportHtml=html.replaceAll('href="#','href="about:srcdoc#');if(!$('result').hidden)mountReport();} function clearReport(){ $('structured-report').textContent='打开一份已保存的核验记录后查看。';$('structured-details').open=false;summaryCanPlan=false;if(!reportHtml)return;reportHtml='';$('report').srcdoc='';} function status(text){ $('status').textContent = text; } -function renderLocks(){const value=localBusy||checkingOperation||Boolean(observedOperation)||Boolean(ownedOperationId),applying=localApplying; busy=value; ['verify','plan','result-recheck','result-details','mode-skill','mode-artifacts','reverify','choose','choose-contract','root','contract','kind','delivery','history-refresh','batch-plan','batch-preview','batch-recover','batch-output','batch-previous','batch-retry','batch-package','batch-digest','batch-open','choose-batch-plan','choose-batch-package'].forEach(id => $(id).disabled=value); $('batch-run').disabled=value||!batchReady; document.querySelectorAll('.history-open').forEach(button=>button.disabled=value||historyLoading); ['history-query','history-kind','history-exit','history-filter','history-clear','history-refresh'].forEach(id=>$(id).disabled=value||historyLoading); $('history-prev').disabled=value||historyLoading||historyOffset===0; $('history-next').disabled=value||historyLoading||historyOffset+12>=historyTotal; $('export-summary').disabled=value||!historyId;$('export-json').disabled=value||!historyId;$('load-example').disabled=value; $('cancel').disabled=checkingOperation||!(observedOperation?.cancellable||ownedOperationId&&['verify','plan','batch/run'].includes(ownedOperationKind)&&!applying); $('confirm').disabled=value||!planId; $('apply').disabled=value || !$('confirm').checked || !planId; $('plan').disabled=value||!selected||!summaryCanPlan; syncHistoryCompareControls(); document.querySelectorAll('.history-compare-pick').forEach(button=>button.disabled=value||historyLoading); } +function renderLocks(){const value=localBusy||checkingOperation||Boolean(observedOperation)||Boolean(ownedOperationId),applying=localApplying; busy=value; ['guide-single','guide-batch','guide-history','verify','plan','result-recheck','result-details','mode-skill','mode-artifacts','reverify','choose','choose-contract','root','contract','kind','delivery','history-refresh','batch-plan','batch-preview','batch-recover','batch-output','batch-previous','batch-retry','batch-package','batch-digest','batch-open','choose-batch-plan','choose-batch-package'].forEach(id => $(id).disabled=value); $('batch-run').disabled=value||!batchReady; document.querySelectorAll('.history-open').forEach(button=>button.disabled=value||historyLoading); ['history-query','history-kind','history-exit','history-filter','history-clear','history-refresh'].forEach(id=>$(id).disabled=value||historyLoading); $('history-prev').disabled=value||historyLoading||historyOffset===0; $('history-next').disabled=value||historyLoading||historyOffset+12>=historyTotal; $('export-summary').disabled=value||!historyId;$('export-json').disabled=value||!historyId;$('load-example').disabled=value; $('cancel').disabled=checkingOperation||!(observedOperation?.cancellable||ownedOperationId&&['verify','plan','batch/run'].includes(ownedOperationKind)&&!applying); $('confirm').disabled=value||!planId; $('apply').disabled=value || !$('confirm').checked || !planId; $('plan').disabled=value||!selected||!summaryCanPlan; syncHistoryCompareControls(); document.querySelectorAll('.history-compare-pick').forEach(button=>button.disabled=value||historyLoading); } function lock(value,applying=false){localBusy=value;localApplying=value&&applying;renderLocks();} function clearPlan(){$('fix-title').textContent='审阅修复计划';planId=null;$('confirm').checked=false;setFix(false);$('changes').textContent='';$('apply').disabled=true;} function invalidate(){ $('structured-report').textContent='尚未核验';$('export-json').disabled=true; $('plan').disabled=true;$('plan').hidden=true;fieldError('root','');fieldError('contract','');selected=null; planId=null; baselineId=null; historyId=null; $('comparison').textContent=''; $('export-summary').disabled=true; hideResult(); setFix(false); $('confirm').checked=false; clearReport(); status('目录或模式已更改,请重新核验'); } @@ -100,6 +102,7 @@ for(const [id,kind] of [['mode-skill','skill'],['mode-artifacts','artifacts']])$ function fieldError(id,message){$(id+'-error').textContent=message;$(id).setAttribute('aria-invalid',String(Boolean(message)));if(message)$(id).focus();} function validateInputs(){fieldError('root','');fieldError('contract','');if(!$('root').value.trim()){fieldError('root',$('kind').value==='artifacts'?'请选择或填写交付目录。':'请选择或填写 Skill 目录。');return false;}if($('kind').value==='artifacts'&&!$('contract').value.trim()){fieldError('contract','交付验收需要一份 YAML 或 JSON 清单,请选择清单文件。');return false;}return true;} function showTaskSummary(value){$('summary-context').textContent=$('root').value;$('task-summary').setAttribute('data-attention',String(Boolean(value?.counts?.some(c=>['阻断问题','建议核对','尚未确认'].includes(c.label)&&c.count>0)))); $('task-summary').hidden=false;summaryCanPlan=Boolean(value?.canPlan)&&!value?.readOnly;$('summary-title').textContent=value?.title||'核验结果';$('summary-next').textContent=value?.description||'查看完整报告后,再决定下一步。';$('summary-counts').replaceChildren();for(const item of (value?.counts||[])){const li=document.createElement('li'),label=document.createElement('span'),count=document.createElement('strong');label.textContent=item.label+':';count.textContent=String(item.count);li.append(label,count);$('summary-counts').append(li);}$('plan').hidden=!summaryCanPlan;$('plan').disabled=busy||!selected||!summaryCanPlan;} +for(const [id,task,heading] of [['guide-single','single','root'],['guide-batch','batch','batch-plan'],['guide-history','history','history-query']])$(id).onclick=()=>{if(busy)return;setTask(task);$(heading).focus();$(heading).scrollIntoView?.({block:'center',behavior:'auto'});}; $('result-details').onclick=()=>{$('report').scrollIntoView?.({block:'start',behavior:'auto'});$('report').focus();}; $('result-recheck').onclick=()=>{if(busy)return;setTask('single');return verify(false);}; syncMode();