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 @@ -5,6 +5,10 @@ versioning theo [SemVer](https://semver.org). **8sync rule:** mỗi PR cập nh

## [Unreleased]

## [0.110.49] — 2026-10-22
### Added
- **Sổ tri thức công ty: `8sync ccc know add --shared "<bài học>"`** (owner 2026-10-22: "cây tri thức liên tục all in 1, hiểu biết rộng, tận dụng kinh nghiệm lẫn nhau, không nhầm lẫn"): một sổ `Công ty` cho bài học đúng với MỌI dự án, mọi phòng đọc đầu tiên ở SessionStart (5 dòng cuối), rồi mới tới sổ dự án mình và 3 dòng cuối của từng dự án khác dưới root của nó; `know ls` in sổ công ty trước, `--json` thêm `shared`; tab Tri thức trên HQ có khối "Công ty" trên cùng. `--shared` và `--repo` không đi cùng. `/remember` ghi rõ khi nào dùng `--shared`. Test know (cả hai bên).

## [0.110.48] — 2026-10-22
### Changed
- **Một công ty, nhiều dự án: `auto up` không mở đội thứ hai nữa** (owner 2026-10-22: "ý tôi là 1 công ty là rooms roles làm nhiều dự án… chứ ui ux vẫn mỗi folder dự án 1 công ty"). Khi `company` đang bật (`auto company on` hoặc `auto up --company`) và đội đã chạy ở repo khác, `auto up` (kể cả nút "Mở team" trên HQ) ở repo này chỉ đưa repo vào scope của auto, ghi `.claude/loop.md`, thêm card đầu nếu có, và báo "đội chung ở <host> nhận card tại đây"; không mở phòng, không ghi team-root (revive không mở phòng ở đó). Đội chung lấy card qua `claim`/`wait` liên dự án (bản .40). Muốn đội riêng cho một repo: `auto company off` rồi `auto up`. `--add` không đổi. Test team +1 (30).
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/cli", "crates/ccc-core"]

[workspace.package]
version = "0.110.48"
version = "0.110.49"
edition = "2021"
license = "PolyForm-Noncommercial-1.0.0"
authors = ["8sync-dev <[email protected]>"]
Expand Down
4 changes: 2 additions & 2 deletions apps/hq-ui/app/api/know/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ export async function GET(req: Request) {
const root = liveProjects(await mergedSessions(o.db), (cwd) => projectOf(cwd)).find((x) => x.root.toLowerCase() === want)?.root;
if (!root) return bad("dự án này không có phòng nào đang chạy", 409);
const r = await run("8sync", ["ccc", "know", "ls", "--json", "--all"], TIMEOUT_MS, root);
if (!r.ok) return json({ own: null, others: [], dir: null, error: (r.stderr.trim() || "8sync ccc know không chạy được (8sync < 0.110.41?)").slice(0, 200) });
if (!r.ok) return json({ shared: null, own: null, others: [], dir: null, error: (r.stderr.trim() || "8sync ccc know không chạy được (8sync < 0.110.41?)").slice(0, 200) });
try {
return json(parseKnow(JSON.parse(r.stdout)));
} catch {
return json({ own: null, others: [], dir: null, error: "8sync ccc know ls trả JSON không hợp lệ" });
return json({ shared: null, own: null, others: [], dir: null, error: "8sync ccc know ls trả JSON không hợp lệ" });
}
}
5 changes: 3 additions & 2 deletions apps/hq-ui/components/hq/know-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function KnowView({ token, roots, repo, active }: { token: string; roots:
</div>
);
}
const n = (data?.own?.lessons.length ?? 0) + (data?.others.reduce((s, b) => s + b.lessons.length, 0) ?? 0);
const n = (data?.shared?.lessons.length ?? 0) + (data?.own?.lessons.length ?? 0) + (data?.others.reduce((s, b) => s + b.lessons.length, 0) ?? 0);
return (
<div className="flex h-full min-h-0 flex-col">
<div className="flex shrink-0 flex-wrap items-center gap-2 border-b px-4 py-2 sm:px-6">
Expand Down Expand Up @@ -78,10 +78,11 @@ export function KnowView({ token, roots, repo, active }: { token: string; roots:
</EmptyState>
) : n === 0 ? (
<EmptyState icon={<BookOpenIcon />} title="Cây tri thức còn trống">
Phòng ghi bài học dùng được ở mọi dự án bằng <code className="font-mono">8sync ccc know add &quot;&lt;bài học&gt;&quot;</code> (hoặc qua <code className="font-mono">/remember</code>). Chuyện riêng của repo vẫn ở su-code/KNOWLEDGE.md.
Phòng ghi bài học của dự án bằng <code className="font-mono">8sync ccc know add &quot;&lt;bài học&gt;&quot;</code>, bài học đúng cho mọi dự án thêm <code className="font-mono">--shared</code> (hoặc qua <code className="font-mono">/remember</code>). Chuyện riêng của repo vẫn ở su-code/KNOWLEDGE.md.
</EmptyState>
) : (
<div className="space-y-6">
{data.shared && data.shared.lessons.length > 0 && <BookBlock book={data.shared} title="Công ty" sub="mọi dự án · 8sync ccc know add --shared" />}
<BookBlock book={data.own} title="Dự án này" empty="Dự án này chưa có bài học chung." />
{data.others.length > 0 && (
<section>
Expand Down
7 changes: 4 additions & 3 deletions apps/hq-ui/lib/know.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

export type Lesson = { day: string | null; room: string | null; text: string };
export type Book = { root: string; lessons: Lesson[] };
export type Know = { own: Book | null; others: Book[]; dir: string | null };
export type Know = { /** The company book (`know add --shared`): lessons for every project. */ shared: Book | null; own: Book | null; others: Book[]; dir: string | null };

/** `- 2026-10-22 [dev] gitleaks full history eats 4 GB` → its parts; a line without the stamp is text only. */
export function lessonParts(line: string): Lesson {
Expand All @@ -22,9 +22,10 @@ function book(v: unknown): Book | null {

/** The CLI's JSON (`{own, others, dir}`); junk degrades to an empty tree, never throws. */
export function parseKnow(v: unknown): Know {
if (!v || typeof v !== "object") return { own: null, others: [], dir: null };
const o = v as { own?: unknown; others?: unknown; dir?: unknown };
if (!v || typeof v !== "object") return { shared: null, own: null, others: [], dir: null };
const o = v as { shared?: unknown; own?: unknown; others?: unknown; dir?: unknown };
return {
shared: book(o.shared),
own: book(o.own),
others: Array.isArray(o.others) ? o.others.map(book).filter((b): b is Book => b != null) : [],
dir: typeof o.dir === "string" ? o.dir : null,
Expand Down
5 changes: 3 additions & 2 deletions apps/hq-ui/tests/know.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe("knowledge tree (8sync ccc know ls --json)", () => {
expect(k.others).toHaveLength(1);
expect(k.others[0].lessons).toHaveLength(1);
expect(k.dir).toBe("/h/know");
expect(parseKnow({ own: null, others: [] })).toEqual({ own: null, others: [], dir: null });
expect(parseKnow("junk")).toEqual({ own: null, others: [], dir: null });
expect(parseKnow({ own: null, others: [] })).toEqual({ shared: null, own: null, others: [], dir: null });
expect(parseKnow("junk")).toEqual({ shared: null, own: null, others: [], dir: null });
expect(parseKnow({ shared: { root: "Công ty", lines: ["- 2026-10-22 [lead] s"] }, own: null, others: [] }).shared?.lessons[0].text).toBe("s");
});
});
2 changes: 1 addition & 1 deletion assets/claude/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "8sync-kit",
"displayName": "8sync kit",
"version": "0.110.48",
"version": "0.110.49",
"description": "8 Sync kit for Claude Code: role-routed subagents (explore, task, quick-task, reviewer, designer, researcher, verifier, pm, architect, qa, critic) and the /ship /rules /sec /harden skills. Hooks, rules and the full skill set come from `8sync ccc kit`.",
"author": { "name": "8 Sync", "url": "https://8syncdev.com" },
"homepage": "https://get.8syncdev.com",
Expand Down
2 changes: 1 addition & 1 deletion assets/claude/skills/remember/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ Ghi: $ARGUMENTS
5. Append đúng một dòng vào cuối `su-code/KNOWLEDGE.md` (repo không có → tạo file với tiêu đề `# KNOWLEDGE`):
`- <type>: <bài học, ≤2 câu, nêu cách áp dụng> — evidence: <lệnh/file:line/URL> (<YYYY-MM-DD>)`
6. Quy trình nhiều bước đã validated và sẽ dùng lại → thêm mục vào `su-code/PLAYBOOKS.md` (When/Steps/Verify/Pitfalls).
7. Bài học dự án khác trên máy này cũng dùng được (công cụ, hook, guard, cách làm chung — không phải chuyện riêng của repo) → thêm `8sync ccc know add "<bài học ngắn>"`: vào cây tri thức chung của máy (mỗi repo một file, SessionStart của mọi dự án đọc được, có ghi root); không ghi secret/dữ liệu khách.
7. Bài học dự án khác trên máy này cũng dùng được (công cụ, hook, guard, cách làm chung — không phải chuyện riêng của repo) → thêm `8sync ccc know add "<bài học ngắn>"` (sổ của repo này, dự án khác đọc được dưới root của nó) hoặc `--shared` khi bài học đúng cho MỌI dự án (sổ công ty, mọi phòng đọc đầu tiên); không ghi secret/dữ liệu khách.
Báo lại đúng dòng đã ghi.
2 changes: 1 addition & 1 deletion crates/cli/src/verbs/ccc/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ TỰ ĐỘNG (gõ trong Claude Code)
8sync ccc auto company on|off [--json] một team làm mọi dự án trong scope (cờ `company` trong auto.json, giữ qua on/off/pause): phòng hết card ở dự án mình thì claim/wait lấy card gấp nhất ở dự án khác; HQ có công tắc \"Công ty\" cạnh \"Critic trả lời ngay\"
8sync ccc auto omp on [--model <provider/model>]|off [--json] đội omp (phòng `8sync . <tên>`) chạy cạnh đội Claude Code: chỉ đổi `teams` (và `omp_model` khi có --model) trong auto.json, giữ mọi thứ khác; `--model <provider>/<model>` = model của đội (phòng mở bằng `8sync . omp-<vai> --model <m>`; giữ khi on/off không có --model; `on --omp`/`up --omp` nhận `--omp-model <m>`); mỗi phòng omp được nhắc đích đầu hàng ≤ 1 lần/10 phút, ≤ 6 lần/giờ; tắt khi model đội (không đặt = model mặc định của omp) là anthropic/… (subscription Claude chỉ dùng trong Claude Code)
8sync ccc auto nudge --session <room id> --cwd <dir> [--model <provider/model>] [--json] (extension omp gọi, --model = model đang chạy của phòng; không có → xét model mặc định của omp) {\"text\"}: lời nhắc đích hiện tại cho phòng omp, null khi auto tắt/tạm dừng, đội omp tắt, phòng chạy anthropic/…, ngoài --here, lease hết, hàng trống hoặc vừa nhắc
8sync ccc know add \"<bài học>\" [--repo <root>] | ls [--all] [--json] cây tri thức chung của máy: mỗi repo một file `~/.local/state/8sync/ccc/know/<repo>.md` (dòng `- <ngày> [<phòng>] <bài học>`); SessionStart nạp bài học của dự án này trước rồi 3 dòng cuối của từng dự án khác dưới tiêu đề root của nó (đọc để học, không lẫn); su-code/KNOWLEDGE.md vẫn là memory commit của repo; CHỈ ghi bài học chung (công cụ, hook, guard, cách làm) — chuyện riêng của khách/dự án, secret, dữ liệu khách KHÔNG vào cây chung (quy tắc tách từng client)
8sync ccc know add \"<bài học>\" [--repo <root> | --shared] | ls [--all] [--json] cây tri thức chung của máy (`--shared` = sổ công ty, đúng cho mọi dự án, mọi phòng đọc đầu tiên): mỗi repo một file `~/.local/state/8sync/ccc/know/<repo>.md` (dòng `- <ngày> [<phòng>] <bài học>`); SessionStart nạp bài học của dự án này trước rồi 3 dòng cuối của từng dự án khác dưới tiêu đề root của nó (đọc để học, không lẫn); su-code/KNOWLEDGE.md vẫn là memory commit của repo; CHỈ ghi bài học chung (công cụ, hook, guard, cách làm) — chuyện riêng của khách/dự án, secret, dữ liệu khách KHÔNG vào cây chung (quy tắc tách từng client)
8sync ccc msg <phòng> \"<tin>\" [--from <phòng>] | msg --all \"<tin>\" nhắn phòng khác của dự án này (cả phòng Claude Code `ccc . <tên>` lẫn phòng omp `. <tên>`; trùng tên → gửi theo id hoặc ccc:<tên> / omp:<tên>): vào inbox phòng đó như dữ liệu từ phòng gửi (không phải lệnh của owner) + hiện trong chat HQ; không có phòng khớp → exit 1
8sync ccc meet [--say \"done|doing|blocked\"] [--room <tên>] [--json] họp sprint daily của các phòng: ghi một dòng vào su-code/standup/<ngày>.md (phòng nói lại trong 30 phút thì thay dòng cũ), đọc dòng của phòng khác; cần su-code/
8sync ccc idle off | status [--json] (bật thêm gate TaskCompleted: task sửa code chưa test thì chưa cho xong)
Expand Down
Loading
Loading