autark-cli 0.5.4 → 0.5.6

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 (2) hide show
  1. package/autark.mjs +18 -17
  2. package/package.json +1 -1
package/autark.mjs CHANGED
@@ -517,7 +517,9 @@ async function refreshRuntimeFiles() {
517
517
  }
518
518
 
519
519
  async function refreshSkills() {
520
- const res = await spawnSync('pnpm', ['dlx', '--silent', 'skills', 'add', 'kiluazen/kstack', '-s', SKILL_NAMES.join(','), '-y', '-g'])
520
+ // skills CLI switched from `-s name,name` to positional `name name`.
521
+ // The old comma-separated form silently matches nothing.
522
+ const res = await spawnSync('pnpm', ['dlx', '--silent', 'skills', 'add', 'kiluazen/kstack', ...SKILL_NAMES, '-y', '-g'])
521
523
  if (res.status !== 0) throw new Error(`kstack skills install failed`)
522
524
  }
523
525
 
@@ -862,7 +864,6 @@ async function mailLint(rest) {
862
864
  'compound-question': 'Compound a/b questions ("are you X or Y...") read as AI hedging across alternatives. Humans ask one specific thing. Drop the "or" and pick the more specific half.',
863
865
  'too-long': 'Cold outreach over 400 chars (~4-6 short lines) reads as a pitch deck, not a peer note. If you wrote more, you\'re explaining instead of asking. Cut to the single sharpest sentence.',
864
866
  'no-anchor-sig': 'Without a clickable name in the signature, the recipient has to type your name into Google to figure out who you are. The HTML <a href> / markdown [name](url) sig is the single biggest "who is this person?" mitigator. Plain "Kushal" alone is a tell.',
865
- 'html-in-text': 'Layout HTML tags (<div>, <p>, <br>, <span>) in the body get sent through `autark mail send --text` as text/plain — the recipient sees the literal markup in their Gmail / Outlook (we have screenshots of this happening). For paragraph breaks use a blank line. For the signature link, the single <a href="...">name</a> is allowed (recipients see "name" rendered if the inbox does any html-detection, or the raw href if not — both fine).',
866
867
  }
867
868
 
868
869
  const violations = []
@@ -890,14 +891,6 @@ async function mailLint(rest) {
890
891
  const hasMdAnchor = /\[[^\]]+\]\(https?:\/\/[^)]+\)/.test(body)
891
892
  const hasHtmlAnchor = /<a\b[^>]*href\s*=\s*["']https?:\/\/[^"']+["'][^>]*>[^<]+<\/a>/i.test(body)
892
893
  if (!hasMdAnchor && !hasHtmlAnchor) violations.push({ rule: 'no-anchor-sig', detail: 'no clickable name in signature', why: WHY['no-anchor-sig'] })
893
- // Layout HTML tags in the body. Catches the autark-2026-05-28 footgun where
894
- // an agent wrote <div>...</div><br> markup, passed it to `mail send --text`,
895
- // and 6 recipients saw raw markup in their Gmail. The <a href> signature
896
- // tag is whitelisted because no-anchor-sig depends on it.
897
- const layoutTagMatch = body.match(/<\s*\/?\s*(div|p|br|span|hr|table|tr|td|th|font|b|i|u|strong|em)\b[^>]*>/gi) || []
898
- for (const tag of layoutTagMatch) {
899
- violations.push({ rule: 'html-in-text', detail: tag, why: WHY['html-in-text'] })
900
- }
901
894
 
902
895
  if (violations.length === 0) {
903
896
  console.log(JSON.stringify({ clean: true, length: len }, null, 2))
@@ -1438,10 +1431,10 @@ function mailUsage() {
1438
1431
  console.log(`autark mail
1439
1432
 
1440
1433
  setup --prefix <name> [--force]
1441
- send --to <email[,email]> --subject <s> --text @body.txt [--run-id <id>] [--dry-run]
1442
- reply --message-id <id> --text @reply.txt [--run-id <id>]
1443
- reply-all --message-id <id> --text @reply.txt [--run-id <id>]
1444
- forward --message-id <id> --to <email> [--text @body.txt] [--run-id <id>]
1434
+ send --to <email[,email]> --subject <s> [--text @body.txt] [--html @body.html] [--cc <e>] [--bcc <e>] [--reply-to <e>] [--label <l>] [--attachment <a>] [--run-id <id>] [--dry-run]
1435
+ reply --message-id <id> [--text @reply.txt] [--html @reply.html] [--run-id <id>]
1436
+ reply-all --message-id <id> [--text @reply.txt] [--html @reply.html] [--run-id <id>]
1437
+ forward --message-id <id> --to <email> [--text @body.txt] [--html @body.html] [--run-id <id>]
1445
1438
  threads [--limit N]
1446
1439
  thread <thread_id>
1447
1440
  messages [--limit N]
@@ -1449,11 +1442,19 @@ function mailUsage() {
1449
1442
  raw <message_id>
1450
1443
  attachment --message-id <id> --attachment-id <id> [--out file]
1451
1444
  request <METHOD> <path> [--body @json] [--raw]
1452
- lint --body @draft.txt | <stdin> grade a draft for AI-tells; exit 1 on violations
1445
+ lint --body @draft.txt | <stdin> content-quality check (AI-tells, slop); exit 1 on violations
1446
+
1447
+ Body flags — matches AgentMail CLI + REST and the wider convention
1448
+ (Mailgun / SendGrid / Resend / Postmark all use the same text vs html split):
1449
+
1450
+ --text @file Plain text body, ships as text/plain MIME part.
1451
+ --html @file HTML body, ships as text/html MIME part.
1452
+ Both Ships as multipart/alternative (text fallback + html).
1453
1453
 
1454
1454
  Mail uses the inbox-scoped token in ~/.autark/credentials.json. --dry-run
1455
- prints the payload without hitting SES. lint is fully local runs the
1456
- outreach skill's hard-fail checks against a draft.`)
1455
+ prints the payload without hitting SES. lint is fully local and only
1456
+ inspects content quality (slop / AI-tells) markup correctness is a
1457
+ CLI/convention concern, not a slop concern.`)
1457
1458
  }
1458
1459
 
1459
1460
  function usage() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autark-cli",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "CLI for autark \u2014 hypothesis-driven product runbooks. Track products, hypotheses, runs, and actions from the terminal.",
5
5
  "type": "module",
6
6
  "license": "MIT",