@themoltnet/legreffier 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +16 -8
  2. package/dist/index.js +88 -27
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -1,19 +1,27 @@
1
1
  # @themoltnet/legreffier
2
2
 
3
- One-command setup for accountable AI agent commits on
3
+ End-to-end attribution for AI coding agents — so you know who wrote the code,
4
+ why, and whether the context behind it actually worked. Built on
4
5
  [MoltNet](https://themolt.net).
5
6
 
6
- `legreffier init` generates a cryptographic identity, creates a GitHub App,
7
- configures git signing, and wires up your AI coding agent — all in one
8
- interactive flow.
7
+ `legreffier init` gives your agent its own cryptographic identity, a persistent
8
+ diary for decisions and rationale, and SSH-signed commits linked to signed
9
+ reasoning — all wired up in one interactive flow. Memory that's _attributed_,
10
+ rationale that's _signed_, and context that can be _measured_ — across sessions
11
+ and across agents.
9
12
 
10
13
  ## What You Get
11
14
 
12
15
  1. **Own identity** — commits show the agent's name and avatar, not yours
13
- 2. **SSH-signed commits** — every commit is signed with the agent's Ed25519 key
14
- 3. **Signed diary entries** non-trivial commits get a cryptographic rationale
15
- linked via a `MoltNet-Diary:` trailer
16
- 4. **GitHub App authentication** push access via installation tokens, no
16
+ 2. **Persistent diary** — signed, content-addressed entries for decisions,
17
+ rationale, and context that survive across sessions and across agents
18
+ 3. **Rationale linked to code** — non-trivial commits carry a `MoltNet-Diary:`
19
+ trailer pointing at a signed entry explaining _why_
20
+ 4. **SSH-signed commits** — every commit is signed with the agent's Ed25519 key
21
+ 5. **Measured context** — compiled packs can be scored against real coding
22
+ tasks via the MoltNet eval runner, so memory earns its place instead of just
23
+ accumulating
24
+ 6. **GitHub App authentication** — push access via installation tokens, no
17
25
  personal access tokens
18
26
 
19
27
  ## Prerequisites
package/dist/index.js CHANGED
@@ -410,14 +410,14 @@ function CliHero({ animated = false }) {
410
410
  /* @__PURE__ */ jsx(Text, { children: " " }),
411
411
  /* @__PURE__ */ jsxs(Text, { children: [
412
412
  " ",
413
- /* @__PURE__ */ jsx(Text, {
413
+ /* @__PURE__ */ jsxs(Text, {
414
414
  color: cliTheme.color.text,
415
- children: "Accountable AI commits. "
415
+ children: ["Attribution for AI coding agents.", " "]
416
416
  }),
417
417
  /* @__PURE__ */ jsx(Text, {
418
418
  color: cliTheme.color.accent,
419
419
  bold: true,
420
- children: "Cryptographic identity."
420
+ children: "Identity, memory, signed rationale."
421
421
  })
422
422
  ] }),
423
423
  /* @__PURE__ */ jsxs(Text, { children: [
@@ -596,6 +596,32 @@ function CliSummaryBox({ agentName, fingerprint, appSlug, apiUrl, mcpUrl }) {
596
596
  }),
597
597
  " in any repo where the app is installed."
598
598
  ]
599
+ }),
600
+ /* @__PURE__ */ jsx(Text, { children: " " }),
601
+ /* @__PURE__ */ jsxs(Text, {
602
+ color: cliTheme.color.text,
603
+ children: [
604
+ " ",
605
+ /* @__PURE__ */ jsx(Text, {
606
+ color: cliTheme.color.primary,
607
+ children: "Next step:"
608
+ }),
609
+ " run ",
610
+ /* @__PURE__ */ jsx(Text, {
611
+ color: cliTheme.color.accent,
612
+ children: "/legreffier-onboarding"
613
+ }),
614
+ " or ",
615
+ /* @__PURE__ */ jsx(Text, {
616
+ color: cliTheme.color.accent,
617
+ children: "$legreffier-onboarding"
618
+ }),
619
+ " in your next session"
620
+ ]
621
+ }),
622
+ /* @__PURE__ */ jsxs(Text, {
623
+ color: cliTheme.color.muted,
624
+ children: [" ", "to connect your team diary and start capturing knowledge."]
599
625
  })
600
626
  ]
601
627
  })
@@ -7485,6 +7511,10 @@ var SKILLS = [
7485
7511
  {
7486
7512
  name: "legreffier-explore",
7487
7513
  files: ["SKILL.md", "references/exploration-pack-plan.yaml"]
7514
+ },
7515
+ {
7516
+ name: "legreffier-onboarding",
7517
+ files: ["SKILL.md", "references/onboarding-guide.md"]
7488
7518
  }
7489
7519
  ];
7490
7520
  async function downloadSkillFiles(skill) {
@@ -7532,33 +7562,60 @@ async function downloadSkills(repoDir, skillDir) {
7532
7562
  }
7533
7563
  }
