diff --git a/docs/index.md b/docs/index.md index e4f92ab76..d9850f408 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,3 +13,22 @@ For all other documenation, see https://taskwarrior.org. * [Building Taskwarrior](./contrib/build) * [Coding Style](./contrib/coding_style) * [Branching Model](./contrib/branching) + +## RFC's + +This is where design documents (RFCs) are kept. + +Although these documents are less formal than [IETF RFCs](https://www.ietf.org/rfc) they serve a similar purpose. +These documents apply only to the Taskwarrior family of products, and are placed here to invite comment before designs finalize. + + - [General Plans](./rfcs/plans) + - [Rules System](./rfcs/rules) + - [Full DOM Support ](./rfcs/dom) + - [Work Week Support](./rfcs/workweek) + - [Recurrence](./rfcs/recurrence) + - [Taskwarrior JSON Format](./rfcs/task) + - [CLI Updates ](./rfcs/cli) + - [Taskserver Sync Protocol](./rfcs/protocol) + - [Taskserver Message Format](./rfcs/request) + - [Taskserver Sync Algorithm](./rfcs/sync) + - [Taskserver Client](./rfcs/client) diff --git a/docs/rfcs/_index.md b/docs/rfcs/_index.md new file mode 100644 index 000000000..4ecb6a2bc --- /dev/null +++ b/docs/rfcs/_index.md @@ -0,0 +1,24 @@ +--- +title: "Taskwarrior - What's next?" +--- + +# Design + +## Plans + + - [Task warrior/Taskserver/Tasksh/Timewarrior Plans](/docs/design/plans) + +## RFCs + + +### Tasksh + + - (No announced plans) + +### Timewarrior + + - (No announced plans) + +### Upcoming + + - Lazy Dates (Deferred Evaluation) diff --git a/docs/rfcs/cli.md b/docs/rfcs/cli.md new file mode 100644 index 000000000..99fd8b3c4 --- /dev/null +++ b/docs/rfcs/cli.md @@ -0,0 +1,162 @@ +--- +title: "Taskwarrior - Command Line Interface" +--- + +## Work in Progress + +This design document is a work in progress, and subject to change. Once +finalized, the feature will be scheduled for an upcoming release. + + +# CLI Syntax Update + +The Taskwarrior command line syntax is being updated to allow more consistent +and predictable results, while making room for new features. + +Adding support for arbitrary expressions on the command line has become +complicated because of the relaxed syntax of Taskwarrior. While the relaxed +syntax allows for a very expressive command line, it also creates ambiguity for +the parser, which needs to be reduced. + +With some limited and careful changes it will be possible to have a clear and +unambiguous command line syntax, which means a predictable and deterministic +experience. + +It should be stated that for straightforward and even current usage patterns, +the command line will likely not change for you. Another goal is to not require +changes to 3rd-party software, where possible. Only the more advanced and as-yet +unintroduced features will require a more strict syntax. This is why now is an +ideal time to tighten the requirements. + + +## Argument Types + +The argument types supported remain the same, adding some new constructs. + + --------------------------------------- --------------------------------------- + Config file override `rc:` + + Configuration override `rc::` Literal value\ + `rc:=` Literal value\ + `rc::=` Calculated value + + Tag `+`\ + `-`\ + `'+tag one'` Multi-word tag + + Attribute modifier `rc:.:`\ + Modifier is one of:\ + `before`\ + `after`\ + `under`\ + `over`\ + `above`\ + `below`\ + `none`\ + `any`\ + `is`\ + `isnt`\ + `equals`\ + `not`\ + `contains`\ + `has`\ + `hasnt`\ + `left`\ + `right`\ + `startswith`\ + `endswith`\ + `word`\ + `noword` + + Search pattern `//` + + Substitution `///`\ + `///g` + + Command `add`\ + `done`\ + `delete`\ + `list`\ + etc. + + Separator `--` + + ID Ranges `[-<id>][,[-<id>]...]` + + UUID `` + + Everything Else ``\ + `' ...'` + --------------------------------------- --------------------------------------- + + +## New Command Line Rules + +Certain command line constructs will no longer be supported, and this is imposed +by the new rules: + +1. Each command line argument may contain only one instance of one argument + type, unless that type is ``. + + task add project:Home +tag Repair the thing # Good + task add project:Home +tag 'Repair the thing' # Good + task add 'project:Home +tag Repair the thing' # Bad + + Putting two arguments into one quoted arg makes that arg a ``. + +2. If an argument type contains spaces, it must either be quoted or escaped. + + task add project:'Home & Garden' ... # Good + task add 'project:Home & Garden' ... # Good + task add project:Home\ \&\ Garden ... # Good + task add project:Home' & 'Garden ... # Good + task add project:Home \& Garden ... # Bad + + The parser will not combine multiple arguments, for example: + + task '/one two/' list # Good + task /one two/ list # Bad + task /'one two'/ list # Bad, unless ' is part of the pattern + +3. By default, *no* calculations are made, unless the `:=` eval operator is + used, and if so, the whole argument may need to be quoted or escaped to + satisfy Rule 1. + + task add project:3.project+x # Literal + task add project:=3.project+x # DOM reference + concatenation + +4. Bare word search terms are no longer supported. Use the pattern type + argument instead. + + task /foo/ list # Good + task foo list # Bad + +5. Expressions must be a series of arguments, not a quoted string. + + task urgency \< 5.0 list # Good + task 'urgency < 5.0 list' # Bad + + +## Other Changes + +Aside from the command line parser, there are other changes needed: + +- Many online documents will need to be modified. + +- Filters will be automatically parenthesized, so that every command line will + now looke like: + + task [overrides] [(cli-filter)] [(context-filter)] [(report-filter)] command [modifications] + +- There will be more errors when the command line is not understood. + +- Ambiguous ISO date formats are dropped. + + YYYYMMDD # Bad + YYYY-MM-DD # Good + + hhmmss # Bad + hh:mm:ss # Good + +- The tutorial videos will be even more out of date, and will be replaced by a + large number of smaller demo \'movies\'. diff --git a/docs/rfcs/client.md b/docs/rfcs/client.md new file mode 100644 index 000000000..0d018f15a --- /dev/null +++ b/docs/rfcs/client.md @@ -0,0 +1,444 @@ +--- +title: "Taskwarrior - Creating a Taskserver Client" +--- + + +# Creating a Taskserver Client + +A Taskserver client is a todo-list manager. It may be as simple as a program +that captures a single task, as complex as Taskwarrior, or anything in between. +It can be a mobile client, a web application, or any other type of program. + +This document describes how such a client would interact with the server. + +A client to the Taskserver is a program that manages a task list, and wishes to +exchange data with the server so that the task list may be shared. + +In order to do this, a client must store tasks locally, upload local changes, +download remote changes, and apply remote changes to the local tasks. + +The client must consider that there may be no network connectivity, or no desire +by the user to synchronize. + +The client will need proper credentials to talk to the server. + + +## Requirements + +In this document, we adopt the convention discussed in Section 1.3.2 of +[RFC1122](https://tools.ietf.org/html/rfc1122#page-16) of using the capitalized +words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the +significance of each particular requirement specified in this document. + +In brief: \"MUST\" (or \"REQUIRED\") means that the item is an absolute +requirement of the specification; \"SHOULD\" (or \"RECOMMENDED\") means there +may exist valid reasons for ignoring this item, but the full implications should +be understood before doing so; and \"MAY\" (or \"OPTIONAL\") means that this +item is optional, and may be omitted without careful consideration. + + +## Taskserver Account + +A Taskserver account must be created. This process creates a storage area, and +generates the necessary credentials. + + +## Credentials + +A Taskserver client needs the following credentials in order to communicate with +a server: + +- Server address and port +- Organization name +- User name +- Password +- Certificate +- Key + +The server address and port are the network location of the server. An example +of this value is: + + foo.example.com:53589 + +In addition to a DNS name, this can be an IPv4 or IPv6 address. + +The organization name is an arbitrary grouping, and is typically \'PUBLIC\', +reflecting the individual nature of server accounts. Future capabilities will +provide functionality that support groups of users, called an organization. + +The user name is the full name. This will be the name used to identify other +users in an organization, in a future release. Example \'John Doe\'. + +The password is a text string generated by the server at account creation time. +It should be considered a secret. + +The certificate is an X.509 PEM file generated by the server at account creation +time. This is used for authentication. It should be considered a secret. + +The key is an X.509 PEM file generated by the server at account creation time. +This is used for encryption. It should be considered a secret. + +These credentials need to be stored on the client, and used during the sync +operation. + + +## Description of a Taskserver Client + +This section describes how a client might behave in order to facilitate +integration with the Taskserver. + + +## Encryption + +The Taskserver only communicates using encryption. Therefore all user data is +encrypted while in transit. The Taskserver currently uses +[GnuTLS](https://gnutls.org) to support this encryption, and therefore supports +the following protocols: + +- SSL 3.0 +- TLS 1.0 +- TLS 1.1 +- TLS 1.2 + +The client may use any library that supports the above. + + +## Configuration + +The client needs to store configuration, which matches the credentials needed +for Taskserver communication. See section 2.1 \"Credentials\". + +The credentials may not be modified by the user without losing server access. + +The server:port data may need to be changed automatically following a redirect +response from the server. See section 5 \"Server Errors\". + + +## Local Storage + +The client needs to store task data locally. The client will need to be able to +find tasks by their UUID and overwrite them. Uploaded and downloaded task +changes will use the [Taskwarrior Data Interchange +Format](/docs/design/task). + + +## Local Changes + +Whenever local data is modified, that change MUST be synced with the server. But +this does not have to occur immediately, in fact the client SHOULD NOT assume +connectivity at any time. + +A client SHOULD NOT also assume that the server is available. If the server is +not available, the local changes should be retained, and the sync operation +repeated later. + +Ideally the client will give the user full control over sync operations. +Automatically syncing after all local modifications is not recommended. If a +client performs too many sync operations, the server MAY revoke the certificate. + +Effectively, the client should maintain a separate list of tasks changed since +the last successful sync operation. + +Note that tasks have a \"modified\" attribute, which should be updated whenever +a change is made. This attribute contributes to conflict resolution on the +server. + + +## Remote Changes + +When a server sends remote changes to a client, in the response to a sync +request, the changes have already been merged by the server, and therefore the +client should simply store them intact. + +Based on the UUID in the task, the client can determine whether a task is new +(and should be added to the local list of tasks), or whether it represents a +modification (and should overwrite it\'s existing entry). + +The client MUST NOT perform any merges. + + +## Sync Key + +Whenever a sync is performed, the server responds by sending a sync key and any +remote changes. The sync key is important, and should be included in the next +sync request. The client is REQUIRED to store the sync key in every server +response message. + +If a client omits the sync key in a sync message, the response will be a +complete set of all tasks and modifications. + + +## Data Integrity + +Although a task is guaranteed to contain at least \'entry\', \'description\' and +\'uuid\' attributes, it may also contain other known fields, and unknown +user-defined fields. An example might be an attribute named \'estimate\'. + +If a task is received via sync that contains an attribute named \'estimate\', +then a client has the responsibility of preserving the attribute intact. If that +data is shown, then it is assumed to be of type \'string\', which is the format +used by JSON for all values. + +Conversely, if a client wishes to add a custom attribute, it is guaranteed that +the server and other clients will preserve that attribute. + +Using this rule, two clients of differing capabilities can exchange data and +still maintain custom attributes. + +This is a requirement. Any client that does not obey this requirement is broken. + + +## Synchronizing + +Synchronizing with the Taskserver consists of a single transaction. Once an +encrypted connection is made with the server, the client MUST compose a [sync +request message](/docs/design/request). This message includes credentials +and local changes. The response message contains status and remote changes, +which MUST be stored locally. + + +## Establishing Encrypted Connection + +All communication with the Taskserver is encrypted using the certificate and key +provided to each user. Using the \'server\' configuration setting, establish a +connection. + + +## Sync Request + +See [sync request message](/docs/design/request). A sync request MUST +contain a sync key if one was provided by a previous sync. A sync request MUST +contain a list of modified tasks, in JSON format (see [Task +JSON](/docs/design/task)), if local modifications have been made. + + +## Sync Response + +A sync response WILL contain a \'code\' and \'status\' header variable, WILL +contain a sync key in the payload, and MAY contain a list of tasks from the +server in JSON format (see [Task JSON](/docs/design/task)). + + +## Server Messages + +There are cases when the server needs to inform the user of some condition. This +may be anticipated server downtime, for example. The response message is +typically not present, but may be present in the header, containing a string: + + ... + message: Scheduled maintenance 2013-07-14 08:00UTC for 10 minutes. + ... + +If such a message is returned by the server, it SHOULD be made available to the +user. This is a recommendation, not a requirement. + + +## Server Errors + +The server may generate many errors (See +[Protocol](/docs/design/protocol)), but the following is a list of the ones +most in need of special handling: + +- 200 Success +- 201 No change +- 301 Redirect +- 430 Access denied +- 431 Account suspended +- 432 Account terminated +- 5xx Error + +The 200 indicates success, and that a change was recorded. The 201 indicates +success but no changes were necessary. The 301 is a redirect message indicating +that the client MUST re-request from a new server. The 43x series messages are +account-related. Any 5xx series code is a server error of some kind. All errors +consist of a code and a status message: + + code: 200 + status: Success + + +## Examples + +Here are examples of properly formatted request and response messages. Note that +the messages are indented for clarity in this document, but is not the case in a +properly formatted message. Also note that newline characters U+000D are not +shown, but are implied by the separate lines. Because some messages have +trailing newline characters, the text is delimited by the \'cut\' markers: + + foo + +The example above illustrates text consisting of: + + U+0066 f + U+006F o + U+006F o + U+000D newline + U+000D newline + +Note that these values are left unspecified, but should be clear from the +context, and the [message format](/docs/design/request) spec: + + + + + + + +## First Sync + +The first time a client syncs, there is (perhaps) no data to upload, and no sync +key from a previous sync. + + type: sync + org: + user: + key: + client: task 2.3.0 + protocol: v1 + +Note the double newline character separating header from payload, with an empty +payload. + + +## Request: Sync No Data + +Ordinarily when a client syncs, there is a sync key from the previous sync +response to send. This example shows a sync with no local changes, but a sync +key from a previous sync. + + type: sync + org: + user: + key: + client: task 2.3.0 + protocol: v1 + + 2e4685f8-34bc-4f9b-b7ed-399388e182e1 + + +## Request: Sync Data + +This sync request shows a sync key from the previous sync, and a locally +modified task. + + type: sync + org: + user: + key: + client: task 2.3.0 + protocol: v1 + + 2e4685f8-34bc-4f9b-b7ed-399388e182e1 + {"description":"An example","uuid":"8ad2e3db-914d-4832-b0e6-72fa04f6e331",...} + + +## Response: No Data + +If a sync results in no downloads to the client, the response will look like +this. + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 200 + status: Ok + + 45da7110-1bcc-4318-d33e-12267a774e0f + +Note that there is a sync key which must be stored and used in the next sync +request, but there are no remote changes to store. + + +## Response: Remote Data + +This shows a sync response providing a new sync key, and a remote change to two +tasks. + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 200 + status: Ok + + 45da7110-1bcc-4318-d33e-12267a774e0f + {"description":"Test data","uuid":"8ad2e3db-914d-4832-b0e6-72fa04f6e331",...} + {"description":"Test data2","uuid":"3b6218f9-726a-44fc-aa63-889ff52be442",...} + +Note that the sync key must be stored for the next sync request. + +Note that the two changed tasks must be stored locally, and if the UUID in the +tasks matches local tasks, then the local tasks must be overwritten. + + +## Response: Error + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 431 + status: Account suspended + +Note the double newline character separating header from payload, with an empty +payload. + + +## Response: Relocate + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 301 + status: Redirect + info: + +Note the \'info\' field will contain a \':\' string that should be used for all +future sync requests. This indicates that a user account was moved to another +server. + +Note the double newline character separating header from payload, with an empty +payload. + + +## Response: Message + +Occasionally the server will need to convey a message, and will include an +additional header variable containing that message. + +The server [protocol](/docs/design/protocol) states that the message SHOULD +be shown to the user. This message will be used for system event messages, used +rarely, and never used for advertising or promotion. + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 200 + status: Ok + message: Scheduled maintenance 2013-07-14 08:00UTC for 10 minutes. + + 45da7110-1bcc-4318-d33e-12267a774e0f + +Note that the same message will likely be included in consecutive responses. + + +## Reference Implementation + +The Taskserver 1.1.0 codebase contains a reference implementation of an SSL/TLS +client and server program, which communicate text strings. + + taskd.git/src/tls/Makefile # To build the example + taskd.git/src/tls/README # How to run the example + taskd.git/src/tls/TLSClient.cpp # TLS client code + taskd.git/src/tls/TLSClient.h + taskd.git/src/tls/TLSServer.cpp # TLS Server code + taskd.git/src/tls/TLSServer.h + taskd.git/src/tls/c.cpp # Client program + taskd.git/src/tls/s.cpp # Server program + taskd.git/src/tls/text.cpp # Text manipulation + taskd.git/src/tls/text.h # Text manipulation + +The Taskwarrior codebase, version 2.4.0, is the reference implementation. + + task.git/src/TLSClient.cpp # TLS client code + task.git/src/TLSClient.h + task.git/src/commands/CmdSync.cpp # Sync implementation + task.git/src/commands/CmdSync.h diff --git a/docs/rfcs/dom.md b/docs/rfcs/dom.md new file mode 100644 index 000000000..d63bc5c57 --- /dev/null +++ b/docs/rfcs/dom.md @@ -0,0 +1,259 @@ +--- +title: "Taskwarrior - Full DOM Support" +--- + +## Work in Progress + +This design document is a work in progress, and subject to change. Once +finalized, the feature will be scheduled for an upcoming release. + + +# Full DOM Support + +Taskwarrior currently supports DOM references that can access any stored data +item. The general forms supported are: + + [ | ] [ ] + +Examples include: + + due + 123.uuid + entry.month + 123.annotations.0.entry.year + a87bc10f-931b-4558-a44a-e901a77db011.description + +Additionally there are references for accessing configuration and system/program +level items. + + rc. + context.program + context.args + context.width + context.height + system.version + system.os + +While this is adequate for data retrieval, we have the possibility of extending +it further to include data formats, higher-level constructs, and then to make +use of DOM references in more locations. This contributes to our goal of +simplifying Taskwarrior. + + +## Proposed Format Support + +When defining a custom report, the columns shown are defined like this: + + report.x.columns=uuid.short,description.oneline ... + +This syntax is: + + [ . ] + +If no `format` is specified, then `default` is assumed. The src/columns/ColΧ\* +objects are responsible for supporting and rendering these formats. There is +currently no consistency among these formats based on data type. + +By incorporating formats into DOM references, we eliminate the need for a +separate syntax for custom reports, and provide this: + + 123.due.iso + 123.due.month.short + 123.uuid.short + +A standard set of formats per data type would be: + +Type + +Formats + +Example + +Numeric + +default + +`123 ` + +indicator + +Based on `rc..indicator` which overrides `rc.numeric.indicator`. + +json + +`"":""` + +String + +default + +Buy milk + +short + +Feb + +indicator + +Based on `rc..indicator` which overrides `rc.string.indicator`. + +json + +`"":""` + +Date + +default + +Based on `rc.dateformat` + +iso + +2017-02-20T09:02:12 + +julian + +2457805.12858 + +epoch + +1234567890 + +age + +2min + +relative + +-2min + +remaining + +0:02:04 + +countdown + +0:02:04 + +indicator + +Based on `rc..indicator` which overrides `rc.date.indicator`. + +json + +`"":""` + +Duration + +default + +1wk + +iso + +P1W + +indicator + +Based on `rc..indicator` which overrides `rc.duration.indicator`. + +json + +`"":""` + +There will also be a set of attribute-specific formats, similar to the currently +supported set: + + depends.list + depends.count + description.combined + description.desc + description.oneline + description.truncated + description.count + description.truncated_count + parent.default|long + parent.short + project.full + project.parent + project.indented + status.default|long + status.short + tags.default|list + tags.count + urgency.default|real + urgency.integer + uuid.default|long + uuid.short + +Custom report sort criteria will also use DOM references. This will be augmented +by the `+`/`-` sort direction and `/` break indicator, which are not part of the +DOM. + + +## High Level Construct Support + +There need to be read-only DOM references that do not correspond directly to +stored attributes. Tasks have emergent properties represented by virtual tags, +which will be accessible, in this case returning a `0` or `1`: + + 123.tags.OVERDUE + +Using `rc.due` and the `due` attribute, the `OVERDUE` virtual tag is a +combination of the two. Other examples may include: + + task.syncneeded + task.pending.count + task.hooks.installed + + +## Writable References + +When a DOM reference refers to an attribute or RC setting, and does not extend +further and reference a component or format, it may be writable. For example: + + rc.hooks # writable + 123.description # writable + 123.entry.month # not writable, not an attribute + + +## Data Interchange + +The export command can be used to show a filtered set of tasks in JSON format, +and this will also be available as a DOM format: + + 123.json + a87bc10f-931b-4558-a44a-e901a77db011.json + + +## RC File Support + +The RC file (`~/.taskrc`) will support DOM references in values. This will form +a late-bound reference, which is evaluated at runtime, every time. + +An example is to make two reports share the same description: + + $ task config -- report.ls.description rc.report.list.description + +This sets the description for the `ls` report to be a reference to the +description of the `list` report. This reference is not evaluated when the entry +is written, but is evaluated every time the value is read, thus providing +late-bound behavior. Then if the description of the `list` report changes, so +does that of the `ls` report automatically. + + +## Implementation Details + +These notes list a series of anticipated changes to the codebase. + +- The `src/columns/Col*` objects will implement type-specific and + attribute-specific DOM support. DOM reference lookup will defer to the + column objects first. +- Some DOM references will be writable, permitting a `_set` command to + complement the `_get` command. +- The `Config` object will recognize DOM references in values and perform + lookup at read time. This will require circularity detection. +- `src/DOM.cpp` will provide a memoized function to determine whether a DOM + reference is valid. +- `src/DOM.cpp` will provide a function to obtain a DOM reference value, with + supporting metadata (type, writable). diff --git a/docs/rfcs/plans.md b/docs/rfcs/plans.md new file mode 100644 index 000000000..dc056aff9 --- /dev/null +++ b/docs/rfcs/plans.md @@ -0,0 +1,436 @@ +--- +title: "Plans" +--- + +There are many interconnected features and technologies in Taskwarrior, +Taskserver, Tasksh and Timewarrior, each piece having it's own goals. + +This matrix allows a simple reading of where things are, and where they are +going. This is a low-resolution time line. It is subject to change. It does not +constitute a concrete plan. This is an all-volunteer effort, and scheduling is +difficult. + +[Last updated 2016-08-08.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Taskwarrior
Technology/Feature
+ 2.5.1
+ Current

