@hasna/loops 0.3.8 → 0.3.9

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.
package/dist/cli/index.js CHANGED
@@ -2953,7 +2953,8 @@ function planPrompt(spec) {
2953
2953
  const budget = spec.tokenBudget ? `Token budget: ${spec.tokenBudget}.` : "No explicit token budget.";
2954
2954
  return [
2955
2955
  "Create a flat DAG goal plan for this objective.",
2956
- "Each node must have a stable short key, a concrete objective, optional dependsOn keys, and optional priority.",
2956
+ "Each node must have a stable short key, a concrete objective, dependsOn keys, priority, and tokenBudget.",
2957
+ "Use dependsOn: [] when there are no dependencies, priority: 0 when no priority is needed, and tokenBudget: null when no per-node budget is needed.",
2957
2958
  "Prefer the smallest plan that can prove the explicit requirements.",
2958
2959
  budget,
2959
2960
  `Objective: ${spec.objective}`
@@ -2965,6 +2966,9 @@ function achievementPrompt(goal, nodes, evidence) {
2965
2966
  "Run an adversarial achievement audit.",
2966
2967
  "Completion is unproven until every explicit requirement is verified against evidence.",
2967
2968
  "Return achieved=false if evidence is missing, ambiguous, or only asserts completion.",
2969
+ "Return achieved=true when the evidence proves every explicit requirement; do not return achieved=false with an empty unmetRequirements array.",
2970
+ "Return status as complete, active, blocked, budgetLimited, cancelled, or null when no status change is appropriate.",
2971
+ "Return evidence and unmetRequirements as arrays, using [] when empty.",
2968
2972
  "adversarialReview must be non-empty and must describe the attempted falsification.",
2969
2973
  `Goal: ${goal.objective}`,
2970
2974
  `Nodes: ${nodes.map((node) => `${node.key}=${node.status}`).join(", ")}`,
@@ -2981,18 +2985,18 @@ var DEFAULT_MAX_TURNS = 10;
2981
2985
  var PlanNodeSchema = z.object({
2982
2986
  key: z.string().min(1).max(64).regex(/^[A-Za-z0-9_.-]+$/),
2983
2987
  objective: z.string().min(1),
2984
- dependsOn: z.array(z.string().min(1)).optional().default([]),
2985
- priority: z.number().int().optional().default(0),
2986
- tokenBudget: z.number().int().positive().optional()
2988
+ dependsOn: z.array(z.string().min(1)),
2989
+ priority: z.number().int(),
2990
+ tokenBudget: z.number().int().positive().nullable()
2987
2991
  });
2988
2992
  var PlanSchema = z.object({
2989
2993
  nodes: z.array(PlanNodeSchema).min(1)
2990
2994
  });
2991
2995
  var AchievementSchema = z.object({
2992
2996
  achieved: z.boolean(),
2993
- status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).optional(),
2994
- evidence: z.array(z.string()).optional().default([]),
2995
- unmetRequirements: z.array(z.string()).optional().default([]),
2997
+ status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).nullable(),
2998
+ evidence: z.array(z.string()),
2999
+ unmetRequirements: z.array(z.string()),
2996
3000
  adversarialReview: z.string().min(1)
2997
3001
  });
2998
3002
  function normalizeGoalSpec2(spec) {
@@ -3076,7 +3080,7 @@ async function planGoal(store, goal, spec, model, opts) {
3076
3080
  objective: node.objective,
3077
3081
  dependsOn: node.dependsOn ?? [],
3078
3082
  priority: node.priority ?? 0,
3079
- tokenBudget: node.tokenBudget,
3083
+ tokenBudget: node.tokenBudget ?? undefined,
3080
3084
  sequence: index
3081
3085
  }));
3082
3086
  assertAcyclicNodes(rawNodes.map((node) => ({ key: node.key, dependsOn: node.dependsOn })));