7534
7564
  }
7535
- function buildGhTokenRule(agentName) {
7565
+ function buildGhTokenRule() {
7536
7566
  return [
7537
- "# GitHub CLI Authentication (LeGreffier)",
7567
+ "# GitHub CLI Authentication (MoltNet agents)",
7538
7568
  "",
7539
- `When \`GIT_CONFIG_GLOBAL\` is set to \`.moltnet/${agentName}/gitconfig\`,`,
7540
- "authenticate `gh` CLI commands as the GitHub App by prefixing them with:",
7569
+ "> **STRICT RULE read this before every `gh` call.**",
7570
+ ">",
7571
+ "> When `GIT_CONFIG_GLOBAL` is set (matches `.moltnet/<agent>/gitconfig`), you",
7572
+ "> **MUST NOT** run bare `gh <command>`. You **MUST** prefix every `gh` call",
7573
+ "> with a `GH_TOKEN` resolved from an **absolute path** to `moltnet.json`.",
7574
+ "> Running bare `gh` silently falls back to the human personal token and",
7575
+ "> attributes the action to the wrong identity — this is a correctness bug,",
7576
+ "> not a warning.",
7577
+ "",
7578
+ "## The only correct form",
7541
7579
  "",
7542
7580
  "```bash",
7543
- "GH_TOKEN=$(npx @themoltnet/cli github token --credentials \"$(dirname \"$GIT_CONFIG_GLOBAL\")/moltnet.json\") gh <command>",
7581
+ "# 1. Resolve credentials to an ABSOLUTE path (never trust $GIT_CONFIG_GLOBAL as-is).",
7582
+ "CREDS=\"$(cd \"$(dirname \"$GIT_CONFIG_GLOBAL\")\" 2>/dev/null && pwd)/moltnet.json\"",
7583
+ "",
7584
+ "# 2. Refuse to proceed if the file does not exist at that absolute path.",
7585
+ "[ -f \"$CREDS\" ] || { echo \"FATAL: moltnet.json not found at $CREDS\" >&2; exit 1; }",
7586
+ "",
7587
+ "# 3. Call gh with GH_TOKEN inlined.",
7588
+ "GH_TOKEN=$(npx @themoltnet/cli github token --credentials \"$CREDS\") gh <command>",
7544
7589
  "```",
7545
7590
  "",
7546
- "The token is cached locally (~1 hour lifetime, 5-min expiry buffer),",
7591
+ "The credentials file (`moltnet.json`) always lives next to the `gitconfig`",
7592
+ "inside the same `.moltnet/<agent>/` directory, regardless of which agent is",
7593
+ "active. The token is cached locally (~1 hour lifetime, 5-min expiry buffer),",
7547
7594
  "so repeated calls are fast after the first API hit.",
7548
7595
  "",
7549
- "## Worktree warning",
7596
+ "## Why absolute paths are mandatory",
7550
7597
  "",
7551
- `\`GIT_CONFIG_GLOBAL\` may be a **relative path** (e.g. \`.moltnet/${agentName}/gitconfig\`).`,
7552
- "In git worktrees the CWD differs from the main worktree root, so `$(dirname \"$GIT_CONFIG_GLOBAL\")`",
7553
- "resolves incorrectly and `no credentials found` is printed the command then falls back to your",
7554
- "personal `gh` token silently.",
7598
+ "`GIT_CONFIG_GLOBAL` is almost always a **relative path** (e.g. `.moltnet/<agent>/gitconfig`).",
7599
+ "Every git worktree has a different CWD from the main worktree root, so",
7600
+ "`$(dirname \"$GIT_CONFIG_GLOBAL\")` resolves differently depending on where you are.",
7601
+ "When it resolves to a non-existent directory:",
7555
7602
  "",
7556
- "**Always resolve to an absolute path first:**",
7603
+ "- `npx @themoltnet/cli github token` prints `no credentials found` to stderr,",
7604
+ "- the command substitution yields an empty `GH_TOKEN`,",
7605
+ "- `gh` silently falls back to your personal token,",
7606
+ "- the resulting API call is attributed to the **human**, not the agent.",
7557
7607
  "",
7558
- "```bash",
7559
- "CREDS=\"$(cd \"$(dirname \"$GIT_CONFIG_GLOBAL\")\" && pwd)/moltnet.json\"",
7560
- "GH_TOKEN=$(npx @themoltnet/cli github token --credentials \"$CREDS\") gh <command>",
7561
- "```",
7608
+ "This failure is invisible in normal output. The `cd ... && pwd` dance in step 1",
7609
+ "is the only reliable way to get an absolute path that works across worktrees.",
7610
+ "",
7611
+ "## Forbidden patterns",
7612
+ "",
7613
+ "- `gh <command>` — bare, no `GH_TOKEN`. **Never.**",
7614
+ "- `GH_TOKEN=$(... --credentials \"$(dirname \"$GIT_CONFIG_GLOBAL\")/moltnet.json\") gh ...`",
7615
+ " — uses the raw relative path. Breaks in worktrees.",
7616
+ "- `GH_TOKEN=$(... --credentials \"./moltnet.json\") gh ...` — relative. Breaks.",
7617
+ "- `GH_TOKEN=$(... --credentials \"~/.moltnet/...\") gh ...` — `~` is not expanded",
7618
+ " inside double quotes; use `$HOME` or the literal absolute path.",
7562
7619
  "",
7563
7620
  "## Allowed `gh` subcommands",
7564
7621
  "",
@@ -7780,7 +7837,7 @@ var ClaudeAdapter = class {
7780
7837
  async writeRules(opts) {
7781
7838
  const dir = join(opts.repoDir, ".claude", "rules");
7782
7839
  await mkdir(dir, { recursive: true });
7783
- await writeFile(join(dir, "legreffier-gh.md"), buildGhTokenRule(opts.agentName), "utf-8");
7840
+ await writeFile(join(dir, "legreffier-gh.md"), buildGhTokenRule(), "utf-8");
7784
7841
  }
7785
7842
  };
7786
7843
  //#endregion
@@ -8057,17 +8114,21 @@ async function writePem(pem, appSlug, configDir) {
8057
8114
  /**
8058
8115
  * Write a standalone gitconfig file to <configDir>/gitconfig and return
8059
8116
  * its path. The config sets user.name/email and enables SSH commit signing
8060
- * using the agent's SSH key.
8117
+ * using the agent's SSH public key.
8118
+ *
8119
+ * **Important:** `signingkey` must live under `[user]`, not `[gpg "ssh"]`.
8120
+ * Git only reads `user.signingkey`; a key declared as `gpg.ssh.signingkey`
8121
+ * is silently ignored and `git commit -S` fails with
8122
+ * `fatal: either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured`.
8061
8123
  */
8062
- async function writeGitConfig({ configDir, name, email, sshKeyPath }) {
8124
+ async function writeGitConfig({ configDir, name, email, sshPublicKeyPath }) {
8063
8125
  const content = [
8064
8126
  "[user]",
8065
8127
  `\tname = ${name}`,
8066
8128
  `\temail = ${email}`,
8129
+ `\tsigningkey = ${sshPublicKeyPath}`,
8067
8130
  "[gpg]",
8068
8131
  " format = ssh",
8069
- "[gpg \"ssh\"]",
8070
- `\tsigningKey = ${sshKeyPath}`,
8071
8132
  "[commit]",
8072
8133
  " gpgsign = true",
8073
8134
  ""
@@ -8322,7 +8383,7 @@ async function runGitSetupPhase(opts) {
8322
8383
  key: "gitSetup",
8323
8384
  status: "running"
8324
8385
  });
8325
- const { privatePath } = await exportSSHKey({ configDir });
8386
+ const { publicPath } = await exportSSHKey({ configDir });
8326
8387
  const email = buildBotEmail((await lookupBotUser(appSlug, { maxRetries: 5 })).id, appSlug);
8327
8388
  await updateConfigSection("git", {
8328
8389
  name: agentName,
@@ -8332,7 +8393,7 @@ async function runGitSetupPhase(opts) {
8332
8393
  configDir,
8333
8394
  name: agentName,
8334
8395
  email,
8335
- sshKeyPath: privatePath
8396
+ sshPublicKeyPath: publicPath
8336
8397
  })
8337
8398
  }, configDir);
8338
8399
  dispatch({
@@ -9252,7 +9313,7 @@ async function runPortRewritePhase(opts) {
9252
9313
  configDir: targetDir,
9253
9314
  name: config.git.name,
9254
9315
  email: config.git.email,
9255
- sshKeyPath: newSshPriv
9316
+ sshPublicKeyPath: newSshPub
9256
9317
  });
9257
9318
  await writeEnvFile({
9258
9319
  envDir: targetDir,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@themoltnet/legreffier",
3
- "version": "0.29.0",
4
- "description": "LeGreffier — one-command accountable AI agent setup",
3
+ "version": "0.30.0",
4
+ "description": "LeGreffier — attribution and measured memory for AI coding agents.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "repository": {
@@ -34,10 +34,10 @@
34
34
  "vite": "^8.0.0",
35
35
  "vitest": "^3.0.0",
36
36
  "@moltnet/api-client": "0.1.0",
37
- "@themoltnet/design-system": "0.3.2",
38
37
  "@moltnet/crypto-service": "0.1.0",
39
- "@themoltnet/github-agent": "0.23.0",
40
- "@themoltnet/sdk": "0.88.0"
38
+ "@themoltnet/design-system": "0.4.0",
39
+ "@themoltnet/sdk": "0.89.0",
40
+ "@themoltnet/github-agent": "0.23.0"
41
41
  },
42
42
  "scripts": {
43
43
  "dev": "vite build --watch",