+ Released 2016-02-24 +
+ 2.6.0
+ Next

+ 2017 +
+ 2.x
+ Future +
Core + DOM
+ Filters
+ Expressions
+ Color Rules
+ Custom Reports
+ Annotations
+ Tags / Virtual Tags
+ Context
+
+ Recurrence
+ Shared library
+ purge command
+
+ True Color +
API + JSON
+ Import
+ Export
+ Hooks
+ Hooks v2
+ DOM
+ Helper commands
+
+ + on-sync hook
+ Full DOM
+ DOM access in rc
+ $ENV access in rc
+ Report columns as DOM refs
+
+ Attributes
+ User Defined Attributes (UDA) +
+ modified
+ priority as a UDA
+
+ template
+ rtype
+ Remove mask
+ Remove imask
+ Remove parent
+
+ org
+ group
+
Reports + Improved layouts
+ Improved Themes +
+ Daily, Weekly reports (history, ghistory)
+
+
Synchronization + task sync
+ task sync init (all tasks)
+
+ + task sync reset
+
TDB (task database) + Local file locking
+ Single file set
+ Single user +
+ + Threaded file load
+ Read-only mode +
I18N / L10N + UTF-8 support
+ deu-DEU
+ eng-USA
+ epo-RUS
+ esp-ESP
+ fra-FRA
+ ita-ITA
+ pol-POL
+ por-PRT
+
+ No I18N / L10N + + Migrate to gettext
+
Documentation + man: task
+ man: taskrc
+ man: task-color
+ man: task-sync
+ youtube: various
+ taskwarrior.org
+ taskwarrior.com: Support Site
+
+ + New video tutorials
+
Testing + C++ tests
+ Python tests
+ Sync tests
+ Parallel tests
+
+ Migration to Flod2
+
+
Tool Chain + GCC 4.7 / Clang 3.3
+ C++11 support
+ CMake
+
+ GCC 4.9 / Clang 3.4
+ Full C++11 support
+
+ Full C++14 support
+ Full C++17 support
+
+ + + + + + + + + + + + + + + + + + + + + + +
Tasksh
Technology/Feature
+ 1.1.0
+ Current