@@ -4216,7 +4220,7 @@ function runDoctor(store) {
4216
4220
  // package.json
4217
4221
  var package_default = {
4218
4222
  name: "@hasna/loops",
4219
- version: "0.3.8",
4223
+ version: "0.3.9",
4220
4224
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
4221
4225
  type: "module",
4222
4226
  main: "dist/index.js",
@@ -2848,7 +2848,8 @@ function planPrompt(spec) {
2848
2848
  const budget = spec.tokenBudget ? `Token budget: ${spec.tokenBudget}.` : "No explicit token budget.";
2849
2849
  return [
2850
2850
  "Create a flat DAG goal plan for this objective.",
2851
- "Each node must have a stable short key, a concrete objective, optional dependsOn keys, and optional priority.",
2851
+ "Each node must have a stable short key, a concrete objective, dependsOn keys, priority, and tokenBudget.",
2852
+ "Use dependsOn: [] when there are no dependencies, priority: 0 when no priority is needed, and tokenBudget: null when no per-node budget is needed.",
2852
2853
  "Prefer the smallest plan that can prove the explicit requirements.",
2853
2854
  budget,
2854
2855
  `Objective: ${spec.objective}`
@@ -2860,6 +2861,9 @@ function achievementPrompt(goal, nodes, evidence) {
2860
2861
  "Run an adversarial achievement audit.",
2861
2862
  "Completion is unproven until every explicit requirement is verified against evidence.",
2862
2863
  "Return achieved=false if evidence is missing, ambiguous, or only asserts completion.",
2864
+ "Return achieved=true when the evidence proves every explicit requirement; do not return achieved=false with an empty unmetRequirements array.",
2865
+ "Return status as complete, active, blocked, budgetLimited, cancelled, or null when no status change is appropriate.",
2866
+ "Return evidence and unmetRequirements as arrays, using [] when empty.",
2863
2867
  "adversarialReview must be non-empty and must describe the attempted falsification.",
2864
2868
  `Goal: ${goal.objective}`,
2865
2869
  `Nodes: ${nodes.map((node) => `${node.key}=${node.status}`).join(", ")}`,
@@ -2876,18 +2880,18 @@ var DEFAULT_MAX_TURNS = 10;
2876
2880
  var PlanNodeSchema = z.object({
2877
2881
  key: z.string().min(1).max(64).regex(/^[A-Za-z0-9_.-]+$/),
2878
2882
  objective: z.string().min(1),
2879
- dependsOn: z.array(z.string().min(1)).optional().default([]),
2880
- priority: z.number().int().optional().default(0),
2881
- tokenBudget: z.number().int().positive().optional()
2883
+ dependsOn: z.array(z.string().min(1)),
2884
+ priority: z.number().int(),
2885
+ tokenBudget: z.number().int().positive().nullable()
2882
2886
  });
2883
2887
  var PlanSchema = z.object({
2884
2888
  nodes: z.array(PlanNodeSchema).min(1)
2885
2889
  });
2886
2890
  var AchievementSchema = z.object({
2887
2891
  achieved: z.boolean(),
2888
- status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).optional(),
2889
- evidence: z.array(z.string()).optional().default([]),
2890
- unmetRequirements: z.array(z.string()).optional().default([]),
2892
+ status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).nullable(),
2893
+ evidence: z.array(z.string()),
2894
+ unmetRequirements: z.array(z.string()),
2891
2895
  adversarialReview: z.string().min(1)
2892
2896
  });
2893
2897
  function normalizeGoalSpec2(spec) {
@@ -2971,7 +2975,7 @@ async function planGoal(store, goal, spec, model, opts) {
2971
2975
  objective: node.objective,
2972
2976
  dependsOn: node.dependsOn ?? [],
2973
2977
  priority: node.priority ?? 0,
2974
- tokenBudget: node.tokenBudget,
2978
+ tokenBudget: node.tokenBudget ?? undefined,
2975
2979
  sequence: index
2976
2980
  }));
2977
2981
  assertAcyclicNodes(rawNodes.map((node) => ({ key: node.key, dependsOn: node.dependsOn })));
@@ -4016,7 +4020,7 @@ function enableStartup(result) {
4016
4020
  // package.json
4017
4021
  var package_default = {
4018
4022
  name: "@hasna/loops",
4019
- version: "0.3.8",
4023
+ version: "0.3.9",
4020
4024
  description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
4021
4025
  type: "module",
4022
4026
  main: "dist/index.js",
package/dist/index.js CHANGED
@@ -2838,7 +2838,8 @@ function planPrompt(spec) {
2838
2838
  const budget = spec.tokenBudget ? `Token budget: ${spec.tokenBudget}.` : "No explicit token budget.";
2839
2839
  return [
2840
2840
  "Create a flat DAG goal plan for this objective.",
2841
- "Each node must have a stable short key, a concrete objective, optional dependsOn keys, and optional priority.",
2841
+ "Each node must have a stable short key, a concrete objective, dependsOn keys, priority, and tokenBudget.",
2842
+ "Use dependsOn: [] when there are no dependencies, priority: 0 when no priority is needed, and tokenBudget: null when no per-node budget is needed.",
2842
2843
  "Prefer the smallest plan that can prove the explicit requirements.",
2843
2844
  budget,
2844
2845
  `Objective: ${spec.objective}`
@@ -2850,6 +2851,9 @@ function achievementPrompt(goal, nodes, evidence) {
2850
2851
  "Run an adversarial achievement audit.",
2851
2852
  "Completion is unproven until every explicit requirement is verified against evidence.",
2852
2853
  "Return achieved=false if evidence is missing, ambiguous, or only asserts completion.",
2854
+ "Return achieved=true when the evidence proves every explicit requirement; do not return achieved=false with an empty unmetRequirements array.",
2855
+ "Return status as complete, active, blocked, budgetLimited, cancelled, or null when no status change is appropriate.",
2856
+ "Return evidence and unmetRequirements as arrays, using [] when empty.",
2853
2857
  "adversarialReview must be non-empty and must describe the attempted falsification.",
2854
2858
  `Goal: ${goal.objective}`,
2855
2859
  `Nodes: ${nodes.map((node) => `${node.key}=${node.status}`).join(", ")}`,
@@ -2866,18 +2870,18 @@ var DEFAULT_MAX_TURNS = 10;
2866
2870
  var PlanNodeSchema = z.object({
2867
2871
  key: z.string().min(1).max(64).regex(/^[A-Za-z0-9_.-]+$/),
2868
2872
  objective: z.string().min(1),
2869
- dependsOn: z.array(z.string().min(1)).optional().default([]),
2870
- priority: z.number().int().optional().default(0),
2871
- tokenBudget: z.number().int().positive().optional()
2873
+ dependsOn: z.array(z.string().min(1)),
2874
+ priority: z.number().int(),
2875
+ tokenBudget: z.number().int().positive().nullable()
2872
2876
  });
2873
2877
  var PlanSchema = z.object({
2874
2878
  nodes: z.array(PlanNodeSchema).min(1)
2875
2879
  });
2876
2880
  var AchievementSchema = z.object({
2877
2881
  achieved: z.boolean(),
2878
- status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).optional(),
2879
- evidence: z.array(z.string()).optional().default([]),
2880
- unmetRequirements: z.array(z.string()).optional().default([]),
2882
+ status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).nullable(),
2883
+ evidence: z.array(z.string()),
2884
+ unmetRequirements: z.array(z.string()),
2881
2885
  adversarialReview: z.string().min(1)
2882
2886
  });
2883
2887
  function normalizeGoalSpec2(spec) {
@@ -2961,7 +2965,7 @@ async function planGoal(store, goal, spec, model, opts) {
2961
2965
  objective: node.objective,
2962
2966
  dependsOn: node.dependsOn ?? [],
2963
2967
  priority: node.priority ?? 0,
2964
- tokenBudget: node.tokenBudget,
2968
+ tokenBudget: node.tokenBudget ?? undefined,
2965
2969
  sequence: index
2966
2970
  }));
2967
2971
  assertAcyclicNodes(rawNodes.map((node) => ({ key: node.key, dependsOn: node.dependsOn })));
package/dist/sdk/index.js CHANGED
@@ -2838,7 +2838,8 @@ function planPrompt(spec) {
2838
2838
  const budget = spec.tokenBudget ? `Token budget: ${spec.tokenBudget}.` : "No explicit token budget.";
2839
2839
  return [
2840
2840
  "Create a flat DAG goal plan for this objective.",
2841
- "Each node must have a stable short key, a concrete objective, optional dependsOn keys, and optional priority.",
2841
+ "Each node must have a stable short key, a concrete objective, dependsOn keys, priority, and tokenBudget.",
2842
+ "Use dependsOn: [] when there are no dependencies, priority: 0 when no priority is needed, and tokenBudget: null when no per-node budget is needed.",
2842
2843
  "Prefer the smallest plan that can prove the explicit requirements.",
2843
2844
  budget,
2844
2845
  `Objective: ${spec.objective}`
@@ -2850,6 +2851,9 @@ function achievementPrompt(goal, nodes, evidence) {
2850
2851
  "Run an adversarial achievement audit.",
2851
2852
  "Completion is unproven until every explicit requirement is verified against evidence.",
2852
2853
  "Return achieved=false if evidence is missing, ambiguous, or only asserts completion.",
2854
+ "Return achieved=true when the evidence proves every explicit requirement; do not return achieved=false with an empty unmetRequirements array.",
2855
+ "Return status as complete, active, blocked, budgetLimited, cancelled, or null when no status change is appropriate.",
2856
+ "Return evidence and unmetRequirements as arrays, using [] when empty.",
2853
2857
  "adversarialReview must be non-empty and must describe the attempted falsification.",
2854
2858
  `Goal: ${goal.objective}`,
2855
2859
  `Nodes: ${nodes.map((node) => `${node.key}=${node.status}`).join(", ")}`,
@@ -2866,18 +2870,18 @@ var DEFAULT_MAX_TURNS = 10;
2866
2870
  var PlanNodeSchema = z.object({
2867
2871
  key: z.string().min(1).max(64).regex(/^[A-Za-z0-9_.-]+$/),
2868
2872
  objective: z.string().min(1),
2869
- dependsOn: z.array(z.string().min(1)).optional().default([]),
2870
- priority: z.number().int().optional().default(0),
2871
- tokenBudget: z.number().int().positive().optional()
2873
+ dependsOn: z.array(z.string().min(1)),
2874
+ priority: z.number().int(),
2875
+ tokenBudget: z.number().int().positive().nullable()
2872
2876
  });
2873
2877
  var PlanSchema = z.object({
2874
2878
  nodes: z.array(PlanNodeSchema).min(1)
2875
2879
  });
2876
2880
  var AchievementSchema = z.object({
2877
2881
  achieved: z.boolean(),
2878
- status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).optional(),
2879
- evidence: z.array(z.string()).optional().default([]),
2880
- unmetRequirements: z.array(z.string()).optional().default([]),
2882
+ status: z.enum(["active", "blocked", "budgetLimited", "complete", "cancelled"]).nullable(),
2883
+ evidence: z.array(z.string()),
2884
+ unmetRequirements: z.array(z.string()),
2881
2885
  adversarialReview: z.string().min(1)
2882
2886
  });
2883
2887
  function normalizeGoalSpec2(spec) {
@@ -2961,7 +2965,7 @@ async function planGoal(store, goal, spec, model, opts) {
2961
2965
  objective: node.objective,
2962
2966
  dependsOn: node.dependsOn ?? [],
2963
2967
  priority: node.priority ?? 0,
2964
- tokenBudget: node.tokenBudget,
2968
+ tokenBudget: node.tokenBudget ?? undefined,
2965
2969
  sequence: index
2966
2970
  }));
2967
2971
  assertAcyclicNodes(rawNodes.map((node) => ({ key: node.key, dependsOn: node.dependsOn })));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/loops",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",