autark-cli 0.5.6 → 0.5.7

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 +46 -5
  2. package/package.json +1 -1
package/autark.mjs CHANGED
@@ -776,15 +776,31 @@ async function hypothesisPause(rest, status) {
776
776
  async function feedbackRecord(rest) {
777
777
  const opts = parseArgs(rest)
778
778
  const ref = opts.hypothesis || opts._[0]
779
+ const text = readValue(required(opts.text || opts.message || opts.body, '--text "<feedback>"'))
780
+
781
+ // --product-id (or a bare product slug with no /Hxx) → product-level feedback.
782
+ const productId = opts['product-id'] || opts.product_id
783
+ const isProductSlug = ref && !opts['hypothesis-id'] && !opts.hypothesis_id && !/\/H\d{2}$/.test(ref)
784
+ if (productId || isProductSlug) {
785
+ let pid = productId
786
+ if (!pid) {
787
+ const ctx = await api('GET', `/v1/context/${encodeURIComponent(ref)}`)
788
+ pid = ctx.product?.id
789
+ }
790
+ if (!pid) throw new Error('product not found')
791
+ const result = await api('POST', `/v1/products/${encodeURIComponent(pid)}/feedback`, { text })
792
+ console.log(result.id)
793
+ return
794
+ }
795
+
779
796
  let hypId = opts['hypothesis-id'] || opts.hypothesis_id
780
797
  if (!hypId) {
781
- if (!ref) throw new Error('pass product/Hxx or --hypothesis-id')
798
+ if (!ref) throw new Error('pass product, product/Hxx, --product-id, or --hypothesis-id')
782
799
  const [productSlug, code] = splitHypothesisRef(ref)
783
800
  const ctx = await api('GET', `/v1/context/${encodeURIComponent(productSlug)}/${encodeURIComponent(code)}`)
784
801
  hypId = ctx.hypothesis?.id
785
802
  }
786
803
  if (!hypId) throw new Error('hypothesis not found')
787
- const text = readValue(required(opts.text || opts.message || opts.body, '--text "<feedback>"'))
788
804
  const body = { text }
789
805
  if (opts['action-id'] || opts.action_id) body.action_id = opts['action-id'] || opts.action_id
790
806
  const result = await api('POST', `/v1/hypotheses/${encodeURIComponent(hypId)}/feedback`, body)
@@ -799,7 +815,8 @@ async function feedbackDelete(rest) {
799
815
  }
800
816
 
801
817
  function feedbackUsage() {
802
- console.log(`autark feedback record <product/Hxx> --text "<nudge>" [--action-id <id>]
818
+ console.log(`autark feedback record <product/Hxx> --text "<nudge>" [--action-id <id>] per-hypothesis nudge
819
+ autark feedback record <product> --text "<nudge>" product-level note (any hypothesis)
803
820
  autark feedback delete <feedback-id>`)
804
821
  }
805
822
 
@@ -886,7 +903,16 @@ async function mailLint(rest) {
886
903
  const compoundQ = /\b(are|is|do|does|did|will|would|can|could|should|have|has)\b[^?]{0,200}\bor\b[^?]{0,200}\?/i
887
904
  if (compoundQ.test(body)) violations.push({ rule: 'compound-question', detail: 'a/b question with "or"', why: WHY['compound-question'] })
888
905
  const sigSplit = body.split(/\n\s*\n(?:best|thanks|cheers|—|-)[\s,]*\n/i)[0] || body
889
- const len = sigSplit.trim().length
906
+ // Measure VISIBLE prose length, not raw markup. An <a href>/[text](url) signature
907
+ // anchor or any HTML wrapper must not eat into the 400-char content budget — only
908
+ // what the recipient actually reads counts.
909
+ const visibleText = sigSplit
910
+ .replace(/<a\b[^>]*>(.*?)<\/a>/gis, '$1') // <a ...>Kushal</a> -> Kushal
911
+ .replace(/\[([^\]]+)\]\(\s*https?:\/\/[^)]+\)/g, '$1') // [Kushal](url) -> Kushal
912
+ .replace(/<[^>]+>/g, '') // drop remaining html tags
913
+ .replace(/\s+/g, ' ') // collapse whitespace
914
+ .trim()
915
+ const len = visibleText.length
890
916
  if (len > 400) violations.push({ rule: 'too-long', detail: `${len} chars`, why: WHY['too-long'] })
891
917
  const hasMdAnchor = /\[[^\]]+\]\(https?:\/\/[^)]+\)/.test(body)
892
918
  const hasHtmlAnchor = /<a\b[^>]*href\s*=\s*["']https?:\/\/[^"']+["'][^>]*>[^<]+<\/a>/i.test(body)
@@ -1188,6 +1214,14 @@ function printProductContext(r) {
1188
1214
  kv('product.url', r.product.url)
1189
1215
  kv('product.visibility', r.product.visibility)
1190
1216
  kv('product.hypothesis_count', (r.hypotheses || []).length)
1217
+ // Product-level operator feedback (newest first). Append-only + timestamped,
1218
+ // so each entry is a distinct nudge — re-read these every run.
1219
+ kv('product.feedback_count', (r.feedback || []).length)
1220
+ for (const f of (r.feedback || [])) {
1221
+ const shortF = String(f.id || '').slice(0, 8)
1222
+ kv(`product.feedback.${shortF}.created_at`, f.created_at)
1223
+ kv(`product.feedback.${shortF}.text`, f.text)
1224
+ }
1191
1225
  for (const h of (r.hypotheses || [])) {
1192
1226
  kv(`hypothesis.${h.code}.id`, h.id)
1193
1227
  kv(`hypothesis.${h.code}.title`, h.title)
@@ -1209,6 +1243,13 @@ function printProductContext(r) {
1209
1243
  if (r.product.tagline) console.log(`> ${r.product.tagline}\n`)
1210
1244
  console.log(`## Brief\n`)
1211
1245
  console.log(r.product.brief?.trim() || '(no brief set — owner can add one at https://autark.sh)')
1246
+ if ((r.feedback || []).length > 0) {
1247
+ console.log(`\n## Operator feedback (${r.feedback.length}) — product-level, newest first\n`)
1248
+ console.log(`These are general operator nudges, not tied to one hypothesis. Treat the most recent as the freshest signal and let them re-shape your next move.\n`)
1249
+ for (const f of r.feedback) {
1250
+ console.log(`- (${f.created_at}) ${f.text}`)
1251
+ }
1252
+ }
1212
1253
  if (!r.hypotheses?.length) {
1213
1254
  console.log(`\n## Hypotheses\n\n(none yet — create one with: autark hypothesis create --product-id <product_id> --md @hyp.md)`)
1214
1255
  } else {
@@ -1471,7 +1512,7 @@ function usage() {
1471
1512
  run start|finish start / finish a run
1472
1513
  log action record one outreach touch
1473
1514
  action escalate flag an action for human attention
1474
- feedback record|delete leave a free-text nudge on a hypothesis
1515
+ feedback record|delete leave a free-text nudge on a hypothesis or product
1475
1516
  context [<slug>|...] pull product or hypothesis context
1476
1517
 
1477
1518
  mail setup|send|reply|... send/read mail via your AgentMail inbox
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autark-cli",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
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",