+ Released 2016-09-05 +
+ 1.2.0
+ Next

+ 2017 +
+ 1.x
+ Future +
Core + Review
+ libreadline
+ Shared library
+
+ + Pomodoro timer
+
Tool Chain + CMake
+ GCC 4.7 / Clang 3.3
+
+ GCC 4.9 / Clang 3.4
+ Full C++11 support
+
+ Full C++14 support
+ Full C++17 support
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Taskserver
Technology/Feature
+ 1.1.0
+ Current

+ Released 2015-05-10 +
+ 1.2.0
+ Next

+ 2017 +
+ 1.x
+ Future +
Core + Serial server + + Shared library
+
+ Threaded server +
Protocol + v1 + + v1.1 - client reset request
+
+ v1.2 +
DB (Data Storage) + + + GC +
Security + Validation + + + UUID:Cert Verification
+ Combined Certs +
Tool Chain + GCC 4.7 / Clang 3.3
+ CMake
+
+ GCC 4.9 / Clang 3.4
+ Full C++11 support
+
+ Full C++14 support
+ Full C++17 support
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Timewarrior
Technology/Feature
+ 1.0.0
+ Current

+ Released 2016-08-20 +
+ 1.1.0
+ Next

+ 2017 +
+ 1.x
+ Future +
Core + Shared library
+
+ + True Color +
Reports + summary report
+ gaps report
+ day chart
+ week chart
+ month chart
+ totals.py extension
+
+ +
Rules + Simple configuration rules + + + Rule System
+
Integration + Taskwarrior on-modify hook script + + +
Tool Chain + CMake
+ GCC 4.7 / Clang 3.3
+ C++11 support
+
+ GCC 4.9 / Clang 3.4
+ Full C++11 support
+
+ Full C++14 support
+ Full C++17 support
+
diff --git a/docs/rfcs/protocol.md b/docs/rfcs/protocol.md new file mode 100644 index 000000000..bd2f4e299 --- /dev/null +++ b/docs/rfcs/protocol.md @@ -0,0 +1,211 @@ +--- +title: "Taskwarrior - Sync Protocol" +--- + + +# Sync Protocol + + +## Introduction + +Taskwarrior data has typically been shared in several ways. Those include SCM +(source code management) systems, directory synchronizing software (such as +DropBox), and by use of the \'push\', \'pull\' and \'merge\' commands introduced +in version 1.9.3. + +While these methods work, they each have problems associated with the merging of +data. In the case of directory synchronizing software, there is no merging at +all - just simple file overwrite, despite many people believing that the data is +somehow combined and preserved. + +The Taskserver is a solution. It is an online/cloud storage and sync service for +taskwarrior data. It performs conflict-free data merging, and minimizes +bandwidth use. + +The Taskserver also provides multi-client access, so that a task added using a +web client could be immediately viewed using a mobile client, or modified using +taskwarrior. Choice of clients is important - people have widely varying +behaviors and tastes. + +The Taskserver also provides multi-user access, which introduces new +capabilities, such as list sharing and delegation. These will require later +modification to this protocol. + +The Taskserver protocol will be implemented by the taskd project and first used +in taskwarrior 2.3.0. Other clients will follow. + + +## Requirements + +In this document, we adopt the convention discussed in Section 1.3.2 of +[RFC1122](https://tools.ietf.org/html/rfc1122#page-16) of using the capitalized +words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the +significance of each particular requirement specified in this document. + +In brief: \"MUST\" (or \"REQUIRED\") means that the item is an absolute +requirement of the specification; \"SHOULD\" (or \"RECOMMENDED\") means there +may exist valid reasons for ignoring this item, but the full implications should +be understood before doing so; and \"MAY\" (or \"OPTIONAL\") means that this +item is optional, and may be omitted without careful consideration. + + +## Link Level + +The Taskserver protocol assumes a reliable data stream such as provided by TCP. +When TCP is used, a Taskserver listens on a single predetermined port *for the +given client* only. This means the server may be using multiple ports to serve +distinct sets of clients. + +This server is only an interface between programs and the task data. It does not +perform any user interaction or presentation-level functions. + + +## Transactions + +Each transaction is a single incoming message, with a single response message. +All communication therefore consists of a single \'send\', followed by a single +\'receive\', then termination. There are no sessions, and no continuously open +connections. The message format is described in the [Taskserver Message +Format](/docs/design/request) document. + + +## Responsibilities of the Server + +The server will maintain a set of transactions, in the original sequence, +punctuated by sync keys which are UUIDs. Each sync key represents a non- trivial +sync operation by a client. Each transaction is a [JSON-formatted +task](/docs/design/task), followed by a newline (\\n) character. The result +is a single file that contains interleaved lines of two types: tasks and sync +keys. + +This design allows the server to maintain a set of deltas such that multiple +clients may request a minimal set of changes since their last sync. + + +## Responsibilities of the Client + +This describes how Taskwarrior implements sync. + +All modifications to tasks (add, modify, done, delete \...) are recorded in the +form of a fully-composed [JSON-formatted task](/docs/design/task). The +formatted task is added to a local backlog.data file. If a task is modified a +second time, it is added again to the backlog.data file - the lines are not +combined. Each task SHALL have a \'modified\' date attribute that will help +resolve conflicts. + +On sync: + +- Send a \'sync\' type message with the entire contents of the backlog.data, + unmodified, as the message payload. +- Receive one of the following response codes: + - 201: This means \'no change\', and there is no further action to be + taken. + - 200: This means \'success\', and the message payload contains a set of + tasks and a sync key: + - The formatted tasks are to be stored as-is. These tasks will either + be appended to the client data or will overwrite existing client + data, based on the UUID of the task. No merge logic is necessary. + - The sync key will be written to the backlog.data file, overwriting + the previous contents, such that it will now contain only one line. + - 301: Redirect to : found in the \'info\' response header, will force the + client to resubmit the request to the new server. + - 3xx, 4xx, 5xx: The \'status\' field contains an error message. +- If the response contained any error or warning, the error should be shown to + the user. This provides an opportunity for the server to announce downtime, + or relocation. + +If no sync key is sent, the server cannot provide an incremental delta, and so +will send all task data, which should be stored as above. This should be the +case for a client making its first sync call. + +If an unrecognized attribute is present in the task data, the client MUST +preserve the attribute unmodified, and assume it is of type \'string\'. This +permits individual clients to augment the task data without other clients +stripping it meaningful data. This is how UDAs (user defined attributes) are +handled. + + +## Extensions + +This protocol was designed so that extensions to the protocol will take the form +of additional message types and status codes. + + +## Summary of Response Codes + +Status responses indicate the server\'s response to the last command received +from the client. The codes consist of a 3 digit numeric code. + +The first digit of the response broadly indicates the success, failure, or +progress of the previous command (based generally on +[RFC640](https://tools.ietf.org/html/rfc640) +[RFC821](https://tools.ietf.org/html/rfc821)): + + ----- ------------------------------------- + 1yz Positive Preliminary reply + 2yz Positive Completion reply + 3yz Positive Intermediate reply + 4yz Transient Negative Completion reply + 5yz Permanent Negative Completion reply + ----- ------------------------------------- + +The next digit in the code indicates the response category: + + ----- ------------------------------------------------- + x0z Syntax + x1z Information (e.g., help) + x2z Connections + x3z Authentication + x4z Unspecified as yet + x5z Taskd System (\...) + x8z Nonstandard (private implementation) extensions + ----- ------------------------------------------------- + +A summary of all status response are: + + ----- ----------- + 200 Success + 201 No change + ----- ----------- + + ----- ---------------------------------------------------------------------------------------------------------------------------------------------- + 300 Deprecated message type. This message will not be supported in future Taskserver releases. + 301 Redirect. Further requests should be made to the specified server/port. + 302 Retry. The client is requested to wait and retry the same request. The wait time is not specified, and further retry responses are possible. + ----- ---------------------------------------------------------------------------------------------------------------------------------------------- + + ----- ------------------------------------------ + 400 Malformed data + 401 Unsupported encoding + 420 Server temporarily unavailable + 421 Server shutting down at operator request + 430 Access denied + 431 Account suspended + 432 Account terminated + ----- ------------------------------------------ + + ----- ----------------------------------- + 500 Syntax error in request + 501 Syntax error, illegal parameters + 502 Not implemented + 503 Command parameter not implemented + 504 Request too big + ----- ----------------------------------- + + +## Security Considerations + +All communication with the Taskserver uses SSL 3.0 or TLS 1.0, 1.1 or 1.2. +Encryption is mandatory. Data is never transmitted in plain text. + + +## Limitations and Guidelines + +Some limitations exists to reduce bandwidth and load on the server. They are: + +- A client may only connect to a single server. Synchronization among a set of + servers is not supported. +- A client should attempt to minimize data bandwidth usage by maintaining a + local data store, and properly using sync keys. +- A client should minimize data transfers by limiting the frequency of sync + requests. diff --git a/docs/rfcs/recurrence.md b/docs/rfcs/recurrence.md new file mode 100644 index 000000000..641c87499 --- /dev/null +++ b/docs/rfcs/recurrence.md @@ -0,0 +1,203 @@ +--- +title: "Taskwarrior - Recurrence" +--- + +# Draft + +This is a draft design document. Your +[feedback](mailto:support@taskwarrior.org?Subject=Feedback) is welcomed. + +Recurrence +---------- + +Recurrence needs an overhaul to improve weaknesses and add new features. + +# Terminology + +- The hidden 'parent' task is called the template. +- Synthesis is the name for the generation of new recurring task instances + when necessary. +- The synthesized tasks are called instances. +- The index is the zero-based monotonically increasing number of the instance. +- Drift is the accumulated errors in time that cause a due date to slowly + change for each recurring task. + +# Criticism of Current Implementation + +- The `mask` attribute grows unbounded. +- Only strict recurrence cycles are supported. The example of mowing the lawn + is that you want to mow the lawn every seven days, but when you are four + days late mowing the lawn, the next mowing should be in seven days, not in + three. +- Intances generated on one machine and then synced, may collide with + equivalent unsynced instances tasks on another device, because the UUIDs are + different. +- You cannot `wait` a recurring task and have that wait period propagate to + all other child tasks. +- Task instances cannot individually expire. + +# Proposals + +## Proposal: Eliminate `mask`, `imaѕk` Attributes + +The `mask` attribute in the template is replaced by `last`, which indicates the +most recent instance index synthesized. Because instances are never synthesized +out of order, we only need to store the most recent index. The `imask` attribute +in the instance is no longer needed. + +## Proposal: Rename `parent` to `template` + +The name `parent` implies subtasks, and confuses those who inspect the +internals. The value remains the UUID of the template. This frees up the +namespace for future use with subtasks. + +## Proposal: New 'rtype' attribute + +To indicate the flavor of recurrence, support the following values: + +* `periodic` - Instances are created on a regular schedule. Example: send birthday flowers. It must occur on a regular schedule, and doesn't matter if you were late last year. This is the default value. +* `chained` - Instances are created back to back, so when one instance ends, the next begins, with the same recurrence. Example: mow the lawn. If you mow two days late, the next instance is not two days early to compensate. + +## Proposal: Use relative offsets + +The delta between `wait` and `due` date in the template should be reflected in +the delta between `wait` and `due` date in the instance. Similarly, +'scheduled' must be handled the same way. + +## Proposal: On load, auto-upgrade legacy tasks + +Upgrade template: + +- Add `rtype:periodic` +- Add `last:N` where `N` is the length of `mask` +- Delete `mask` + +Upgrade instance: + +- Rename `parent` to `template` +- Delete `imask` +- Update `wait` if not set to: `wait:due + (template.due - template.wait)` +- Update `scheduled` if not set to: + `scheduled:due + (template.due - template.scheduled)` + +## Proposal: Deleting a chained instance + +Deleting a `rtype:chained` instance causes the next chained instance to be +synthesized. This gives the illusion that the due date is simply pushed out to +`(now + template.recur)`. + +## Proposal: Modification Propagation + +TBD + +## Proposal: Exotic Dates + +Expand date specifications to use pattern phrases: + +- `4th thursday in November` +- `4th thursday of November` +- `Friday before easter` +- `next Tuesday` +- `last Tuesday` +- `last July` +- `weekend` +- `3 days before eom` +- `in the morning` +- `4pm` +- `noon` +- `midnight` + +Got suggestions? + +## Proposal: User-Defined Week Start + +TBD + +# Implementation + +## Implementation: Adding a new `periodic` template + +When adding a new periodic template: + + task add ... due:D recur:R wait:D-1wk scheduled:D-1wk until:U + +Creates: + + template.uuid: NEW_UUID + template.description: ... + template.entry: now + template.modified: now + template.due: D + template.recur: R (stored in raw form, ie 'P14D') + template.wait: D-1wk + template.scheduled: D-1wk + template.until: U + template.rtype: periodic + template.last: + +Creating the Nth instance (index N): + + Clone instance from template. + + instance.uuid: NEW_UUID + instance.modified: now + instance.due: template.due + (N * template.recur) + instance.wait: instance.due + (template.due - template.wait) + instance.scheduled: instance.due + (template.due - template.scheduled) + instance.start: + + template.last: N + +## Implementation: Adding a new `chained` template + +When adding a new chained template: + + task add ... due:D recur:R wait:D-1wk scheduled:D-1wk until:U rtype:chained + +Creates: + + template.uuid: NEW_UUID + template.description: ... + template.entry: now + template.modified: now + template.due: D + template.recur: R (stored in raw form, ie 'P14D') + template.wait: D-1wk + template.scheduled: D-1wk + template.until: U + template.rtype: chained + +Creating the Nth instance (index N): + + Clone instance from template. + + instance.uui d: NEW_UUID + instance.mod ified: now + instance.due : instance[N-1].end + template.recur + instance.wai t: instance.due + (template.due - template.wait) + instance.sch eduled: instance.due + (template.due - template.scheduled) + instance.sta rt: + +Chained tasks do not obey `rc.recurrence.limit`, and show only one pending task +at a time. + +## Implementation: Special handling for months + +Certain recurrence periods are inexact: + +- P1M +- P1Y +- P1D + +When the recurrence period is `P1M` the number of days in a month varies and +causes drift. + +When the recurrence period is `P1Y` the number of days in a year varies and +causes drift. + +When the recurrence period is `P1D` the number of hours in a day varies due to +daylight savings, and causes drift. + +Drift should be avoided by carefully implementing: + + instance.due: template.due + (N * template.recur) diff --git a/docs/rfcs/request.md b/docs/rfcs/request.md new file mode 100644 index 000000000..293b807d6 --- /dev/null +++ b/docs/rfcs/request.md @@ -0,0 +1,221 @@ +--- +title: "Taskwarrior - Request" +--- + + +# Taskserver Message Format + +The Taskserver accepts and emits only messages. These messages look somewhat +like email, as defined in [RFC821](https://tools.ietf.org/html/rfc821), +[RFC2822](https://tools.ietf.org/html/rfc2822). + +The message format allows for data, metadata, and extensibility. This +combination allows the Taskserver to accommodate current and future needs. This +document describes the message format, and the supported message types. + + +## Requirements + +In this document, we adopt the convention discussed in Section 1.3.2 of +[RFC1122](https://tools.ietf.org/html/rfc1122#page-16) of using the capitalized +words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the +significance of each particular requirement specified in this document. + +In brief: \"MUST\" (or \"REQUIRED\") means that the item is an absolute +requirement of the specification; \"SHOULD\" (or \"RECOMMENDED\") means there +may exist valid reasons for ignoring this item, but the full implications should +be understood before doing so; and \"MAY\" (or \"OPTIONAL\") means that this +item is optional, and may be omitted without careful consideration. + + +## Encoding + +All messages are UTF8-encoded text. + + +## Message Format + +This format is based on [RFC2822](https://tools.ietf.org/html/rfc2822), +\'Internet Message Format\'. Here is an example of the format: + + + name: value + name2: value2 + + payload + +There are three sections. The first is the size, which is a 4-byte, big- Endian, +binary byte count of the length of the message, including the 4 bytes for the +size. + +The header section is a set of name/value pairs separated by newline characters +(U+000D). The name is separated from the value by \': \' (colon U+003A, space +U+0020) The header section is terminated by two consecutive newline (U+000D) +characters. All text is UTF8-encoded. + +The payload section is arbitrary, and message type-specific. However, it is +still UTF8-encoded text. + + +## Message Requirements + +Messages SHALL contain particular headers. Those are: + +- type +- protocol +- client + +The \'type\' value is what determines the interpretation of the payload. + +The \'protocol\' value should be \'v1\', or any subsequently published protocol +version. + +The \'client\' represent the client identifier, so that any special cases can be +handled. For example, an emergency fix that is client version-specific could be +released, to support users that have not updated their client, or perhaps the +client has not released a fix. The form of the \'version\' value is: + + + +As an example: + + taskwarrior 2.3.0 + +DO NOT spoof any other software using this client value. If another client is +spoofed, then patches addressing protocol errors may break working software. + + +## Auth Data + +Every request from the client SHALL contain \"auth\" information, which involves +these header entries: + + org: + user: + key: + +The user and org fields uniquely identify a user. + +The key field is generated when a new server account is set up. It is a shared +secret, equivalent to a password, and should be protected. + +Authentication failure can result in these errors: + +- 430 Authentication failed +- 431 Account suspended + + +## Status Data + +Every response from the Taskserver SHALL contain status data: + + code: + status: + +The code is a numeric status indicator defined in the [Sync +Protocol](/docs/design/protocol). + + +## Payload Data + +Payload data is optional, arbitrary and message type dependent. It is always +UTF8-encoded text. + + +## Message Types + +The Taskserver supports several message types, thus providing a set of +primitives for use by clients. + +It is expected that the number of supported ticket types will increase over +time. + + +## Sync Message + +The \"sync\" message always originates from the client, but the response will +contain data from the server. A sync is therefore a single request with a single +response. + +The \"sync\" message type MUST contain the following headers: + +- type +- org +- user +- key +- client +- protocol + +The \"sync\" message payload has this format: + + + + + ... + + +Here is an example of a sync message: + + type: sync + org: + user: + key: + client: task 2.3.0 + protocol: v1 + + 2e4685f8-34bc-4f9b-b7ed-399388e182e1 + {"description":"Test data","entry":"20130602T002341Z","status":"pending"} + +The request contains the proper auth section, and the body contains the current +sync key followed by a newline characters (U+000D), then a list of +JSON-formatted tasks \[2\] each separated by a newline character (U+000D). + +An example response message might be: + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 200 + status: Ok + + 45da7110-1bcc-4318-d33e-12267a774e0f + +The status indicates success, and the payload contains zero remote task +modifications, followed by a sync key. + + +## Statistics Message + +The message format іs simply: + + type: statistics + org: + user: + key: + client: taskd 1.0.0 + protocol: v1 + +There is no payload. An example response message might be: + + type: response + client: taskd 1.0.0 + protocol: v1 + code: 200 + status: Ok + average request bytes: 0 + average response bytes: 0 + average response time: 0.000000 + errors: 0 + idle: 1.000000 + maximum response time: 0.000000 + total bytes in: 0 + total bytes out: 0 + tps: 0.000000 + transactions: 1 + uptime: 28 + +There is no payload, and the results are in the header variables. + +Note that the statistics gathered by the server are growing, which means new +values are occasionally added to the response message. Existing values will not +be removed. diff --git a/docs/rfcs/rules.md b/docs/rfcs/rules.md new file mode 100644 index 000000000..cf08acd3a --- /dev/null +++ b/docs/rfcs/rules.md @@ -0,0 +1,231 @@ +--- +title: "Taskwarrior - Rule System" +--- + +## Work in Progress + +This design document is a work in progress, and subject to change. Once +finalized, the feature will be scheduled for an upcoming release. + + +# Rule System + +The rule system is a framework that supports highly configurable features, with +runtime evaluation, DOM access and an internal API. Implementing a rule system +meets the goal of shrinking and stabilizing the product core, while adding new +features, and enabling many more. + + +## Required Enhancements + +To prepare for a Rules System, various subsystems must first be enhanced: + +- DOM references need to be unambiguous, and will all have the `dom.` prefix. + +- DOM references need to be able to access any Taskwarrior data, in any + +- Custom reports will change from referencing `[.]` to simply + `` + +- RC file syntax needs to be enhanced, so support rule definitions, which are + multi-line blocks that are indentation-sensitive + +- RC file syntax will support two ways of specifying the same data: + + a.b.c=... + + a: + b: + c=... + +- RC file syntax will allow the use of environment variables inline: + + name=${TERM} + include ${HOME}/.taskrc_local + +- The `Variant` object will migrate to `libshared` + +- The expression evaluator `Eval` object will migrate to `libshared` + +- The column objects will gain a more structured base class, and will serve as + providers for DOM references + +- The \'exec\' command will be able to run a rule, if the reference is correct + +- Taskwarrior will store state data in a new `state.data` file + +- `Config` object needs to use the `rat` parser, to tackle the more complex + syntax + +- The RC file will support environment variable expansion, where `${NAME}` + will be replaced by its corresponding value at launch time + +At that point, the rules system can be implemented in `libshared`, and will use +a pluggable architecture to allow its integration into several projects. + + +## DOM Enhancements + +DOM references will be enhanced, with many more references supported. All DOM +references will begin with `dom.`, yielding unambiguous references. References +will have a type. Types will support sub-references (`.`, +`.`, `.`), and display formats included. + + dom . [ .] [. ] . + + dom . 123 . entry . year . yyyy + dom . 123 . entry + dom . 123 . tags + dom . 123 . tags . count + dom . 123 . tags . 1 + +In addition to direct attribute access, DOM references will also support tw +references beyond the current set: + + dom.rc. + dom.cli.args + dom.terminal.width + dom.terminal.height + dom.system.version + dom.system.oѕ + +And will also support higher-level constructs that do not directly correlate to +attributes, for example: + + dom.active Boolean indicator of any active tasks + dom.synced Boolean indicator of the need to sync + dom.rc.path String path of .taskrc file (or override) + dom.data.path String path of data directory + dom.hooks.path String path of hooks directory + +Finally, access to state: + + dom.state.program + dom.state.sync.last + dom.state.sync.configured + dom.state.run.last + dom.state.context + + +## RC Syntax Changes + +The current configuration system supports only two different forms of syntax: + + = [ ] + + include + +A rule is a new form of syntax that consists of the rule keyword, a name, +optional trigger, followed by indented actions in the form of API calls and flow +control. For example: + + rule myRule() on_launch: + # Some code here + +A rule definition will appear in the RC file, alongside all the existing +settings. The rule syntax will require a blank line to terminate the rule +definition, the result being that the RC file should be quite readable, although +it will look like Python. + + +## Hook Scripts + +While this functionality can also be implemented using hook scripts, rules will +run in-process, and therefore do not require external interpreters to be +launched every time. This creates the potential to run faster than a hook +script. + +For complex processing, hook scripts will be the preferred mechanism, but as the +rules system matures, rules will be made to run more quickly. With adequate +performance, a rule will be the preferred implementation over a hook script. +This is not expected to be the case at first. + +Hook scripts are not likely to be extended beyond their current form, and with +greater DOM access and a growing API, rules should be able to supplant most hook +script use cases. + + +## Rule Triggers + +The set of supported rule types will include: + +* `on_launch` - Triggered on program launch. +* `on_add` - Triggered when a task is added. A context task will be provided. The rule can modify the task, and approve or reject it. +* `on_modify` - Triggered when a task is modified. A before and after context task will be provided. The rule can modify the task, and approve or reject it. +* `on_exit` - Triggered on program exit. +* `color` - Triggered when colors are being determined. +* `virtual tag` - Defines a new virtual tag. +* `format` - Triggered when an attribute needs formatting, defines are new format. + +More rules types will be added for more capabilities in future releases. + + +## API + +The API is a simple set of actions that may be taken by a rule. + +* `debug()` - Displays the string in debug mode only and continues processing. +* `warn()` - Displays the string as a warning continues processing. +* `error()` - Displays the string as an error and terminates processing. +* `exec( [ ... ])` - Executes the external program and passes arguments to it. If the program exits with non-zero status, it is treated as an error. +* `return ` - Provides a result value for the rule, when necessary. + +This is a very limited set at first, and more API calls will be added to support +capabilities in future releases. + + +## Grammar + +The grammar closely tracks that of Python. Blocks are indented consistently. + +* `if : ... else: ... ` - The condition is a full Algebraic expression, and supports none of the command line conveniences. Terms must be combined with logical operators. The condition is an expression that is evaluated and converted to a Boolean value. +* `for in : ` - There is no native type for a collection, but there are DOM references (`tags` \...) that reference collections. This provides a way to iterate. +* `set = ` - Writes to a named type. The name may be a writable DOM object (`dom...`) or temporary variable storage (`tmp...`). Writing to a read-only DOM reference is an error. +* `([]) ` - A function is either a rule or an API call. Calling an undefined function is an error. + + +## Examples + +Here are some example rules which illustrate the syntax and API. + +The replacement for the nag feature: + + rule Nag(before, after) on-modify: + if before.urgency < tasks.max.urgency: + warn ‘You have more urgent tasks’ + + if after.status == 'completed' and before.urgency < (dom.urgency.max - 2.0): + warn 'You have more urgent tasks!' + +Correct commonly misspelled word: + + rule CorrectSpelling(task) on_add: + set task.description = substitute(task.description, 'teh', 'the') + +Abbreviation expansion: + + rule ExpandAbbreviation(task) on_modify: + set task.description = substitute(task.description, '/TW-\d+/', 'https:\/\/github.com\/GothenburgBitFactory\/taskwarrior\/issues\/\1') + +Warn on missing project: + + rule WarnOnMissingProject(task) on_add: + if task.project == ‘’: + warn(‘Project not specified’) + +Color rule: + + rule ColorizeDue(task) color: + if task.due > now: + if task.due < (now + 5d): + return dom.rc.color.due + else: + return dom.rc.color.due.later + +Policy: + + rule policyProject(task) on_add: + if task.project == '': + if rc.default.project == '': + error('You must specify a project') + set task.project = rc.default.project diff --git a/docs/rfcs/sync.md b/docs/rfcs/sync.md new file mode 100644 index 000000000..df5424ab2 --- /dev/null +++ b/docs/rfcs/sync.md @@ -0,0 +1,253 @@ +--- +title: "Taskwarrior - Taskserver Sync Algorithm" +--- + + +# Taskserver Sync Algorithm + +This document describes how task changes are merged by the Taskserver. It does +not describe [the protocol](/docs/design/protocol) used by the Taskserver. + +The Taskserver merges tasks from multiple sources, resulting in conflict- free +syncing of data. The algorithm used to achieve this is simple and effective, +paralleling what SCM systems do to perform a rebase. + + +## Requirements + +In this document, we adopt the convention discussed in Section 1.3.2 of +[RFC1122](https://tools.ietf.org/html/rfc1122#page-16) of using the capitalized +words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the +significance of each particular requirement specified in this document. + +In brief: \"MUST\" (or \"REQUIRED\") means that the item is an absolute +requirement of the specification; \"SHOULD\" (or \"RECOMMENDED\") means there +may exist valid reasons for ignoring this item, but the full implications should +be understood before doing so; and \"MAY\" (or \"OPTIONAL\") means that this +item is optional, and may be omitted without careful consideration. + + +## Problem Definition + +The sync algorithm considers a single task, with multiple changes occurring in +two separate locations that must be resolved. The two locations are the local +machine and the server. This results in two parallel change sequences. + +Examples using multiple clients collapse down to the simple two-branch case +because the clients are merged serially. + + +## Change Sequence + +A sequence of changes to the same task is represented as: + + T0 --> T1 --> T2 + +Although all examples are of the two-branch variety, some involve trivial +branches. Going through these examples will illustrate the algorithm. First the +legend: + + T0 Represents the original task, the base. + T1 Represents the task with a non-trivial set of changes. + T2 Represents the task with further changes. + + +## Deltas + +The transition from T0 \--\> T1 can be seen as a transform applied to T0, +resulting in T1. That transform is the delta (d1) between T0 and T1, which is a +subtractive term: + + d1 = (T1 - T0) + +Therefore: + + T0 --> T1 = T0 + d1 + = T0 + (T1 - T0) + +This states that the transition from T0 to T1 is the application of a delta to +the original, T0, which results in T1. Applying this to the whole change +sequence yields: + + T0 --> T1 --> T2 = T0 + d1 + d2 + = T0 + (T1 - T0) + (T2 - T1) + + +## Use Case Classification + +Because clients sync requests are processed serially, there is no need to +consider the multiple client cases. This means there is only ever the case with +two parallel change sequences = the two branch case. + + +## Two Branch Case + +The two branch case represents changes made to the same task in two locations, +resulting in two deltas that must be applied to the same base. + + T0 --> T1 + T0 --> T2 + +This reduces to a base with two deltas, but the order in which the deltas are +applied is important. For example: + + T0 + d1 + d2 =/= T0 + d2 + d1 + +The application of deltas is not commutative, except in the trivial case where +the two deltas are identical, or the deltas do not overlap. The deltas therefore +need to be applied in the correct sequence. Tasks have metadata that indicates +the last modified time, which dictates the sequence. Assuming d1 occurred before +d2, this neatly collapses down to a single branch sequence: + + T0 + d1 + d2 = T3 + +Note that the result in this case is T3, because it will be neither T1 nor T2, +unless the deltas are identical. + + +## Two Branch, Multiple Changes Case + +The two branch case can be complicated by multiple changes per branch: + + T0 --> T1 --> T3 --> T5 + T0 --> T2 --> T4 + +Note that the numbers were chosen to represent the order in which the changes +were made. First a list of deltas is generated: + + T0 --> T1 = d1 + T1 --> T3 = d3 + T3 --> T5 = d5 + T0 --> T2 = d2 + T0 --> T4 = d4 + + d1, d3, d5, d2, d4 + +Then the deltas are sorted by modified time: + + d1, d2, d3, d4, d5 + +Then epplied to the base, yielding T6: + + T0 + d1 + d2 + d3 + d4 +d5 = T6 + + +## Two Branch Case Example + +Suppose the base task looks like this: + + T0 project:ONE due:tomorrow priority:H +tag1 Original description + +The first branch looks like this: + + T1 project:TWO due:23rd priority:H +tag1 Original description + +The second branch looks like this: + + T2 project:ONE due:tomorrow priority:H +tag1 Modified description + +Delta d1 is: + + T0 project:ONE due:tomorrow priority:H +tag1 Original description + T1 project:TWO due:23rd priority:H +tag1 Original description + ---------------------------------------------------------------------- + d1 project:TWO due:23rd + +Delta d2 is: + + T0 project:ONE due:tomorrow priority:H +tag1 Original description + T2 project:ONE due:tomorrow priority:H +tag1 Modified description + ---------------------------------------------------------------------- + d2 Modified description + +If d1 occurred before d2, the result is: + + T3 = T0 + d1 + d2 + = T0 + (project:TWO due:23rd) + (Modified description) + + T3 = project:TWO due:23rd priority:H +tag1 Modified description + + +## Use Cases + +A range of illustrated use cases, from the trivial to the complex will show the +algorithm in use. + + +## Use Case 1: New Local Task + +Initial state: + + Server: - + Client: T0 + +The server has no data, and so T0 is stored. The result is now: + + Server: T0 + Client: T0 + + +## Use Case 2: Local Change + +Initial state: + + Server: T0 + Client: T0 --> T1 + +The server resolves the change: + + T0 --> T1 = T0 + d1 + = T1 + +T1 is stored. The result is now: + + Server: T0 --> T1 + Client: T1 + + +## Use Case 3: Local and Remote Change + +Initial state: + + Server: T0 --> T1 + Client: T0 --> T2 + +This is the two branch case, and the deltas are generated: + + T0 --> T1 = T0 + d1 + T0 --> T2 = T0 + d2 + +The order of change is determine to be d1, d2, yielding T3: + + T3 = T0 + d1 + d2 + +T3 is stored on the server, and returned to the client. The result is now: + + Server: T0 --> T1 --> T2 --> T3 + Client: T3 + + +## Use Case 4: Multiple Local and Remote Changes + +Initial state: + + Server: T0 --> T1 --> T3 + Client: T0 --> T2 --> T4 + +This is the two branch case, and the deltas are generated: + + T0 --> T1 = T0 + d1 + T1 --> T3 = T0 + d3 + T0 --> T2 = T0 + d2 + T2 --> T4 = T0 + d4 + + d1, d3, d2, d4 + +The order of change is determine to be d1, d2, d3, d4, yielding T5: + + T5 = T0 + d1 + d2 + d3 + d4 + +T5 is stored on the server, and returned to the client. The result is now: + + Server: T0 --> T1 --> T2 --> T3 --> T4 --> T5 + Client: T5 diff --git a/docs/rfcs/task.md b/docs/rfcs/task.md new file mode 100644 index 000000000..ee03738fd --- /dev/null +++ b/docs/rfcs/task.md @@ -0,0 +1,761 @@ +--- +title: "Taskwarrior - Taskwarrior JSON Format" +--- + + +# Taskwarrior JSON Format + +When Taskwarrior exchanges data, it uses [JSON](https://www.json.org/). This +document describes the structure and semantics for tasks exported from +Taskwarrior, imported to Taskwarrior, or synced with the Taskserver. + +Any client of the Taskserver will need to communicate task information. This +document describes the format of a single task. It does not describe the +communication and sync protocol between client and server. + +This document is subject to change. The data attributes are also subject to +change. + + +## Requirements + +In this document, we adopt the convention discussed in Section 1.3.2 of +[RFC1122](https://tools.ietf.org/html/rfc1122#page-16) of using the capitalized +words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the +significance of each particular requirement specified in this document. + +In brief: \"MUST\" (or \"REQUIRED\") means that the item is an absolute +requirement of the specification; \"SHOULD\" (or \"RECOMMENDED\") means there +may exist valid reasons for ignoring this item, but the full implications should +be understood before doing so; and \"MAY\" (or \"OPTIONAL\") means that this +item is optional, and may be omitted without careful consideration. + + +## General Format + +The format is JSON, specifically a JSON object as a single line of text, +terminated by a newline (U+000D). + +The JSON looks like this: + + {"description":"One two three","status":"pending", ... } + +While this is not a valid task (there are missing fields), the format is +illustrated. + +All attribute names are quoted with \" (U+0022). A name will always have a +corresponding value, and if a value is blank, then the name/value pair is +omitted from the line. Newline characters are not permitted within the value, +meaning that a task consists of a single line of text. + +All data is UTF8. + + +## Data Types + +There are five data types used in the task format. + + +## Data Type: String + +Strings may consist of any UTF8 encoded characters. + + +## Data Type: Fixed String + +A fixed string is one value from a set of acceptable values, such as a priority +level, where the values may only be \"\", \"L\", \"M\" or \"H\". + + +## Data Type: UUID + +A UUID is a 32-hex-character lower case string, formatted in this way: + + xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +An example: + + 296d835e-8f85-4224-8f36-c612cad1b9f8 + + +## Data Type: Integer + +Integers are rendered in a simple fashion: + + 123 + + +## Data Type: Date + +Dates are rendered in ISO 8601 combined date and time in UTC format using the +template: + + YYYYMMDDTHHMMSSZ + +An example: + + 20120110T231200Z + +No other formats are supported. + + +## Data Type: Duration + +Duration values represent a time period. They take the form: + + [[] ] + +Some examples include: + +- -3days +- annual +- 4hrs + +The supported units are: + +- annual +- biannual +- bimonthly +- biweekly +- biyearly +- daily +- days +- day +- d +- fortnight +- hours +- hour +- hrs +- hr +- h +- minutes +- mins +- min +- monthly +- months +- month +- mnths +- mths +- mth +- mos +- mo +- quarterly +- quarters +- qrtrs +- qtrs +- qtr +- q +- seconds +- secs +- sec +- s +- semiannual +- sennight +- weekdays +- weekly +- weeks +- week +- wks +- wk +- w +- yearly +- years +- year +- yrs +- yr +- y + +Note that some values lack precision, for example \"2q\" means two quarters, or +half a year. + +Note that not all combinations of and make sense, for example \"3annual\" makes +no sense, but evaluates to \"3years\". + + +## The Attributes + +Here are the standard attributes that may comprise a task: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType
statusString
uuidUUID
entryDate
descriptionString
startDate
endDate
dueDate
untilDate
waitDate
modifiedDate
scheduledDate
recurString
maskString
imaskInteger
parentUUID
projectString
priorityString
dependsString
tags *String
annotation *String
(UDA)?
+ +\* Both tags and annotations are lists of strings and objects. + +Any UDA fields are assumed to be of type string. + +There are other forms, which are conditional upon the state of a task: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Status ValuePendingDeletedCompletedWaitingRecurring ParentRecurring Child
statusReqdReqdReqdReqdReqdReqd
uuidReqdReqdReqdReqdReqdReqd
entryReqdReqdReqdReqdReqdReqd
descriptionReqdReqdReqdReqdReqdReqd
startOptOptOptOptOptOpt
endReqdReqd
dueOptOptOptOptReqdOpt
untilOptOptOptOptOptOpt
scheduledOptOptOptOptOptOpt
waitReqd
recurReqdReqd
maskIntrn
imaskIntrn
parentReqd
annotationOptOptOptOptOptOpt
projectOptOptOptOptOptOpt
tagsOptOptOptOptOptOpt
priorityOptOptOptOptOptOpt
dependsOptOptOptOptOptOpt
modifiedIntrnIntrnIntrnIntrnIntrnIntrn
UDAOptOptOptOptOptOpt
+ +(Legend: Reqd = required, Opt = optional, Intrn = Internally generated) + +All tasks have four required fields. There are other states in which a task may +exist, and the requirements change. At a minimum, a valid task contains: + +- uuid +- status +- entry +- description + +*Deleted*\ +A deleted task MUST also have \"status\":\"deleted\", an \"end\" date and a +\"modified\" date. + +*Completed*\ +A completed task MUST also have \"status\":\"completed\", an \"end\" date and a +\"modified\" date. + +*Waiting*\ +A waiting task MUST also have \"status\":\"waiting\" and a \"wait\" date. The +task is hidden from the user, until that \"wait\" date has passed, whereupon the +status reverts to \"pending\", and the \"wait\" date is removed. + +*Recurring Parent*\ +When a recurring task is entered, it MUST have \"status\":\"recurring\", a +\"recur\" period and a \"due\" date. It MAY also have an \"until\" date. +Recurring parent tasks are hidden from the user. + +*Recurring Child*\ +A recurring child task is not created by the user, but is cloned from the +recurring parent task by the Taskserver. It may be modified by the user. On +completion, there is special handling to be done. See section 3.11. + + +## Additional Attributes + +There MAY be other fields than those listed above in a task definition. Such +fields MUST be preserved intact by any client, which means that if a task is +downloaded that contains an unrecognized field, that field MUST not be modified, +and MUST continue to exist in the task.. + +User Defined Attributes (UDAs) are additional fields. + + +## Attribute Details + +The individual fields convey important information about a task, and in some +cases work only in collusion with other fields. All such details are listed +here. + + +## Attribute: status + +The status field describes the state of the task, which may ONLY be one of these +literal strings: + + "status":"pending" + "status":"deleted" + "status":"completed" + "status":"waiting" + "status":"recurring" + +A pending task is a task that has not yet been completed or deleted. This is the +typical state for a task. + +A deleted task is one that has been removed from the pending state, and MUST +have an \"end\" field specified. Given the required \"entry\" and \"end\" field, +it can be determined how long the task was pending. + +A completed task is one that has been removed from the pending state by +completion, and MUST have an \"end\" field specified. Given the required +\"entry\" and \"end\" fields, it can be determine how long the task was pending. + +A waiting task is ostensibly a pending task that has been hidden from typical +view, and MUST have a \"wait\" field containing the date when the task is +automatically returned to the pending state. If a client sees a task that is in +the waiting state, and the \"wait\" field is earlier than the current date and +time, the client MUST remove the \"wait\" field and set the \"status\" field to +\"pending\". + +A recurring task is essentially a parent template task from which child tasks +are cloned. The parent remains hidden from view, and contains a \"mask\" field +that represents the recurrences. Each cloned child task has an \"imask\" field +that indexes into the parent \"mask\" field, as well as a \"parent\" field that +lists the UUID of the parent. + + +## Attribute: uuid + +When a task is created, it MUST be assigned a new UUID by the client. Once +assigned, a UUID field MUST NOT be modified. UUID fields are permanent. + + +## Attribute: entry + +When a task is created, it MUST be assigned an \"entry\" date by the client. +This is the creation date of the task. + + +## Attribute: description + +When a task is created, it MUST have a \"description\" field value, which +contains UTF8 characters. A \"description\" field may not contain newline +characters, but may contain other characters, properly escaped. See + for details. + + +## Attribute: start + +To indicate that a task is being worked on, it MAY be assigned a \"start\" +field. Such a task is then considered Active. + + +## Attribute: end + +When a task is deleted or completed, is MUST be assigned an \"end\" field. It is +not valid for a task to have an \"end\" field unless the status is also +\"completed\" or \"deleted\". If a completed task is restored to the \"pending\" +state, the \"end\" field is removed. + + +## Attribute: due + +A task MAY have a \"due\" field, which indicates when the task should be +completed. + + +## Attribute: until + +A recurring task MAY have an \"until\" field, which is the date after which no +more recurring tasks should be generated. At that time, the parent recurring +task is set to \"completed\". + + +## Attribute: wait + +A task MAY have a \"wait\" field date, in conjunction with a \"status\" of +\"waiting\". A waiting task is one that is not typically shown on reports until +it is past the wait date. + +An example of this is a birthday reminder. A task may be entered for a birthday +reminder in 10 months time, but can have a \"wait\" date 9 months from now, +which means the task remains hidden until 1 month before the due date. This +prevents long-term tasks from cluttering reports until they become relevant. + + +## Attribute: recur + +The \"recur\" field is for recurring tasks, and specifies the period between +child tasks, in the form of a duration value. The value is kept in the raw state +(such as \"3wks\") as a string, so that it may be evaluated each time it is +needed. + + +## Attribute: mask + +A parent recurring task has a \"mask\" field that is an array of child status +indicators. Suppose a task is created that is due every week for a month. The +\"mask\" field will look like: + + "----" + +This mask has four slots, indicating that there are four child tasks, and each +slot indicates, in this case, that the child tasks are pending (\"-\"). The +possible slot indicators are: + +* `-` - Pending +* `+` - Completed +* `X` - Deleted +* `W` - Waiting + +Suppose the first three tasks has been completed, the mask would look like this: + + "+++-" + +If there were only three indicators in the mask: + + "+-+" + +This would indicate that the second task is pending, the first and third are +complete, and the fourth has not yet been generated. + + +## Attribute: imask + +Child recurring tasks have an \"imask\" field instead of a \"mask\" field like +their parent. The \"imask\" field is a zero-based integer offset into the +\"mask\" field of the parent. + +If a child task is completed, one of the changes that MUST occur is to look up +the parent task, and using \"imask\" set the \"mask\" of the parent to the +correct indicator. This prevents recurring tasks from being generated twice. + + +## Attribute: parent + +A recurring task instance MUST have a \"parent\" field, which is the UUID of the +task that has \"status\" of \"recurring\". This linkage between tasks, +established using \"parent\", \"mask\" and \"imask\" is used to track the need +to generate more recurring tasks. + + +## Attribute: annotation\_\... + +Annotations are strings with timestamps. Each annotation itself has an \"entry\" +field and a \"description\" field, similar to the task itself. Annotations form +an array named \"annotations\". For example (lines broken for clarity): + + "annotations":[ + {"entry":"20120110T234212Z","description":"Remember to get the mail"}, + {"entry":"20120110T234559Z","description":"Pay the bills"} + ] + + +## Attribute: project + +A project is a single string. For example: + + "project":"Personal Taxes" + +Note that projects receive special handling, so that when a \".\" (U+002E) is +used, it implies a hierarchy, which means the following two projects: + + "Home.Kitchen" + "Home.Garden" + +are both considered part of the \"Home\" project. + + +## Attribute: tags + +The \"tags\" field is an array of string, where each string is a single word +containing no spaces. For example: + + "tags":["home","garden"] + + +## Attribute: priority + +The \"priority\" field, if present, MAY contain one of the following strings: + + "priority":"H" + "priority":"M" + "priority":"L" + +These represent High, Medium and Low priorities. An absent priority field +indicates no priority. + + +## Attribute: depends + +The \"depends\" field is a string containing a comma-separated unique set of +UUIDs. If task 2 depends on task 1, then it is task 1 that must be completed +first. Task 1 is considered a \"blocking\" tasks, and task 2 is considered a +\"blocked\" task. For example: + + "depends":",, ..." + +Note that in a future version of this specification, this will be changed to a +JSON array of strings, like the \"tags\" field. + + +## Attribute: modified + +A task MUST have a \"modified\" field set if it is modified. This field is of +type \"date\", and is used as a reference when merging tasks. + + +## Attribute: scheduled + +A task MAY have a \"scheduled\" field, which indicates when the task should be +available to start. A task that has passed its \"scheduled\" data is said to be +\"ready\". + + +## User Defined Attributes + +A User Defined Attribute (UDA) is a field that is defined via configuration. +Given that the configuration is not present in the JSON format of a task, any +fields that are not recognized are to be treated as UDAs. This means that if a +task contains a UDA, unless the meaning of it is understood, it MUST be +preserved. + +UDAs may have one of four types: string, numeric, date and duration. + diff --git a/docs/rfcs/week.png b/docs/rfcs/week.png new file mode 100644 index 000000000..d6b320443 Binary files /dev/null and b/docs/rfcs/week.png differ diff --git a/docs/rfcs/workweek.md b/docs/rfcs/workweek.md new file mode 100644 index 000000000..1de1ed36e --- /dev/null +++ b/docs/rfcs/workweek.md @@ -0,0 +1,35 @@ +--- +title: "Taskwarrior - Work Week Support" +--- + +## Work in Progress + +This design document is a work in progress, and subject to change. Once +finalized, the feature will be scheduled for an upcoming release. + + +# Work Week Support + +Taskwarrior supports the idea that a week starts on either a Sunday or a Monday, +as determined by configuration. This was added eight years ago, simply for +display purposes in the `calendar` report. Since then its use has propagated and +it influences the `sow` date reference.0 + +Further requests have been made to make this more flexible, so that the notion +of \'weekend\' can be defined. Furthermore, the idea that every week has a +weekend has also been questioned. + +It has become clear that a `weekstart` setting, and the notion of a weekend are +no longer useful. + + +## Proposed Support + +One option is to allow the user to completely define a work week in the +following way: + + workweek=1,2,3,4,5 + +With Sunday as day zero, this states that the work week is the typical Monday - +Friday. From this setting, the meaning of `soww` and `eoww` can be determined, +as well as `recur:weekday`. diff --git a/docs/rfcs/year.png b/docs/rfcs/year.png new file mode 100644 index 000000000..a8e54d649 Binary files /dev/null and b/docs/rfcs/year.png differ