ticlawk 0.1.16-dev.29 → 0.1.16-dev.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ticlawk",
3
- "version": "0.1.16-dev.29",
3
+ "version": "0.1.16-dev.30",
4
4
  "description": "Local connector that links agent harnesses (Claude Code, Codex, OpenClaw, opencode, Pi) to the Ticlawk mobile app.",
5
5
  "type": "module",
6
6
  "main": "ticlawk.mjs",
@@ -11,8 +11,8 @@ Use this in DMs, and in groups where your conversation role is admin or owner.
11
11
 
12
12
  ## Goal Setup When No Specific Goal Exists
13
13
 
14
- - When the current conversation has no goal, briefly decide whether the owner may want an ongoing conversation goal. Use that decision only to choose your next action; do not expose it as recipient-facing content.
15
- - If it looks like a one-off request, answer normally following `COMMUNICATION.md`. If the owner may want an ongoing goal, ask naturally following `COMMUNICATION.md` whether to set one for the current DM, an existing group, or a new group before writing state.
14
+ - When the current conversation has no goal, decide whether the current message is one-off or may be starting, clarifying, or changing an ongoing goal. Use that decision only to choose your next action; do not expose it as recipient-facing content.
15
+ - Treat explicit goal statements, goal discussions, or questions about what the conversation/group should pursue as goal setup candidates. If it looks like a one-off request, answer normally following `COMMUNICATION.md`. Otherwise ask naturally following `COMMUNICATION.md` whether to set one for the current DM, an existing group, or a new group before writing state.
16
16
  - Clarify only the details needed to proceed: goal definition, success/completion criteria, time range, constraints/boundaries, rough approach or roadmap, the agent's deliverables, owner responsibilities, required files/repos/accounts/credentials/budget/resources, dashboard decision view and metrics, and briefing triggers/cadence.
17
17
  - Before setting a charter, summarize the proposed short charter and ask for confirmation. Keep charters to the local goal, roles, success criteria, and boundaries; do not put shared workflow law, dashboard state, task status, or long playbooks in the charter.
18
18
  - After confirmation, write the charter if you have scope authority. Then create and publish the initial dashboard as part of goal setup, push it to the owner for review, and ask whether the layout/style/decision view are satisfactory. Create reminders/resources only when useful, and seed group tasks only in group scope. Then enter the normal goal loop.
@@ -85,18 +85,40 @@ export function buildGroupContextBlock(msg) {
85
85
  export function buildCharterBlock(msg) {
86
86
  const charter = (msg.conversation_charter || '').trim();
87
87
  if (!charter) return '';
88
+ const authorityLine = hasGoalAuthority(msg)
89
+ ? 'Use it as the current goal and role spec. If the owner appears to change the goal, read GOAL_AUTHORITY.md and follow the goal-change flow before updating state.'
90
+ : 'Use it as current group goal and role context. The group admin owns charter and dashboard changes unless they explicitly delegate them.';
88
91
  return promptBlock(`
89
- Goal and role assignments for this conversation:
92
+ [conversation_goal]
93
+ Current charter for this conversation:
90
94
  ${charter}
95
+
96
+ ${authorityLine}
97
+ [/conversation_goal]
91
98
  `);
92
99
  }
93
100
 
94
101
  export function buildGoalStateBlock(msg) {
95
102
  if ((msg.conversation_charter || '').trim()) return '';
96
103
  const convType = msg.conversation_type || 'dm';
97
- return convType === 'group'
98
- ? 'This group has no specific goal right now.'
99
- : 'This conversation has no specific goal right now.';
104
+ const subject = convType === 'group' ? 'This group' : 'This conversation';
105
+ const authorityLine = hasGoalAuthority(msg)
106
+ ? 'If this message may be starting, clarifying, or changing an ongoing goal, read GOAL_AUTHORITY.md "Goal Setup When No Specific Goal Exists" and follow it to propose/confirm the goal before writing charter/dashboard state. If it is clearly one-off, answer normally.'
107
+ : 'The group admin owns goal setup; follow direct mentions or assigned tasks normally.';
108
+ return promptBlock(`
109
+ [conversation_goal]
110
+ ${subject} does not have a chartered goal yet.
111
+ ${authorityLine}
112
+ [/conversation_goal]
113
+ `);
114
+ }
115
+
116
+ function hasGoalAuthority(msg) {
117
+ const convType = msg.conversation_type || 'dm';
118
+ if (convType !== 'group') return true;
119
+ if (msg.recipient_is_conversation_admin === true) return true;
120
+ const recipientRole = String(msg.recipient_conversation_role || msg.recipient_role || '').trim().toLowerCase();
121
+ return recipientRole === 'admin' || recipientRole === 'owner';
100
122
  }
101
123
 
102
124
  export function buildQuoteBlock(msg, target = '') {
@@ -129,6 +151,12 @@ function senderDescription(msg) {
129
151
  return sender ? `@${sender}, ${type}` : type;
130
152
  }
131
153
 
154
+ function senderFactDescription(msg) {
155
+ const type = msg.sender_type === 'agent' ? 'agent' : 'human user';
156
+ const sender = msg.sender_display_name || msg.sender_user_id || msg.sender_agent_id || '';
157
+ return sender ? `@${sender}, ${type}` : type;
158
+ }
159
+
132
160
  function conversationLabel(msg, target) {
133
161
  const convType = msg.conversation_type || 'dm';
134
162
  if (convType === 'dm') return 'a one-on-one conversation';
@@ -139,16 +167,17 @@ function buildMessageSummary(msg, target) {
139
167
  const convType = msg.conversation_type || 'dm';
140
168
  const reason = normalizeDeliveryReasonForPrompt(msg.reason || '');
141
169
  const sender = senderDescription(msg);
170
+ const senderFact = senderFactDescription(msg);
142
171
  const where = conversationLabel(msg, target);
143
172
 
144
173
  if (convType === 'dm') {
145
174
  return `This is a one-on-one message from ${sender}.`;
146
175
  }
147
176
  if (reason === 'assignment') {
148
- return `This message assigns or routes work to you in ${where}.\nSender: ${sender}`;
177
+ return `This message assigns or routes work to you in ${where}.\nSender: ${senderFact}`;
149
178
  }
150
179
  if (reason === 'ambient') {
151
- return `This message was shared as background context in ${where}.\nIt is not assigned work.\nSender: ${sender}`;
180
+ return `Sender: ${senderFact}`;
152
181
  }
153
182
  if (reason === 'mention') {
154
183
  return `You were mentioned in ${where} by ${sender}.`;
@@ -157,7 +186,7 @@ function buildMessageSummary(msg, target) {
157
186
  return `This is a reply in ${where} from ${sender}.`;
158
187
  }
159
188
  if (reason === 'manual') {
160
- return `This is a manual wake-up or reminder for ${where}.\nSource: ${sender}`;
189
+ return `This is a manual wake-up or reminder for ${where}.\nSource: ${senderFact}`;
161
190
  }
162
191
  return `This is a message in ${where} from ${sender}.`;
163
192
  }