opencode-discipline 0.1.0 → 0.1.1

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/dist/index.js +83 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12703,8 +12703,62 @@ function buildCompactionContext(state) {
12703
12703
  ].join(`
12704
12704
  `);
12705
12705
  }
12706
+ function buildTodoSeedContent(planName) {
12707
+ return `Plan kickoff: ${planName}`;
12708
+ }
12709
+ function buildTodoSeedInstruction(planName, retry) {
12710
+ const content = buildTodoSeedContent(planName);
12711
+ const title = retry ? "## Discipline Plugin \u2014 Todo Seed Retry" : "## Discipline Plugin \u2014 Todo Seed";
12712
+ const intro = retry ? "The plan kickoff todo is still missing in the right panel." : "Before continuing, create the kickoff todo so progress is visible in the right panel.";
12713
+ return [
12714
+ title,
12715
+ intro,
12716
+ "Call `todowrite` now with this item:",
12717
+ `- content: \`${content}\``,
12718
+ "- status: `in_progress`",
12719
+ "- priority: `high`"
12720
+ ].join(`
12721
+ `);
12722
+ }
12723
+ function extractTodos(response) {
12724
+ if (Array.isArray(response)) {
12725
+ return response.filter((item) => {
12726
+ return typeof item === "object" && item !== null && typeof item.content === "string" && typeof item.status === "string" && typeof item.priority === "string";
12727
+ });
12728
+ }
12729
+ if (response && typeof response === "object") {
12730
+ const data = response.data;
12731
+ if (Array.isArray(data)) {
12732
+ return extractTodos(data);
12733
+ }
12734
+ }
12735
+ return [];
12736
+ }
12737
+ function hasPlanKickoffTodo(todos, planName) {
12738
+ const planNameLower = planName.toLowerCase();
12739
+ return todos.some((todo) => {
12740
+ const content = todo.content.toLowerCase();
12741
+ return content.includes(planNameLower) && content.includes("plan");
12742
+ });
12743
+ }
12744
+ async function readSessionTodos(client, directory, sessionID) {
12745
+ const sessionApi = client.session;
12746
+ if (!sessionApi || typeof sessionApi.todo !== "function") {
12747
+ return;
12748
+ }
12749
+ try {
12750
+ const response = await sessionApi.todo({
12751
+ query: { directory },
12752
+ path: { id: sessionID }
12753
+ });
12754
+ return extractTodos(response);
12755
+ } catch {
12756
+ return;
12757
+ }
12758
+ }
12706
12759
  var DisciplinePlugin = async ({ worktree, directory, client }) => {
12707
12760
  const manager = new WaveStateManager(worktree);
12761
+ const todoNudges = new Map;
12708
12762
  return {
12709
12763
  "experimental.session.compacting": async (input, output) => {
12710
12764
  const state = manager.getState(input.sessionID);
@@ -12725,6 +12779,28 @@ var DisciplinePlugin = async ({ worktree, directory, client }) => {
12725
12779
  if (currentAgent === "plan" && state.wave < 3) {
12726
12780
  output.system.push(buildPlanReadOnlyReminder());
12727
12781
  }
12782
+ if (sessionID && currentAgent === "plan" && !state.accepted) {
12783
+ const nudgeState = todoNudges.get(sessionID) ?? {
12784
+ prompted: false,
12785
+ retried: false,
12786
+ seeded: false
12787
+ };
12788
+ const todos = await readSessionTodos(client, directory, sessionID);
12789
+ const hasSeededTodo = todos !== undefined && hasPlanKickoffTodo(todos, state.planName);
12790
+ if (hasSeededTodo) {
12791
+ nudgeState.seeded = true;
12792
+ }
12793
+ if (!nudgeState.seeded) {
12794
+ if (!nudgeState.prompted) {
12795
+ output.system.push(buildTodoSeedInstruction(state.planName, false));
12796
+ nudgeState.prompted = true;
12797
+ } else if (todos !== undefined && !hasSeededTodo && !nudgeState.retried) {
12798
+ output.system.push(buildTodoSeedInstruction(state.planName, true));
12799
+ nudgeState.retried = true;
12800
+ }
12801
+ }
12802
+ todoNudges.set(sessionID, nudgeState);
12803
+ }
12728
12804
  },
12729
12805
  "tool.execute.before": async (input, output) => {
12730
12806
  const filePath = output.args?.filePath;
@@ -12756,6 +12832,13 @@ var DisciplinePlugin = async ({ worktree, directory, client }) => {
12756
12832
  try {
12757
12833
  const current = manager.getState(args.sessionID);
12758
12834
  const state = current ? manager.advanceWave(args.sessionID) : manager.startPlan(args.sessionID);
12835
+ if (!current) {
12836
+ todoNudges.set(args.sessionID, {
12837
+ prompted: false,
12838
+ retried: false,
12839
+ seeded: false
12840
+ });
12841
+ }
12759
12842
  const waveName = WAVE_NAMES[state.wave];
12760
12843
  const nextStep = WAVE_NEXT_STEPS[state.wave];
12761
12844
  return `Wave ${state.wave} (${waveName}) started for plan '${state.planName}'. You may now proceed with ${nextStep}.`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-discipline",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",